blob: 3fddd2829b96cc3b70979914b9d1f8ee30780d29 [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>
SathishKumar Manib357a772012-09-25 23:28:29 -070025#include "AudioUtil.h"
Iliyan Malchev4765c432012-06-11 14:36:16 -070026#include "AudioHardwareALSA.h"
27#include <media/AudioRecord.h>
SathishKumar Mani5ff7a022012-09-14 11:36:35 -070028#include <dlfcn.h>
Ajay Dudani9746c472012-06-18 16:01:16 -070029#ifdef QCOM_CSDCLIENT_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -070030extern "C" {
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
SathishKumar Manib357a772012-09-25 23:28:29 -070050#define MAX_HDMI_CHANNEL_CNT 6
Iliyan Malchev4765c432012-06-11 14:36:16 -070051
52namespace android_audio_legacy
53{
54
55static int s_device_open(const hw_module_t*, const char*, hw_device_t**);
56static int s_device_close(hw_device_t*);
57static status_t s_init(alsa_device_t *, ALSAHandleList &);
58static status_t s_open(alsa_handle_t *);
59static status_t s_close(alsa_handle_t *);
60static status_t s_standby(alsa_handle_t *);
61static status_t s_route(alsa_handle_t *, uint32_t, int);
62static status_t s_start_voice_call(alsa_handle_t *);
63static status_t s_start_voip_call(alsa_handle_t *);
64static status_t s_start_fm(alsa_handle_t *);
65static void s_set_voice_volume(int);
66static void s_set_voip_volume(int);
67static void s_set_mic_mute(int);
68static void s_set_voip_mic_mute(int);
69static void s_set_voip_config(int, int);
70static status_t s_set_fm_vol(int);
71static void s_set_btsco_rate(int);
72static status_t s_set_lpa_vol(int);
73static void s_enable_wide_voice(bool flag);
74static void s_enable_fens(bool flag);
75static void s_set_flags(uint32_t flags);
76static status_t s_set_compressed_vol(int);
77static void s_enable_slow_talk(bool flag);
78static void s_set_voc_rec_mode(uint8_t mode);
79static void s_set_volte_mic_mute(int state);
80static void s_set_volte_volume(int vol);
ty.lee74060de2012-08-02 00:47:00 +090081#ifdef SEPERATED_AUDIO_INPUT
82static void s_setInput(int);
83
84static int input_source;
85#endif
SathishKumar Mani5ff7a022012-09-14 11:36:35 -070086#ifdef QCOM_CSDCLIENT_ENABLED
87static void s_set_csd_handle(void*);
88#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -070089
90static char mic_type[25];
91static char curRxUCMDevice[50];
92static char curTxUCMDevice[50];
93static int fluence_mode;
94static int fmVolume;
ty.lee924f7982012-08-01 23:15:30 +090095#ifdef USES_FLUENCE_INCALL
96static uint32_t mDevSettingsFlag = TTY_OFF | DMIC_FLAG;
97#else
Iliyan Malchev4765c432012-06-11 14:36:16 -070098static uint32_t mDevSettingsFlag = TTY_OFF;
ty.lee924f7982012-08-01 23:15:30 +090099#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700100static int btsco_samplerate = 8000;
101static bool pflag = false;
102static ALSAUseCaseList mUseCaseList;
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700103static void *csd_handle;
Iliyan Malchev4765c432012-06-11 14:36:16 -0700104
105static hw_module_methods_t s_module_methods = {
106 open : s_device_open
107};
108
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700109extern "C" {
110hw_module_t HAL_MODULE_INFO_SYM = {
Iliyan Malchev4765c432012-06-11 14:36:16 -0700111 tag : HARDWARE_MODULE_TAG,
112 version_major : 1,
113 version_minor : 0,
114 id : ALSA_HARDWARE_MODULE_ID,
115 name : "QCOM ALSA module",
116 author : "QuIC Inc",
117 methods : &s_module_methods,
118 dso : 0,
119 reserved : {0,},
120};
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700121}
Iliyan Malchev4765c432012-06-11 14:36:16 -0700122
123static int s_device_open(const hw_module_t* module, const char* name,
124 hw_device_t** device)
125{
126 char value[128];
127 alsa_device_t *dev;
128 dev = (alsa_device_t *) malloc(sizeof(*dev));
129 if (!dev) return -ENOMEM;
130
131 memset(dev, 0, sizeof(*dev));
132
133 /* initialize the procs */
134 dev->common.tag = HARDWARE_DEVICE_TAG;
135 dev->common.version = 0;
136 dev->common.module = (hw_module_t *) module;
137 dev->common.close = s_device_close;
138 dev->init = s_init;
139 dev->open = s_open;
140 dev->close = s_close;
141 dev->route = s_route;
142 dev->standby = s_standby;
143 dev->startVoiceCall = s_start_voice_call;
144 dev->startVoipCall = s_start_voip_call;
145 dev->startFm = s_start_fm;
146 dev->setVoiceVolume = s_set_voice_volume;
147 dev->setVoipVolume = s_set_voip_volume;
148 dev->setMicMute = s_set_mic_mute;
149 dev->setVoipMicMute = s_set_voip_mic_mute;
150 dev->setVoipConfig = s_set_voip_config;
151 dev->setFmVolume = s_set_fm_vol;
152 dev->setBtscoRate = s_set_btsco_rate;
153 dev->setLpaVolume = s_set_lpa_vol;
154 dev->enableWideVoice = s_enable_wide_voice;
155 dev->enableFENS = s_enable_fens;
156 dev->setFlags = s_set_flags;
157 dev->setCompressedVolume = s_set_compressed_vol;
158 dev->enableSlowTalk = s_enable_slow_talk;
159 dev->setVocRecMode = s_set_voc_rec_mode;
160 dev->setVoLTEMicMute = s_set_volte_mic_mute;
161 dev->setVoLTEVolume = s_set_volte_volume;
ty.lee74060de2012-08-02 00:47:00 +0900162#ifdef SEPERATED_AUDIO_INPUT
163 dev->setInput = s_setInput;
164#endif
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700165#ifdef QCOM_CSDCLIENT_ENABLED
166 dev->setCsdHandle = s_set_csd_handle;
167#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700168 *device = &dev->common;
169
170 property_get("persist.audio.handset.mic",value,"0");
171 strlcpy(mic_type, value, sizeof(mic_type));
172 property_get("persist.audio.fluence.mode",value,"0");
173 if (!strcmp("broadside", value)) {
174 fluence_mode = FLUENCE_MODE_BROADSIDE;
175 } else {
176 fluence_mode = FLUENCE_MODE_ENDFIRE;
177 }
178 strlcpy(curRxUCMDevice, "None", sizeof(curRxUCMDevice));
179 strlcpy(curTxUCMDevice, "None", sizeof(curTxUCMDevice));
SathishKumar Mani9efed762012-09-18 18:52:48 -0700180 ALOGV("ALSA module opened");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700181
182 return 0;
183}
184
185static int s_device_close(hw_device_t* device)
186{
187 free(device);
188 device = NULL;
189 return 0;
190}
191
192// ----------------------------------------------------------------------------
193
194static const int DEFAULT_SAMPLE_RATE = ALSA_DEFAULT_SAMPLE_RATE;
195
196static void switchDevice(alsa_handle_t *handle, uint32_t devices, uint32_t mode);
197static char *getUCMDevice(uint32_t devices, int input, char *rxDevice);
198static void disableDevice(alsa_handle_t *handle);
199int getUseCaseType(const char *useCase);
200
201static int callMode = AudioSystem::MODE_NORMAL;
202// ----------------------------------------------------------------------------
203
204bool platform_is_Fusion3()
205{
206 char platform[128], baseband[128];
207 property_get("ro.board.platform", platform, "");
208 property_get("ro.baseband", baseband, "");
209 if (!strcmp("msm8960", platform) && !strcmp("mdm", baseband))
210 return true;
211 else
212 return false;
213}
214
215int deviceName(alsa_handle_t *handle, unsigned flags, char **value)
216{
217 int ret = 0;
218 char ident[70];
219
220 if (flags & PCM_IN) {
221 strlcpy(ident, "CapturePCM/", sizeof(ident));
222 } else {
223 strlcpy(ident, "PlaybackPCM/", sizeof(ident));
224 }
225 strlcat(ident, handle->useCase, sizeof(ident));
226 ret = snd_use_case_get(handle->ucMgr, ident, (const char **)value);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700227 ALOGD("Device value returned is %s", (*value));
Iliyan Malchev4765c432012-06-11 14:36:16 -0700228 return ret;
229}
230
SathishKumar Manib357a772012-09-25 23:28:29 -0700231status_t setHDMIChannelCount()
232{
233 status_t err = NO_ERROR;
234 int channel_count = 0;
235 const char *channel_cnt_str = NULL;
236 EDID_AUDIO_INFO info = { 0 };
237
238 ALSAControl control("/dev/snd/controlC0");
239 if (AudioUtil::getHDMIAudioSinkCaps(&info)) {
240 for (int i = 0; i < info.nAudioBlocks && i < MAX_EDID_BLOCKS; i++) {
241 if (info.AudioBlocksArray[i].nChannels > channel_count &&
242 info.AudioBlocksArray[i].nChannels <= MAX_HDMI_CHANNEL_CNT) {
243 channel_count = info.AudioBlocksArray[i].nChannels;
244 }
245 }
246 }
247
248 switch (channel_count) {
249 case 6: channel_cnt_str = "Six"; break;
250 case 5: channel_cnt_str = "Five"; break;
251 case 4: channel_cnt_str = "Four"; break;
252 case 3: channel_cnt_str = "Three"; break;
253 default: channel_cnt_str = "Two"; break;
254 }
255 ALOGD("HDMI channel count: %s", channel_cnt_str);
256 control.set("HDMI_RX Channels", channel_cnt_str);
257
258 return err;
259}
260
Iliyan Malchev4765c432012-06-11 14:36:16 -0700261status_t setHardwareParams(alsa_handle_t *handle)
262{
263 struct snd_pcm_hw_params *params;
264 unsigned long bufferSize, reqBuffSize;
265 unsigned int periodTime, bufferTime;
266 unsigned int requestedRate = handle->sampleRate;
267 int status = 0;
268 int channels = handle->channels;
269 snd_pcm_format_t format = SNDRV_PCM_FORMAT_S16_LE;
270
271 params = (snd_pcm_hw_params*) calloc(1, sizeof(struct snd_pcm_hw_params));
272 if (!params) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700273 ALOGE("Failed to allocate ALSA hardware parameters!");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700274 return NO_INIT;
275 }
276
277 reqBuffSize = handle->bufferSize;
Iliyan Malchev4113f342012-06-11 14:39:47 -0700278 ALOGD("setHardwareParams: reqBuffSize %d channels %d sampleRate %d",
Iliyan Malchev4765c432012-06-11 14:36:16 -0700279 (int) reqBuffSize, handle->channels, handle->sampleRate);
280
Ajay Dudani9746c472012-06-18 16:01:16 -0700281#ifdef QCOM_SSR_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700282 if (channels == 6) {
283 if (!strncmp(handle->useCase, SND_USE_CASE_VERB_HIFI_REC, strlen(SND_USE_CASE_VERB_HIFI_REC))
284 || !strncmp(handle->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, strlen(SND_USE_CASE_MOD_CAPTURE_MUSIC))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700285 ALOGV("HWParams: Use 4 channels in kernel for 5.1(%s) recording ", handle->useCase);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700286 channels = 4;
Iliyan Malchev4765c432012-06-11 14:36:16 -0700287 }
288 }
289#endif
290
291 param_init(params);
292 param_set_mask(params, SNDRV_PCM_HW_PARAM_ACCESS,
293 SNDRV_PCM_ACCESS_RW_INTERLEAVED);
294 if (handle->format != SNDRV_PCM_FORMAT_S16_LE) {
Ajay Dudani9746c472012-06-18 16:01:16 -0700295 if (handle->format == AudioSystem::AMR_NB
296 || handle->format == AudioSystem::AMR_WB
297#ifdef QCOM_QCHAT_ENABLED
298 || handle->format == AudioSystem::EVRC
299 || handle->format == AudioSystem::EVRCB
300 || handle->format == AudioSystem::EVRCWB
301#endif
302 )
Iliyan Malchev4765c432012-06-11 14:36:16 -0700303 format = SNDRV_PCM_FORMAT_SPECIAL;
304 }
305 param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
306 format);
307 param_set_mask(params, SNDRV_PCM_HW_PARAM_SUBFORMAT,
308 SNDRV_PCM_SUBFORMAT_STD);
SathishKumar Mani77780382012-09-21 20:58:33 -0700309 param_set_int(params, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, reqBuffSize);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700310 param_set_int(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS, 16);
311 param_set_int(params, SNDRV_PCM_HW_PARAM_FRAME_BITS,
312 channels * 16);
313 param_set_int(params, SNDRV_PCM_HW_PARAM_CHANNELS,
314 channels);
315 param_set_int(params, SNDRV_PCM_HW_PARAM_RATE, handle->sampleRate);
316 param_set_hw_refine(handle->handle, params);
317
318 if (param_set_hw_params(handle->handle, params)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700319 ALOGE("cannot set hw params");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700320 return NO_INIT;
321 }
322 param_dump(params);
323
324 handle->handle->buffer_size = pcm_buffer_size(params);
325 handle->handle->period_size = pcm_period_size(params);
326 handle->handle->period_cnt = handle->handle->buffer_size/handle->handle->period_size;
Iliyan Malchev4113f342012-06-11 14:39:47 -0700327 ALOGD("setHardwareParams: buffer_size %d, period_size %d, period_cnt %d",
Iliyan Malchev4765c432012-06-11 14:36:16 -0700328 handle->handle->buffer_size, handle->handle->period_size,
329 handle->handle->period_cnt);
330 handle->handle->rate = handle->sampleRate;
331 handle->handle->channels = handle->channels;
332 handle->periodSize = handle->handle->period_size;
333 if (strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_REC) &&
334 strcmp(handle->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC) &&
335 (6 != handle->channels)) {
336 //Do not update buffersize for 5.1 recording
337 handle->bufferSize = handle->handle->period_size;
338 }
339
340 return NO_ERROR;
341}
342
343status_t setSoftwareParams(alsa_handle_t *handle)
344{
345 struct snd_pcm_sw_params* params;
346 struct pcm* pcm = handle->handle;
347
348 unsigned long periodSize = pcm->period_size;
349 int channels = handle->channels;
350
351 params = (snd_pcm_sw_params*) calloc(1, sizeof(struct snd_pcm_sw_params));
352 if (!params) {
353 LOG_ALWAYS_FATAL("Failed to allocate ALSA software parameters!");
354 return NO_INIT;
355 }
356
Ajay Dudani9746c472012-06-18 16:01:16 -0700357#ifdef QCOM_SSR_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700358 if (channels == 6) {
359 if (!strncmp(handle->useCase, SND_USE_CASE_VERB_HIFI_REC, strlen(SND_USE_CASE_VERB_HIFI_REC))
360 || !strncmp(handle->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, strlen(SND_USE_CASE_MOD_CAPTURE_MUSIC))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700361 ALOGV("SWParams: Use 4 channels in kernel for 5.1(%s) recording ", handle->useCase);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700362 channels = 4;
363 }
364 }
365#endif
366
367 // Get the current software parameters
368 params->tstamp_mode = SNDRV_PCM_TSTAMP_NONE;
369 params->period_step = 1;
370 if(((!strcmp(handle->useCase,SND_USE_CASE_MOD_PLAY_VOIP)) ||
371 (!strcmp(handle->useCase,SND_USE_CASE_VERB_IP_VOICECALL)))){
Iliyan Malchev4113f342012-06-11 14:39:47 -0700372 ALOGV("setparam: start & stop threshold for Voip ");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700373 params->avail_min = handle->channels - 1 ? periodSize/4 : periodSize/2;
374 params->start_threshold = periodSize/2;
375 params->stop_threshold = INT_MAX;
376 } else {
377 params->avail_min = periodSize/2;
378 params->start_threshold = channels * (periodSize/4);
379 params->stop_threshold = INT_MAX;
380 }
381 params->silence_threshold = 0;
382 params->silence_size = 0;
383
384 if (param_set_sw_params(handle->handle, params)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700385 ALOGE("cannot set sw params");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700386 return NO_INIT;
387 }
388 return NO_ERROR;
389}
390
391void switchDevice(alsa_handle_t *handle, uint32_t devices, uint32_t mode)
392{
393 const char **mods_list;
394 use_case_t useCaseNode;
395 unsigned usecase_type = 0;
396 bool inCallDevSwitch = false;
397 char *rxDevice, *txDevice, ident[70], *use_case = NULL;
398 int err = 0, index, mods_size;
399 int rx_dev_id, tx_dev_id;
SathishKumar Mani9efed762012-09-18 18:52:48 -0700400 ALOGD("%s: device %d mode:%d", __FUNCTION__, devices, mode);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700401
402 if ((mode == AudioSystem::MODE_IN_CALL) || (mode == AudioSystem::MODE_IN_COMMUNICATION)) {
403 if ((devices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) ||
404 (devices & AudioSystem::DEVICE_IN_WIRED_HEADSET)) {
405 devices = devices | (AudioSystem::DEVICE_OUT_WIRED_HEADSET |
406 AudioSystem::DEVICE_IN_WIRED_HEADSET);
407 } else if (devices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE) {
408 devices = devices | (AudioSystem::DEVICE_OUT_WIRED_HEADPHONE |
409 AudioSystem::DEVICE_IN_BUILTIN_MIC);
SathishKumar Manic669c272012-09-21 20:12:08 -0700410 } else if (devices & AudioSystem::DEVICE_IN_BUILTIN_MIC) {
411 if (mode == AudioSystem::MODE_IN_CALL) {
412 devices |= AudioSystem::DEVICE_OUT_EARPIECE;
413 }
414 } else if (devices & AudioSystem::DEVICE_OUT_EARPIECE) {
415 devices = devices | AudioSystem::DEVICE_IN_BUILTIN_MIC;
Iliyan Malchev4765c432012-06-11 14:36:16 -0700416 } else if (devices & AudioSystem::DEVICE_OUT_SPEAKER) {
ty.lee10dfa852012-08-01 21:09:45 +0900417 devices = devices | (AudioSystem::DEVICE_IN_BACK_MIC |
Iliyan Malchev4765c432012-06-11 14:36:16 -0700418 AudioSystem::DEVICE_OUT_SPEAKER);
419 } else if ((devices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO) ||
420 (devices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET) ||
421 (devices & AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET)) {
422 devices = devices | (AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET |
423 AudioSystem::DEVICE_OUT_BLUETOOTH_SCO);
Ajay Dudani9746c472012-06-18 16:01:16 -0700424#ifdef QCOM_ANC_HEADSET_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700425 } else if ((devices & AudioSystem::DEVICE_OUT_ANC_HEADSET) ||
426 (devices & AudioSystem::DEVICE_IN_ANC_HEADSET)) {
427 devices = devices | (AudioSystem::DEVICE_OUT_ANC_HEADSET |
428 AudioSystem::DEVICE_IN_ANC_HEADSET);
429 } else if (devices & AudioSystem::DEVICE_OUT_ANC_HEADPHONE) {
430 devices = devices | (AudioSystem::DEVICE_OUT_ANC_HEADPHONE |
431 AudioSystem::DEVICE_IN_BUILTIN_MIC);
432#endif
433 } else if (devices & AudioSystem::DEVICE_OUT_AUX_DIGITAL) {
Sungmin Choi6ebf0aa2012-09-28 16:09:12 -0700434 if (mode == AudioSystem::MODE_IN_CALL)
435 devices = devices | (AudioSystem::DEVICE_IN_BACK_MIC |
436 AudioSystem::DEVICE_OUT_SPEAKER);
437 else
438 devices = devices | (AudioSystem::DEVICE_OUT_AUX_DIGITAL |
439 AudioSystem::DEVICE_IN_BACK_MIC);
Ajay Dudani9746c472012-06-18 16:01:16 -0700440#ifdef QCOM_PROXY_DEVICE_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700441 } else if ((devices & AudioSystem::DEVICE_OUT_PROXY) ||
442 (devices & AudioSystem::DEVICE_IN_PROXY)) {
443 devices = devices | (AudioSystem::DEVICE_OUT_PROXY |
444 AudioSystem::DEVICE_IN_PROXY);
445#endif
446 }
447 }
Ajay Dudani9746c472012-06-18 16:01:16 -0700448#ifdef QCOM_SSR_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700449 if ((devices & AudioSystem::DEVICE_IN_BUILTIN_MIC) && ( 6 == handle->channels)) {
450 if (!strncmp(handle->useCase, SND_USE_CASE_VERB_HIFI_REC, strlen(SND_USE_CASE_VERB_HIFI_REC))
451 || !strncmp(handle->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, strlen(SND_USE_CASE_MOD_CAPTURE_MUSIC))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700452 ALOGV(" switchDevice , use ssr devices for channels:%d usecase:%s",handle->channels,handle->useCase);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700453 s_set_flags(SSRQMIC_FLAG);
454 }
455 }
456#endif
457
458 rxDevice = getUCMDevice(devices & AudioSystem::DEVICE_OUT_ALL, 0, NULL);
459 txDevice = getUCMDevice(devices & AudioSystem::DEVICE_IN_ALL, 1, rxDevice);
460
Iliyan Malchev4765c432012-06-11 14:36:16 -0700461 if ((rxDevice != NULL) && (txDevice != NULL)) {
462 if (((strncmp(rxDevice, curRxUCMDevice, MAX_STR_LEN)) ||
SathishKumar Manic669c272012-09-21 20:12:08 -0700463 (strncmp(txDevice, curTxUCMDevice, MAX_STR_LEN))) &&
464 ((mode == AudioSystem::MODE_IN_CALL) ||
465 (mode == AudioSystem::MODE_IN_COMMUNICATION)))
Iliyan Malchev4765c432012-06-11 14:36:16 -0700466 inCallDevSwitch = true;
467 }
Ajay Dudani91bf8912012-08-20 18:48:13 -0700468
469#ifdef QCOM_CSDCLIENT_ENABLED
SathishKumar Manic669c272012-09-21 20:12:08 -0700470 if (platform_is_Fusion3() && (inCallDevSwitch == true)) {
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700471 if (csd_disable_device == NULL) {
472 ALOGE("dlsym:Error:%s Loading csd_client_disable_device", dlerror());
473 } else {
474 err = csd_disable_device();
475 if (err < 0)
476 {
477 ALOGE("csd_client_disable_device, failed, error %d", err);
478 }
Ajay Dudani91bf8912012-08-20 18:48:13 -0700479 }
480 }
481#endif
482
Iliyan Malchev4765c432012-06-11 14:36:16 -0700483 snd_use_case_get(handle->ucMgr, "_verb", (const char **)&use_case);
484 mods_size = snd_use_case_get_list(handle->ucMgr, "_enamods", &mods_list);
485 if (rxDevice != NULL) {
486 if ((strncmp(curRxUCMDevice, "None", 4)) &&
487 ((strncmp(rxDevice, curRxUCMDevice, MAX_STR_LEN)) || (inCallDevSwitch == true))) {
488 if ((use_case != NULL) && (strncmp(use_case, SND_USE_CASE_VERB_INACTIVE,
489 strlen(SND_USE_CASE_VERB_INACTIVE)))) {
490 usecase_type = getUseCaseType(use_case);
491 if (usecase_type & USECASE_TYPE_RX) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700492 ALOGD("Deroute use case %s type is %d\n", use_case, usecase_type);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700493 strlcpy(useCaseNode.useCase, use_case, MAX_STR_LEN);
494 snd_use_case_set(handle->ucMgr, "_verb", SND_USE_CASE_VERB_INACTIVE);
495 mUseCaseList.push_front(useCaseNode);
496 }
497 }
498 if (mods_size) {
499 for(index = 0; index < mods_size; index++) {
500 usecase_type = getUseCaseType(mods_list[index]);
501 if (usecase_type & USECASE_TYPE_RX) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700502 ALOGD("Deroute use case %s type is %d\n", mods_list[index], usecase_type);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700503 strlcpy(useCaseNode.useCase, mods_list[index], MAX_STR_LEN);
504 snd_use_case_set(handle->ucMgr, "_dismod", mods_list[index]);
505 mUseCaseList.push_back(useCaseNode);
506 }
507 }
508 }
509 snd_use_case_set(handle->ucMgr, "_disdev", curRxUCMDevice);
510 }
511 }
512 if (txDevice != NULL) {
513 if ((strncmp(curTxUCMDevice, "None", 4)) &&
514 ((strncmp(txDevice, curTxUCMDevice, MAX_STR_LEN)) || (inCallDevSwitch == true))) {
515 if ((use_case != NULL) && (strncmp(use_case, SND_USE_CASE_VERB_INACTIVE,
516 strlen(SND_USE_CASE_VERB_INACTIVE)))) {
517 usecase_type = getUseCaseType(use_case);
518 if ((usecase_type & USECASE_TYPE_TX) && (!(usecase_type & USECASE_TYPE_RX))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700519 ALOGD("Deroute use case %s type is %d\n", use_case, usecase_type);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700520 strlcpy(useCaseNode.useCase, use_case, MAX_STR_LEN);
521 snd_use_case_set(handle->ucMgr, "_verb", SND_USE_CASE_VERB_INACTIVE);
522 mUseCaseList.push_front(useCaseNode);
523 }
524 }
525 if (mods_size) {
526 for(index = 0; index < mods_size; index++) {
527 usecase_type = getUseCaseType(mods_list[index]);
528 if ((usecase_type & USECASE_TYPE_TX) && (!(usecase_type & USECASE_TYPE_RX))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700529 ALOGD("Deroute use case %s type is %d\n", mods_list[index], usecase_type);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700530 strlcpy(useCaseNode.useCase, mods_list[index], MAX_STR_LEN);
531 snd_use_case_set(handle->ucMgr, "_dismod", mods_list[index]);
532 mUseCaseList.push_back(useCaseNode);
533 }
534 }
535 }
536 snd_use_case_set(handle->ucMgr, "_disdev", curTxUCMDevice);
537 }
538 }
SathishKumar Mani9efed762012-09-18 18:52:48 -0700539 ALOGD("%s,rxDev:%s, txDev:%s, curRxDev:%s, curTxDev:%s\n", __FUNCTION__, rxDevice, txDevice, curRxUCMDevice, curTxUCMDevice);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700540
541 if (rxDevice != NULL) {
542 snd_use_case_set(handle->ucMgr, "_enadev", rxDevice);
543 strlcpy(curRxUCMDevice, rxDevice, sizeof(curRxUCMDevice));
Ajay Dudani9746c472012-06-18 16:01:16 -0700544#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700545 if (devices & AudioSystem::DEVICE_OUT_FM)
546 s_set_fm_vol(fmVolume);
547#endif
548 }
549 if (txDevice != NULL) {
550 snd_use_case_set(handle->ucMgr, "_enadev", txDevice);
551 strlcpy(curTxUCMDevice, txDevice, sizeof(curTxUCMDevice));
552 }
553 for(ALSAUseCaseList::iterator it = mUseCaseList.begin(); it != mUseCaseList.end(); ++it) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700554 ALOGD("Route use case %s\n", it->useCase);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700555 if ((use_case != NULL) && (strncmp(use_case, SND_USE_CASE_VERB_INACTIVE,
556 strlen(SND_USE_CASE_VERB_INACTIVE))) && (!strncmp(use_case, it->useCase, MAX_UC_LEN))) {
557 snd_use_case_set(handle->ucMgr, "_verb", it->useCase);
558 } else {
559 snd_use_case_set(handle->ucMgr, "_enamod", it->useCase);
560 }
561 }
562 if (!mUseCaseList.empty())
563 mUseCaseList.clear();
564 if (use_case != NULL) {
565 free(use_case);
566 use_case = NULL;
567 }
Iliyan Malchev4113f342012-06-11 14:39:47 -0700568 ALOGD("switchDevice: curTxUCMDevivce %s curRxDevDevice %s", curTxUCMDevice, curRxUCMDevice);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700569
SathishKumar Manic669c272012-09-21 20:12:08 -0700570 if (platform_is_Fusion3() && (inCallDevSwitch == true)) {
Iliyan Malchev4765c432012-06-11 14:36:16 -0700571 /* get tx acdb id */
572 memset(&ident,0,sizeof(ident));
573 strlcpy(ident, "ACDBID/", sizeof(ident));
574 strlcat(ident, curTxUCMDevice, sizeof(ident));
575 tx_dev_id = snd_use_case_get(handle->ucMgr, ident, NULL);
576
577 /* get rx acdb id */
578 memset(&ident,0,sizeof(ident));
579 strlcpy(ident, "ACDBID/", sizeof(ident));
580 strlcat(ident, curRxUCMDevice, sizeof(ident));
581 rx_dev_id = snd_use_case_get(handle->ucMgr, ident, NULL);
582
ehgrace.kim91e9fad2012-07-02 18:27:28 -0700583 if (((rx_dev_id == DEVICE_SPEAKER_MONO_RX_ACDB_ID ) || (rx_dev_id == DEVICE_SPEAKER_STEREO_RX_ACDB_ID ))
584 && tx_dev_id == DEVICE_HANDSET_TX_ACDB_ID) {
Iliyan Malchev4765c432012-06-11 14:36:16 -0700585 tx_dev_id = DEVICE_SPEAKER_TX_ACDB_ID;
586 }
587
Ajay Dudani9746c472012-06-18 16:01:16 -0700588#ifdef QCOM_CSDCLIENT_ENABLED
Iliyan Malchev4113f342012-06-11 14:39:47 -0700589 ALOGV("rx_dev_id=%d, tx_dev_id=%d\n", rx_dev_id, tx_dev_id);
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700590 if (csd_enable_device == NULL) {
591 ALOGE("dlsym:Error:%s Loading csd_client_enable_device", dlerror());
592 } else {
593 err = csd_enable_device(rx_dev_id, tx_dev_id, mDevSettingsFlag);
594 if (err < 0)
595 {
596 ALOGE("csd_client_disable_device failed, error %d", err);
597 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700598 }
Iliyan Malchev4113f342012-06-11 14:39:47 -0700599#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700600 }
601
602 if (rxDevice != NULL) {
603 if (pflag && (((!strncmp(rxDevice, DEVICE_SPEAKER_HEADSET, strlen(DEVICE_SPEAKER_HEADSET))) &&
604 ((!strncmp(curRxUCMDevice, DEVICE_HEADPHONES, strlen(DEVICE_HEADPHONES))) ||
605 (!strncmp(curRxUCMDevice, DEVICE_HEADSET, strlen(DEVICE_HEADSET))))) ||
606 (((!strncmp(curRxUCMDevice, DEVICE_SPEAKER_HEADSET, strlen(DEVICE_SPEAKER_HEADSET))) &&
607 ((!strncmp(rxDevice, DEVICE_HEADPHONES, strlen(DEVICE_HEADPHONES))) ||
608 (!strncmp(rxDevice, DEVICE_HEADSET, strlen(DEVICE_HEADSET))))))) &&
609 ((!strncmp(handle->useCase, SND_USE_CASE_VERB_HIFI, strlen(SND_USE_CASE_VERB_HIFI))) ||
610 (!strncmp(handle->useCase, SND_USE_CASE_MOD_PLAY_MUSIC, strlen(SND_USE_CASE_MOD_PLAY_MUSIC))))) {
611 s_open(handle);
612 pflag = false;
613 }
614 }
615
616 if (rxDevice != NULL) {
617 free(rxDevice);
618 rxDevice = NULL;
619 }
620 if (txDevice != NULL) {
621 free(txDevice);
622 txDevice = NULL;
623 }
624}
625
626// ----------------------------------------------------------------------------
627
628static status_t s_init(alsa_device_t *module, ALSAHandleList &list)
629{
SathishKumar Mani9efed762012-09-18 18:52:48 -0700630 ALOGV("s_init: Initializing devices for ALSA module");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700631
632 list.clear();
633
634 return NO_ERROR;
635}
636
637static status_t s_open(alsa_handle_t *handle)
638{
639 char *devName;
640 unsigned flags = 0;
641 int err = NO_ERROR;
642
SathishKumar Manib357a772012-09-25 23:28:29 -0700643 if(handle->devices & AudioSystem::DEVICE_OUT_AUX_DIGITAL) {
644 err = setHDMIChannelCount();
645 if(err != OK) {
646 ALOGE("setHDMIChannelCount err = %d", err);
647 return err;
648 }
649 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700650 /* No need to call s_close for LPA as pcm device open and close is handled by LPAPlayer in stagefright */
651 if((!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER)) || (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_LPA))
652 ||(!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 -0700653 ALOGV("s_open: Opening LPA /Tunnel playback");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700654 return NO_ERROR;
655 }
656
657 s_close(handle);
658
SathishKumar Mani9efed762012-09-18 18:52:48 -0700659 ALOGV("s_open: handle %p", handle);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700660
661 // ASoC multicomponent requires a valid path (frontend/backend) for
662 // the device to be opened
663
664 // The PCM stream is opened in blocking mode, per ALSA defaults. The
665 // AudioFlinger seems to assume blocking mode too, so asynchronous mode
666 // should not be used.
SathishKumar Mani88613382012-08-13 18:40:18 -0700667 if ((!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER)) ||
668 (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_LPA)) ||
669 (!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_TUNNEL)) ||
670 (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_TUNNEL))) {
671 ALOGV("LPA/tunnel use case");
672 flags |= PCM_MMAP;
673 flags |= DEBUG_ON;
674 } else if ((!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI)) ||
675 (!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC)) ||
676 (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -0700677 (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_MUSIC))) {
SathishKumar Mani88613382012-08-13 18:40:18 -0700678 ALOGV("Music case");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700679 flags = PCM_OUT;
680 } else {
681 flags = PCM_IN;
682 }
683 if (handle->channels == 1) {
684 flags |= PCM_MONO;
SathishKumar Manie42406e2012-08-29 16:25:54 -0700685 }
Ajay Dudani9746c472012-06-18 16:01:16 -0700686#ifdef QCOM_SSR_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700687 else if (handle->channels == 4 ) {
688 flags |= PCM_QUAD;
689 } else if (handle->channels == 6 ) {
690 if (!strncmp(handle->useCase, SND_USE_CASE_VERB_HIFI_REC, strlen(SND_USE_CASE_VERB_HIFI_REC))
691 || !strncmp(handle->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, strlen(SND_USE_CASE_MOD_CAPTURE_MUSIC))) {
692 flags |= PCM_QUAD;
693 } else {
694 flags |= PCM_5POINT1;
695 }
SathishKumar Manie42406e2012-08-29 16:25:54 -0700696 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700697#endif
698 else {
699 flags |= PCM_STEREO;
700 }
701 if (deviceName(handle, flags, &devName) < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700702 ALOGE("Failed to get pcm device node: %s", devName);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700703 return NO_INIT;
704 }
705 if (devName != NULL) {
706 handle->handle = pcm_open(flags, (char*)devName);
707 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700708 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700709 return NO_INIT;
710 }
711
712 if (!handle->handle) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700713 ALOGE("s_open: Failed to initialize ALSA device '%s'", devName);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700714 free(devName);
715 return NO_INIT;
716 }
717
718 handle->handle->flags = flags;
719 err = setHardwareParams(handle);
720
721 if (err == NO_ERROR) {
722 err = setSoftwareParams(handle);
723 }
724
725 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700726 ALOGE("Set HW/SW params failed: Closing the pcm stream");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700727 s_standby(handle);
728 }
729
730 free(devName);
731 return NO_ERROR;
732}
733
734static status_t s_start_voip_call(alsa_handle_t *handle)
735{
736
737 char* devName;
738 char* devName1;
739 unsigned flags = 0;
740 int err = NO_ERROR;
741 uint8_t voc_pkt[VOIP_BUFFER_MAX_SIZE];
742
743 s_close(handle);
744 flags = PCM_OUT;
745 flags |= PCM_MONO;
Iliyan Malchev4113f342012-06-11 14:39:47 -0700746 ALOGV("s_open:s_start_voip_call handle %p", handle);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700747
748 if (deviceName(handle, flags, &devName) < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700749 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700750 return NO_INIT;
751 }
752
753 if (devName != NULL) {
754 handle->handle = pcm_open(flags, (char*)devName);
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 failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700768 }
769
770 handle->handle->flags = flags;
771 err = setHardwareParams(handle);
772
773 if (err == NO_ERROR) {
774 err = setSoftwareParams(handle);
775 }
776
777 err = pcm_prepare(handle->handle);
778 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700779 ALOGE("DEVICE_OUT_DIRECTOUTPUT: pcm_prepare failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700780 }
781
782 /* first write required start dsp */
783 memset(&voc_pkt,0,sizeof(voc_pkt));
784 pcm_write(handle->handle,&voc_pkt,handle->handle->period_size);
785 handle->rxHandle = handle->handle;
786 free(devName);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700787 ALOGV("s_open: DEVICE_IN_COMMUNICATION ");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700788 flags = PCM_IN;
789 flags |= PCM_MONO;
790 handle->handle = 0;
791
792 if (deviceName(handle, flags, &devName1) < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700793 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700794 return NO_INIT;
795 }
796 if (devName != NULL) {
797 handle->handle = pcm_open(flags, (char*)devName1);
798 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700799 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700800 return NO_INIT;
801 }
802
803 if (!handle->handle) {
804 free(devName);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700805 ALOGE("s_open: Failed to initialize ALSA device '%s'", devName);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700806 return NO_INIT;
807 }
808
809 if (!pcm_ready(handle->handle)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700810 ALOGE(" pcm ready in failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700811 }
812
813 handle->handle->flags = flags;
814
815 err = setHardwareParams(handle);
816
817 if (err == NO_ERROR) {
818 err = setSoftwareParams(handle);
819 }
820
821
822 err = pcm_prepare(handle->handle);
823 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700824 ALOGE("DEVICE_IN_COMMUNICATION: pcm_prepare failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700825 }
826
827 /* first read required start dsp */
828 memset(&voc_pkt,0,sizeof(voc_pkt));
829 pcm_read(handle->handle,&voc_pkt,handle->handle->period_size);
830 return NO_ERROR;
831}
832
833static status_t s_start_voice_call(alsa_handle_t *handle)
834{
835 char* devName;
836 unsigned flags = 0;
837 int err = NO_ERROR;
838
SathishKumar Mani9efed762012-09-18 18:52:48 -0700839 ALOGV("s_start_voice_call: handle %p", handle);
Ajay Dudani86c852b2012-07-19 15:28:45 -0700840
Iliyan Malchev4765c432012-06-11 14:36:16 -0700841 // ASoC multicomponent requires a valid path (frontend/backend) for
842 // the device to be opened
843
844 flags = PCM_OUT | PCM_MONO;
845 if (deviceName(handle, flags, &devName) < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700846 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700847 return NO_INIT;
848 }
849 if (devName != NULL) {
850 handle->handle = pcm_open(flags, (char*)devName);
851 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700852 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700853 return NO_INIT;
854 }
855 if (!handle->handle) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700856 ALOGE("s_start_voicecall: could not open PCM device");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700857 goto Error;
858 }
859
860 handle->handle->flags = flags;
861 err = setHardwareParams(handle);
862 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700863 ALOGE("s_start_voice_call: setHardwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700864 goto Error;
865 }
866
867 err = setSoftwareParams(handle);
868 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700869 ALOGE("s_start_voice_call: setSoftwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700870 goto Error;
871 }
872
873 err = pcm_prepare(handle->handle);
874 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700875 ALOGE("s_start_voice_call: pcm_prepare failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700876 goto Error;
877 }
878
879 if (ioctl(handle->handle->fd, SNDRV_PCM_IOCTL_START)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700880 ALOGE("s_start_voice_call:SNDRV_PCM_IOCTL_START failed\n");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700881 goto Error;
882 }
883
884 // Store the PCM playback device pointer in rxHandle
885 handle->rxHandle = handle->handle;
886 free(devName);
887
888 // Open PCM capture device
889 flags = PCM_IN | PCM_MONO;
890 if (deviceName(handle, flags, &devName) < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700891 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700892 goto Error;
893 }
894 if (devName != NULL) {
895 handle->handle = pcm_open(flags, (char*)devName);
896 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700897 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700898 return NO_INIT;
899 }
900 if (!handle->handle) {
901 free(devName);
902 goto Error;
903 }
904
905 handle->handle->flags = flags;
906 err = setHardwareParams(handle);
907 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700908 ALOGE("s_start_voice_call: setHardwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700909 goto Error;
910 }
911
912 err = setSoftwareParams(handle);
913 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700914 ALOGE("s_start_voice_call: setSoftwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700915 goto Error;
916 }
917
918 err = pcm_prepare(handle->handle);
919 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700920 ALOGE("s_start_voice_call: pcm_prepare failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700921 goto Error;
922 }
923
924 if (ioctl(handle->handle->fd, SNDRV_PCM_IOCTL_START)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700925 ALOGE("s_start_voice_call:SNDRV_PCM_IOCTL_START failed\n");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700926 goto Error;
927 }
928
929 if (platform_is_Fusion3()) {
Ajay Dudani9746c472012-06-18 16:01:16 -0700930#ifdef QCOM_CSDCLIENT_ENABLED
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700931 if (csd_start_voice == NULL) {
932 ALOGE("dlsym:Error:%s Loading csd_client_start_voice", dlerror());
933 } else {
934 err = csd_start_voice();
935 if (err < 0){
936 ALOGE("s_start_voice_call: csd_client error %d\n", err);
937 goto Error;
938 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700939 }
Iliyan Malchev4113f342012-06-11 14:39:47 -0700940#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700941 }
942
943 free(devName);
944 return NO_ERROR;
945
946Error:
Iliyan Malchev4113f342012-06-11 14:39:47 -0700947 ALOGE("s_start_voice_call: Failed to initialize ALSA device '%s'", devName);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700948 free(devName);
949 s_close(handle);
950 return NO_INIT;
951}
952
953static status_t s_start_fm(alsa_handle_t *handle)
954{
955 char *devName;
956 unsigned flags = 0;
957 int err = NO_ERROR;
958
SathishKumar Mani9efed762012-09-18 18:52:48 -0700959 ALOGV("s_start_fm: handle %p", handle);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700960
961 // ASoC multicomponent requires a valid path (frontend/backend) for
962 // the device to be opened
963
964 flags = PCM_OUT | PCM_STEREO;
965 if (deviceName(handle, flags, &devName) < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700966 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700967 goto Error;
968 }
969 if (devName != NULL) {
970 handle->handle = pcm_open(flags, (char*)devName);
971 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700972 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700973 return NO_INIT;
974 }
975 if (!handle->handle) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700976 ALOGE("s_start_fm: could not open PCM device");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700977 goto Error;
978 }
979
980 handle->handle->flags = flags;
981 err = setHardwareParams(handle);
982 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700983 ALOGE("s_start_fm: setHardwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700984 goto Error;
985 }
986
987 err = setSoftwareParams(handle);
988 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700989 ALOGE("s_start_fm: setSoftwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700990 goto Error;
991 }
992
993 err = pcm_prepare(handle->handle);
994 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700995 ALOGE("s_start_fm: setSoftwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700996 goto Error;
997 }
998
999 if (ioctl(handle->handle->fd, SNDRV_PCM_IOCTL_START)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001000 ALOGE("s_start_fm: SNDRV_PCM_IOCTL_START failed\n");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001001 goto Error;
1002 }
1003
1004 // Store the PCM playback device pointer in rxHandle
1005 handle->rxHandle = handle->handle;
1006 free(devName);
1007
1008 // Open PCM capture device
1009 flags = PCM_IN | PCM_STEREO;
1010 if (deviceName(handle, flags, &devName) < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001011 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001012 goto Error;
1013 }
1014 if (devName != NULL) {
1015 handle->handle = pcm_open(flags, (char*)devName);
1016 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001017 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001018 return NO_INIT;
1019 }
1020 if (!handle->handle) {
1021 goto Error;
1022 }
1023
1024 handle->handle->flags = flags;
1025 err = setHardwareParams(handle);
1026 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001027 ALOGE("s_start_fm: setHardwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001028 goto Error;
1029 }
1030
1031 err = setSoftwareParams(handle);
1032 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001033 ALOGE("s_start_fm: setSoftwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001034 goto Error;
1035 }
1036
1037 err = pcm_prepare(handle->handle);
1038 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001039 ALOGE("s_start_fm: pcm_prepare failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001040 goto Error;
1041 }
1042
1043 if (ioctl(handle->handle->fd, SNDRV_PCM_IOCTL_START)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001044 ALOGE("s_start_fm: SNDRV_PCM_IOCTL_START failed\n");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001045 goto Error;
1046 }
1047
1048 s_set_fm_vol(fmVolume);
1049 free(devName);
1050 return NO_ERROR;
1051
1052Error:
1053 free(devName);
1054 s_close(handle);
1055 return NO_INIT;
1056}
1057
1058static status_t s_set_fm_vol(int value)
1059{
1060 status_t err = NO_ERROR;
1061
1062 ALSAControl control("/dev/snd/controlC0");
1063 control.set("Internal FM RX Volume",value,0);
1064 fmVolume = value;
1065
1066 return err;
1067}
1068
1069static status_t s_set_lpa_vol(int value)
1070{
1071 status_t err = NO_ERROR;
1072
1073 ALSAControl control("/dev/snd/controlC0");
1074 control.set("LPA RX Volume",value,0);
1075
1076 return err;
1077}
1078
1079static status_t s_start(alsa_handle_t *handle)
1080{
1081 status_t err = NO_ERROR;
1082
1083 if(!handle->handle) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001084 ALOGE("No active PCM driver to start");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001085 return err;
1086 }
1087
1088 err = pcm_prepare(handle->handle);
1089
1090 return err;
1091}
1092
1093static status_t s_close(alsa_handle_t *handle)
1094{
1095 int ret;
1096 status_t err = NO_ERROR;
1097 struct pcm *h = handle->rxHandle;
1098
1099 handle->rxHandle = 0;
SathishKumar Mani9efed762012-09-18 18:52:48 -07001100 ALOGV("s_close: handle %p h %p", handle, h);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001101 if (h) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001102 ALOGV("s_close rxHandle\n");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001103 err = pcm_close(h);
1104 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001105 ALOGE("s_close: pcm_close failed for rxHandle with err %d", err);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001106 }
1107 }
1108
1109 h = handle->handle;
1110 handle->handle = 0;
1111
1112 if (h) {
SathishKumar Mani9efed762012-09-18 18:52:48 -07001113 ALOGV("s_close handle h %p\n", h);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001114 err = pcm_close(h);
1115 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001116 ALOGE("s_close: pcm_close failed for handle with err %d", err);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001117 }
1118
1119 if ((!strcmp(handle->useCase, SND_USE_CASE_VERB_VOICECALL) ||
1120 !strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_VOICE)) &&
1121 platform_is_Fusion3()) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001122#ifdef QCOM_CSDCLIENT_ENABLED
SathishKumar Mani5ff7a022012-09-14 11:36:35 -07001123 if (csd_stop_voice == NULL) {
1124 ALOGE("dlsym:Error:%s Loading csd_client_disable_device", dlerror());
1125 } else {
1126 err = csd_stop_voice();
1127 if (err < 0) {
1128 ALOGE("s_close: csd_client error %d\n", err);
1129 }
Iliyan Malchev4765c432012-06-11 14:36:16 -07001130 }
Iliyan Malchev4113f342012-06-11 14:39:47 -07001131#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001132 }
1133
1134 disableDevice(handle);
1135 } else if((!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER)) ||
1136 (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_LPA)) ||
1137 (!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_TUNNEL)) ||
1138 (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_TUNNEL))){
1139 disableDevice(handle);
1140 }
1141
1142 return err;
1143}
1144
1145/*
1146 this is same as s_close, but don't discard
1147 the device/mode info. This way we can still
1148 close the device, hit idle and power-save, reopen the pcm
1149 for the same device/mode after resuming
1150*/
1151static status_t s_standby(alsa_handle_t *handle)
1152{
1153 int ret;
SathishKumar Manie42406e2012-08-29 16:25:54 -07001154 status_t err = NO_ERROR;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001155 struct pcm *h = handle->rxHandle;
1156 handle->rxHandle = 0;
SathishKumar Mani9efed762012-09-18 18:52:48 -07001157 ALOGV("s_standby: handle %p h %p", handle, h);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001158 if (h) {
SathishKumar Mani0a019912012-09-11 12:33:11 -07001159 ALOGD("s_standby rxHandle\n");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001160 err = pcm_close(h);
1161 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001162 ALOGE("s_standby: pcm_close failed for rxHandle with err %d", err);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001163 }
1164 }
1165
1166 h = handle->handle;
1167 handle->handle = 0;
1168
1169 if (h) {
SathishKumar Mani9efed762012-09-18 18:52:48 -07001170 ALOGV("s_standby handle h %p\n", h);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001171 err = pcm_close(h);
1172 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001173 ALOGE("s_standby: pcm_close failed for handle with err %d", err);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001174 }
1175 disableDevice(handle);
1176 } else if((!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER)) ||
1177 (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_LPA)) ||
1178 (!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_TUNNEL)) ||
1179 (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_TUNNEL))) {
1180 disableDevice(handle);
1181 }
1182
1183 return err;
1184}
1185
1186static status_t s_route(alsa_handle_t *handle, uint32_t devices, int mode)
1187{
1188 status_t status = NO_ERROR;
1189
Iliyan Malchev4113f342012-06-11 14:39:47 -07001190 ALOGD("s_route: devices 0x%x in mode %d", devices, mode);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001191 callMode = mode;
1192 switchDevice(handle, devices, mode);
1193 return status;
1194}
1195
1196int getUseCaseType(const char *useCase)
1197{
SathishKumar Mani0a019912012-09-11 12:33:11 -07001198 ALOGD("use case is %s\n", useCase);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001199 if (!strncmp(useCase, SND_USE_CASE_VERB_HIFI,
chahee.kima8b76532012-10-01 16:34:06 +09001200 MAX_LEN(useCase,SND_USE_CASE_VERB_HIFI)) ||
SathishKumar Mani88613382012-08-13 18:40:18 -07001201 !strncmp(useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC,
chahee.kima8b76532012-10-01 16:34:06 +09001202 MAX_LEN(useCase,SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001203 !strncmp(useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER,
chahee.kima8b76532012-10-01 16:34:06 +09001204 MAX_LEN(useCase,SND_USE_CASE_VERB_HIFI_LOW_POWER)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001205 !strncmp(useCase, SND_USE_CASE_VERB_HIFI_TUNNEL,
chahee.kima8b76532012-10-01 16:34:06 +09001206 MAX_LEN(useCase,SND_USE_CASE_VERB_HIFI_TUNNEL)) ||
1207 !strncmp(useCase, SND_USE_CASE_VERB_HIFI2,
1208 MAX_LEN(useCase,SND_USE_CASE_VERB_HIFI2)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001209 !strncmp(useCase, SND_USE_CASE_VERB_DIGITAL_RADIO,
chahee.kima8b76532012-10-01 16:34:06 +09001210 MAX_LEN(useCase,SND_USE_CASE_VERB_DIGITAL_RADIO)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001211 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_MUSIC,
chahee.kima8b76532012-10-01 16:34:06 +09001212 MAX_LEN(useCase,SND_USE_CASE_MOD_PLAY_MUSIC)) ||
SathishKumar Mani88613382012-08-13 18:40:18 -07001213 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC,
chahee.kima8b76532012-10-01 16:34:06 +09001214 MAX_LEN(useCase,SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC)) ||
1215 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_MUSIC2,
1216 MAX_LEN(useCase,SND_USE_CASE_MOD_PLAY_MUSIC2)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001217 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_LPA,
chahee.kima8b76532012-10-01 16:34:06 +09001218 MAX_LEN(useCase,SND_USE_CASE_MOD_PLAY_LPA)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001219 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_TUNNEL,
chahee.kima8b76532012-10-01 16:34:06 +09001220 MAX_LEN(useCase,SND_USE_CASE_MOD_PLAY_TUNNEL)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001221 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_FM,
chahee.kima8b76532012-10-01 16:34:06 +09001222 MAX_LEN(useCase,SND_USE_CASE_MOD_PLAY_FM))) {
Iliyan Malchev4765c432012-06-11 14:36:16 -07001223 return USECASE_TYPE_RX;
1224 } else if (!strncmp(useCase, SND_USE_CASE_VERB_HIFI_REC,
chahee.kima8b76532012-10-01 16:34:06 +09001225 MAX_LEN(useCase,SND_USE_CASE_VERB_HIFI_REC)) ||
SathishKumar Mani88613382012-08-13 18:40:18 -07001226 !strncmp(useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_REC,
chahee.kima8b76532012-10-01 16:34:06 +09001227 MAX_LEN(useCase,SND_USE_CASE_VERB_HIFI_LOWLATENCY_REC)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001228 !strncmp(useCase, SND_USE_CASE_VERB_FM_REC,
chahee.kima8b76532012-10-01 16:34:06 +09001229 MAX_LEN(useCase,SND_USE_CASE_VERB_FM_REC)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001230 !strncmp(useCase, SND_USE_CASE_VERB_FM_A2DP_REC,
chahee.kima8b76532012-10-01 16:34:06 +09001231 MAX_LEN(useCase,SND_USE_CASE_VERB_FM_A2DP_REC)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001232 !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC,
chahee.kima8b76532012-10-01 16:34:06 +09001233 MAX_LEN(useCase,SND_USE_CASE_MOD_CAPTURE_MUSIC)) ||
SathishKumar Mani88613382012-08-13 18:40:18 -07001234 !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_LOWLATENCY_MUSIC,
chahee.kima8b76532012-10-01 16:34:06 +09001235 MAX_LEN(useCase,SND_USE_CASE_MOD_CAPTURE_LOWLATENCY_MUSIC)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001236 !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_FM,
chahee.kima8b76532012-10-01 16:34:06 +09001237 MAX_LEN(useCase,SND_USE_CASE_MOD_CAPTURE_FM)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001238 !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_A2DP_FM,
chahee.kima8b76532012-10-01 16:34:06 +09001239 MAX_LEN(useCase,SND_USE_CASE_MOD_CAPTURE_A2DP_FM))) {
Iliyan Malchev4765c432012-06-11 14:36:16 -07001240 return USECASE_TYPE_TX;
1241 } else if (!strncmp(useCase, SND_USE_CASE_VERB_VOICECALL,
chahee.kima8b76532012-10-01 16:34:06 +09001242 MAX_LEN(useCase,SND_USE_CASE_VERB_VOICECALL)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001243 !strncmp(useCase, SND_USE_CASE_VERB_IP_VOICECALL,
chahee.kima8b76532012-10-01 16:34:06 +09001244 MAX_LEN(useCase,SND_USE_CASE_VERB_IP_VOICECALL)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001245 !strncmp(useCase, SND_USE_CASE_VERB_DL_REC,
chahee.kima8b76532012-10-01 16:34:06 +09001246 MAX_LEN(useCase,SND_USE_CASE_VERB_DL_REC)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001247 !strncmp(useCase, SND_USE_CASE_VERB_UL_DL_REC,
chahee.kima8b76532012-10-01 16:34:06 +09001248 MAX_LEN(useCase,SND_USE_CASE_VERB_UL_DL_REC)) ||
1249 !strncmp(useCase, SND_USE_CASE_VERB_INCALL_REC,
1250 MAX_LEN(useCase,SND_USE_CASE_VERB_INCALL_REC)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001251 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_VOICE,
chahee.kima8b76532012-10-01 16:34:06 +09001252 MAX_LEN(useCase,SND_USE_CASE_MOD_PLAY_VOICE)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001253 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_VOIP,
chahee.kima8b76532012-10-01 16:34:06 +09001254 MAX_LEN(useCase,SND_USE_CASE_MOD_PLAY_VOIP)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001255 !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_VOICE_DL,
chahee.kima8b76532012-10-01 16:34:06 +09001256 MAX_LEN(useCase,SND_USE_CASE_MOD_CAPTURE_VOICE_DL)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001257 !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_VOICE_UL_DL,
chahee.kima8b76532012-10-01 16:34:06 +09001258 MAX_LEN(useCase,SND_USE_CASE_MOD_CAPTURE_VOICE_UL_DL)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001259 !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_VOICE,
chahee.kima8b76532012-10-01 16:34:06 +09001260 MAX_LEN(useCase, SND_USE_CASE_MOD_CAPTURE_VOICE)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001261 !strncmp(useCase, SND_USE_CASE_VERB_VOLTE,
chahee.kima8b76532012-10-01 16:34:06 +09001262 MAX_LEN(useCase,SND_USE_CASE_VERB_VOLTE)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001263 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_VOLTE,
chahee.kima8b76532012-10-01 16:34:06 +09001264 MAX_LEN(useCase, SND_USE_CASE_MOD_PLAY_VOLTE))) {
Iliyan Malchev4765c432012-06-11 14:36:16 -07001265 return (USECASE_TYPE_RX | USECASE_TYPE_TX);
1266 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001267 ALOGE("unknown use case %s\n", useCase);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001268 return 0;
1269 }
1270}
1271
1272static void disableDevice(alsa_handle_t *handle)
1273{
1274 unsigned usecase_type = 0;
1275 int i, mods_size;
1276 char *useCase;
1277 const char **mods_list;
1278
1279 snd_use_case_get(handle->ucMgr, "_verb", (const char **)&useCase);
1280 if (useCase != NULL) {
1281 if (!strncmp(useCase, handle->useCase, MAX_UC_LEN)) {
1282 snd_use_case_set(handle->ucMgr, "_verb", SND_USE_CASE_VERB_INACTIVE);
1283 } else {
1284 snd_use_case_set(handle->ucMgr, "_dismod", handle->useCase);
1285 }
1286 free(useCase);
1287 snd_use_case_get(handle->ucMgr, "_verb", (const char **)&useCase);
1288 if (strncmp(useCase, SND_USE_CASE_VERB_INACTIVE,
1289 strlen(SND_USE_CASE_VERB_INACTIVE)))
1290 usecase_type |= getUseCaseType(useCase);
1291 mods_size = snd_use_case_get_list(handle->ucMgr, "_enamods", &mods_list);
SathishKumar Mani9efed762012-09-18 18:52:48 -07001292 ALOGV("Number of modifiers %d\n", mods_size);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001293 if (mods_size) {
1294 for(i = 0; i < mods_size; i++) {
SathishKumar Mani9efed762012-09-18 18:52:48 -07001295 ALOGV("index %d modifier %s\n", i, mods_list[i]);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001296 usecase_type |= getUseCaseType(mods_list[i]);
1297 }
1298 }
SathishKumar Mani9efed762012-09-18 18:52:48 -07001299 ALOGV("usecase_type is %d\n", usecase_type);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001300 if (!(usecase_type & USECASE_TYPE_TX) && (strncmp(curTxUCMDevice, "None", 4)))
1301 snd_use_case_set(handle->ucMgr, "_disdev", curTxUCMDevice);
1302 if (!(usecase_type & USECASE_TYPE_RX) && (strncmp(curRxUCMDevice, "None", 4)))
1303 snd_use_case_set(handle->ucMgr, "_disdev", curRxUCMDevice);
1304 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001305 ALOGE("Invalid state, no valid use case found to disable");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001306 }
1307 free(useCase);
1308}
1309
1310char *getUCMDevice(uint32_t devices, int input, char *rxDevice)
1311{
1312 if (!input) {
1313 if (!(mDevSettingsFlag & TTY_OFF) &&
1314 (callMode == AudioSystem::MODE_IN_CALL) &&
1315 ((devices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) ||
ty.lee924f7982012-08-01 23:15:30 +09001316 (devices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE))) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001317#ifdef QCOM_ANC_HEADSET_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001318 ||
1319 (devices & AudioSystem::DEVICE_OUT_ANC_HEADSET) ||
1320 (devices & AudioSystem::DEVICE_OUT_ANC_HEADPHONE))) {
1321#endif
1322 if (mDevSettingsFlag & TTY_VCO) {
1323 return strdup(SND_USE_CASE_DEV_TTY_HEADSET_RX);
1324 } else if (mDevSettingsFlag & TTY_FULL) {
1325 return strdup(SND_USE_CASE_DEV_TTY_FULL_RX);
1326 } else if (mDevSettingsFlag & TTY_HCO) {
1327 return strdup(SND_USE_CASE_DEV_TTY_HANDSET_RX); /* HANDSET RX */
1328 }
1329 }else if ((devices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET) ||
1330 (devices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)) {
1331 return strdup(SND_USE_CASE_DEV_PROXY_RX); /* PROXY RX */
1332 } else if ((devices & AudioSystem::DEVICE_OUT_SPEAKER) &&
1333 ((devices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) ||
1334 (devices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE))) {
1335 if (mDevSettingsFlag & ANC_FLAG) {
1336 return strdup(SND_USE_CASE_DEV_SPEAKER_ANC_HEADSET); /* COMBO SPEAKER+ANC HEADSET RX */
1337 } else {
1338 return strdup(SND_USE_CASE_DEV_SPEAKER_HEADSET); /* COMBO SPEAKER+HEADSET RX */
1339 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001340#ifdef QCOM_ANC_HEADSET_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001341 } else if ((devices & AudioSystem::DEVICE_OUT_SPEAKER) &&
1342 ((devices & AudioSystem::DEVICE_OUT_ANC_HEADSET) ||
1343 (devices & AudioSystem::DEVICE_OUT_ANC_HEADPHONE))) {
1344 return strdup(SND_USE_CASE_DEV_SPEAKER_ANC_HEADSET); /* COMBO SPEAKER+ANC HEADSET RX */
1345 } else if ((devices & AudioSystem::DEVICE_OUT_SPEAKER) &&
1346 (devices & AudioSystem::DEVICE_OUT_FM_TX)) {
1347 return strdup(SND_USE_CASE_DEV_SPEAKER_FM_TX); /* COMBO SPEAKER+FM_TX RX */
1348#endif
1349 } else if (devices & AudioSystem::DEVICE_OUT_EARPIECE) {
ty.lee925596f2012-09-12 18:23:59 +09001350 if (callMode == AudioSystem::MODE_IN_CALL) {
1351 return strdup(SND_USE_CASE_DEV_VOC_EARPIECE); /* Voice HANDSET RX */
1352 } else
1353 return strdup(SND_USE_CASE_DEV_EARPIECE); /* HANDSET RX */
Iliyan Malchev4765c432012-06-11 14:36:16 -07001354 } else if (devices & AudioSystem::DEVICE_OUT_SPEAKER) {
ty.lee925596f2012-09-12 18:23:59 +09001355 if (callMode == AudioSystem::MODE_IN_CALL) {
1356 return strdup(SND_USE_CASE_DEV_VOC_SPEAKER); /* Voice SPEAKER RX */
1357 } else
1358 return strdup(SND_USE_CASE_DEV_SPEAKER); /* SPEAKER RX */
Iliyan Malchev4765c432012-06-11 14:36:16 -07001359 } else if ((devices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) ||
1360 (devices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE)) {
1361 if (mDevSettingsFlag & ANC_FLAG) {
ty.lee925596f2012-09-12 18:23:59 +09001362 if (callMode == AudioSystem::MODE_IN_CALL) {
1363 return strdup(SND_USE_CASE_DEV_VOC_ANC_HEADSET); /* Voice ANC HEADSET RX */
1364 } else
1365 return strdup(SND_USE_CASE_DEV_ANC_HEADSET); /* ANC HEADSET RX */
Iliyan Malchev4765c432012-06-11 14:36:16 -07001366 } else {
ty.lee925596f2012-09-12 18:23:59 +09001367 if (callMode == AudioSystem::MODE_IN_CALL) {
1368 return strdup(SND_USE_CASE_DEV_VOC_HEADPHONE); /* Voice HEADSET RX */
1369 } else
1370 return strdup(SND_USE_CASE_DEV_HEADPHONES); /* HEADSET RX */
Iliyan Malchev4765c432012-06-11 14:36:16 -07001371 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001372#ifdef QCOM_ANC_HEADSET_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001373 } else if ((devices & AudioSystem::DEVICE_OUT_ANC_HEADSET) ||
1374 (devices & AudioSystem::DEVICE_OUT_ANC_HEADPHONE)) {
ty.lee925596f2012-09-12 18:23:59 +09001375 if (callMode == AudioSystem::MODE_IN_CALL) {
1376 return strdup(SND_USE_CASE_DEV_VOC_ANC_HEADSET); /* Voice ANC HEADSET RX */
1377 } else
1378 return strdup(SND_USE_CASE_DEV_ANC_HEADSET); /* ANC HEADSET RX */
Iliyan Malchev4765c432012-06-11 14:36:16 -07001379#endif
1380 } else if ((devices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO) ||
1381 (devices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET) ||
1382 (devices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT)) {
1383 if (btsco_samplerate == BTSCO_RATE_16KHZ)
1384 return strdup(SND_USE_CASE_DEV_BTSCO_WB_RX); /* BTSCO RX*/
1385 else
1386 return strdup(SND_USE_CASE_DEV_BTSCO_NB_RX); /* BTSCO RX*/
1387 } else if ((devices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP) ||
1388 (devices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES) ||
Ajay Dudani9746c472012-06-18 16:01:16 -07001389#ifdef QCOM_VOIP_ENABLED
1390 (devices & AudioSystem::DEVICE_OUT_DIRECTOUTPUT) ||
1391#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001392 (devices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER)) {
1393 /* Nothing to be done, use current active device */
1394 if (strncmp(curRxUCMDevice, "None", 4)) {
1395 return strdup(curRxUCMDevice);
1396 }
1397 } else if (devices & AudioSystem::DEVICE_OUT_AUX_DIGITAL) {
1398 return strdup(SND_USE_CASE_DEV_HDMI); /* HDMI RX */
Ajay Dudani9746c472012-06-18 16:01:16 -07001399#ifdef QCOM_PROXY_DEVICE_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001400 } else if (devices & AudioSystem::DEVICE_OUT_PROXY) {
1401 return strdup(SND_USE_CASE_DEV_PROXY_RX); /* PROXY RX */
Ajay Dudani9746c472012-06-18 16:01:16 -07001402#endif
1403#ifdef QCOM_FM_TX_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001404 } else if (devices & AudioSystem::DEVICE_OUT_FM_TX) {
1405 return strdup(SND_USE_CASE_DEV_FM_TX); /* FM Tx */
1406#endif
1407 } else if (devices & AudioSystem::DEVICE_OUT_DEFAULT) {
ty.lee925596f2012-09-12 18:23:59 +09001408 if (callMode == AudioSystem::MODE_IN_CALL) {
1409 return strdup(SND_USE_CASE_DEV_VOC_SPEAKER); /* Voice SPEAKER RX */
1410 } else
1411 return strdup(SND_USE_CASE_DEV_SPEAKER); /* SPEAKER RX */
Iliyan Malchev4765c432012-06-11 14:36:16 -07001412 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001413 ALOGD("No valid output device: %u", devices);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001414 }
1415 } else {
1416 if (!(mDevSettingsFlag & TTY_OFF) &&
1417 (callMode == AudioSystem::MODE_IN_CALL) &&
ty.lee924f7982012-08-01 23:15:30 +09001418 ((devices & AudioSystem::DEVICE_IN_WIRED_HEADSET))) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001419#ifdef QCOM_ANC_HEADSET_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001420 ||(devices & AudioSystem::DEVICE_IN_ANC_HEADSET))) {
1421#endif
1422 if (mDevSettingsFlag & TTY_HCO) {
1423 return strdup(SND_USE_CASE_DEV_TTY_HEADSET_TX);
1424 } else if (mDevSettingsFlag & TTY_FULL) {
1425 return strdup(SND_USE_CASE_DEV_TTY_FULL_TX);
1426 } else if (mDevSettingsFlag & TTY_VCO) {
1427 if (!strncmp(mic_type, "analog", 6)) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001428 return strdup(SND_USE_CASE_DEV_TTY_HANDSET_ANALOG_TX);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001429 } else {
1430 return strdup(SND_USE_CASE_DEV_TTY_HANDSET_TX);
1431 }
1432 }
1433 } else if (devices & AudioSystem::DEVICE_IN_BUILTIN_MIC) {
1434 if (!strncmp(mic_type, "analog", 6)) {
1435 return strdup(SND_USE_CASE_DEV_HANDSET); /* HANDSET TX */
1436 } else {
1437 if (mDevSettingsFlag & DMIC_FLAG) {
ty.lee924f7982012-08-01 23:15:30 +09001438#ifdef USES_FLUENCE_INCALL
1439 if(callMode == AudioSystem::MODE_IN_CALL) {
1440 if (fluence_mode == FLUENCE_MODE_ENDFIRE) {
1441 return strdup(SND_USE_CASE_DEV_DUAL_MIC_ENDFIRE); /* DUALMIC EF TX */
1442 } else if (fluence_mode == FLUENCE_MODE_BROADSIDE) {
1443 return strdup(SND_USE_CASE_DEV_DUAL_MIC_BROADSIDE); /* DUALMIC BS TX */
1444 } else {
1445 return strdup(SND_USE_CASE_DEV_HANDSET); /* BUILTIN-MIC TX */
1446 }
1447 }
1448#else
Iliyan Malchev4765c432012-06-11 14:36:16 -07001449 if (((rxDevice != NULL) &&
1450 !strncmp(rxDevice, SND_USE_CASE_DEV_SPEAKER,
1451 (strlen(SND_USE_CASE_DEV_SPEAKER)+1))) ||
1452 !strncmp(curRxUCMDevice, SND_USE_CASE_DEV_SPEAKER,
1453 (strlen(SND_USE_CASE_DEV_SPEAKER)+1))) {
1454 if (fluence_mode == FLUENCE_MODE_ENDFIRE) {
1455 return strdup(SND_USE_CASE_DEV_SPEAKER_DUAL_MIC_ENDFIRE); /* DUALMIC EF TX */
1456 } else if (fluence_mode == FLUENCE_MODE_BROADSIDE) {
1457 return strdup(SND_USE_CASE_DEV_SPEAKER_DUAL_MIC_BROADSIDE); /* DUALMIC BS TX */
1458 }
1459 } else {
1460 if (fluence_mode == FLUENCE_MODE_ENDFIRE) {
1461 return strdup(SND_USE_CASE_DEV_DUAL_MIC_ENDFIRE); /* DUALMIC EF TX */
1462 } else if (fluence_mode == FLUENCE_MODE_BROADSIDE) {
1463 return strdup(SND_USE_CASE_DEV_DUAL_MIC_BROADSIDE); /* DUALMIC BS TX */
1464 }
1465 }
ty.lee924f7982012-08-01 23:15:30 +09001466#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001467 } else if (mDevSettingsFlag & QMIC_FLAG){
1468 return strdup(SND_USE_CASE_DEV_QUAD_MIC);
ty.lee924f7982012-08-01 23:15:30 +09001469 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001470#ifdef QCOM_SSR_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001471 else if (mDevSettingsFlag & SSRQMIC_FLAG){
Iliyan Malchev4113f342012-06-11 14:39:47 -07001472 ALOGV("return SSRQMIC_FLAG: 0x%x devices:0x%x",mDevSettingsFlag,devices);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001473 // Mapping for quad mic input device.
1474 return strdup(SND_USE_CASE_DEV_SSR_QUAD_MIC); /* SSR Quad MIC */
ty.lee924f7982012-08-01 23:15:30 +09001475 }
Iliyan Malchev4765c432012-06-11 14:36:16 -07001476#endif
ty.lee74060de2012-08-02 00:47:00 +09001477#ifdef SEPERATED_AUDIO_INPUT
1478 if(input_source == AUDIO_SOURCE_VOICE_RECOGNITION) {
ty.lee74060de2012-08-02 00:47:00 +09001479 return strdup(SND_USE_CASE_DEV_VOICE_RECOGNITION ); /* VOICE RECOGNITION TX */
ty.lee74060de2012-08-02 00:47:00 +09001480 }
1481#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001482 else {
ty.lee74060de2012-08-02 00:47:00 +09001483 return strdup(SND_USE_CASE_DEV_HANDSET); /* BUILTIN-MIC TX */
Iliyan Malchev4765c432012-06-11 14:36:16 -07001484 }
1485 }
1486 } else if (devices & AudioSystem::DEVICE_IN_AUX_DIGITAL) {
1487 return strdup(SND_USE_CASE_DEV_HDMI_TX); /* HDMI TX */
Ajay Dudani9746c472012-06-18 16:01:16 -07001488#ifdef QCOM_ANC_HEADSET_ENABLED
ehgrace.kim249f87d2012-08-12 20:40:32 -07001489 } else if (devices & AudioSystem::DEVICE_IN_ANC_HEADSET) {
Iliyan Malchev4765c432012-06-11 14:36:16 -07001490 return strdup(SND_USE_CASE_DEV_HEADSET); /* HEADSET TX */
1491#endif
ehgrace.kim249f87d2012-08-12 20:40:32 -07001492 } else if (devices & AudioSystem::DEVICE_IN_WIRED_HEADSET) {
ty.lee925596f2012-09-12 18:23:59 +09001493 if (callMode == AudioSystem::MODE_IN_CALL) {
1494 return strdup(SND_USE_CASE_DEV_VOC_HEADSET); /* Voice HEADSET TX */
1495 } else
1496 return strdup(SND_USE_CASE_DEV_HEADSET); /* HEADSET TX */
Iliyan Malchev4765c432012-06-11 14:36:16 -07001497 } else if (devices & AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
1498 if (btsco_samplerate == BTSCO_RATE_16KHZ)
1499 return strdup(SND_USE_CASE_DEV_BTSCO_WB_TX); /* BTSCO TX*/
1500 else
1501 return strdup(SND_USE_CASE_DEV_BTSCO_NB_TX); /* BTSCO TX*/
Ajay Dudani9746c472012-06-18 16:01:16 -07001502#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001503 } else if ((devices & AudioSystem::DEVICE_IN_ANLG_DOCK_HEADSET) ||
1504 (devices & AudioSystem::DEVICE_IN_PROXY)) {
1505 return strdup(SND_USE_CASE_DEV_PROXY_TX); /* PROXY TX */
1506#endif
1507 } else if ((devices & AudioSystem::DEVICE_IN_COMMUNICATION) ||
1508 (devices & AudioSystem::DEVICE_IN_VOICE_CALL)) {
1509 /* Nothing to be done, use current active device */
1510 if (strncmp(curTxUCMDevice, "None", 4)) {
1511 return strdup(curTxUCMDevice);
1512 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001513#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001514 } else if ((devices & AudioSystem::DEVICE_IN_FM_RX) ||
1515 (devices & AudioSystem::DEVICE_IN_FM_RX_A2DP)) {
1516 /* Nothing to be done, use current tx device or set dummy device */
1517 if (strncmp(curTxUCMDevice, "None", 4)) {
1518 return strdup(curTxUCMDevice);
1519 } else {
1520 return strdup(SND_USE_CASE_DEV_DUMMY_TX);
1521 }
1522#endif
1523 } else if ((devices & AudioSystem::DEVICE_IN_AMBIENT) ||
1524 (devices & AudioSystem::DEVICE_IN_BACK_MIC)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001525 ALOGI("No proper mapping found with UCM device list, setting default");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001526 if (!strncmp(mic_type, "analog", 6)) {
1527 return strdup(SND_USE_CASE_DEV_HANDSET); /* HANDSET TX */
1528 } else {
ty.lee925596f2012-09-12 18:23:59 +09001529 if (callMode == AudioSystem::MODE_IN_CALL) {
1530 return strdup(SND_USE_CASE_DEV_VOC_LINE); /* Voice BUILTIN-MIC TX */
ty.lee87459f02012-09-29 18:49:05 +09001531#ifdef SEPERATED_AUDIO_INPUT
1532 } else if(input_source == AUDIO_SOURCE_CAMCORDER) {
1533 return strdup(SND_USE_CASE_DEV_CAMCORDER_TX ); /* CAMCORDER TX */
1534#endif
ty.lee925596f2012-09-12 18:23:59 +09001535 } else
1536 return strdup(SND_USE_CASE_DEV_LINE); /* BUILTIN-MIC TX */
Iliyan Malchev4765c432012-06-11 14:36:16 -07001537 }
1538 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001539 ALOGD("No valid input device: %u", devices);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001540 }
1541 }
1542 return NULL;
1543}
1544
1545void s_set_voice_volume(int vol)
1546{
1547 int err = 0;
SathishKumar Mani9efed762012-09-18 18:52:48 -07001548 ALOGV("s_set_voice_volume: volume %d", vol);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001549 ALSAControl control("/dev/snd/controlC0");
1550 control.set("Voice Rx Volume", vol, 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_volume == NULL) {
1555 ALOGE("dlsym:Error:%s Loading csd_client_volume", dlerror());
1556 } else {
1557 err = csd_volume(vol);
1558 if (err < 0) {
1559 ALOGE("s_set_voice_volume: csd_client error %d", err);
1560 }
SathishKumar Manie42406e2012-08-29 16:25:54 -07001561 }
Iliyan Malchev4113f342012-06-11 14:39:47 -07001562#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001563 }
1564}
1565
1566void s_set_volte_volume(int vol)
1567{
SathishKumar Mani9efed762012-09-18 18:52:48 -07001568 ALOGV("s_set_volte_volume: volume %d", vol);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001569 ALSAControl control("/dev/snd/controlC0");
1570 control.set("VoLTE Rx Volume", vol, 0);
1571}
1572
1573
1574void s_set_voip_volume(int vol)
1575{
SathishKumar Mani9efed762012-09-18 18:52:48 -07001576 ALOGV("s_set_voip_volume: volume %d", vol);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001577 ALSAControl control("/dev/snd/controlC0");
1578 control.set("Voip Rx Volume", vol, 0);
1579}
1580void s_set_mic_mute(int state)
1581{
1582 int err = 0;
SathishKumar Mani9efed762012-09-18 18:52:48 -07001583 ALOGV("s_set_mic_mute: state %d", state);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001584 ALSAControl control("/dev/snd/controlC0");
1585 control.set("Voice Tx Mute", state, 0);
1586
1587 if (platform_is_Fusion3()) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001588#ifdef QCOM_CSDCLIENT_ENABLED
SathishKumar Mani5ff7a022012-09-14 11:36:35 -07001589 if (csd_mic_mute == NULL) {
1590 ALOGE("dlsym:Error:%s Loading csd_mic_mute", dlerror());
1591 } else {
1592 err=csd_mic_mute(state);
1593 if (err < 0) {
1594 ALOGE("s_set_mic_mute: csd_client error %d", err);
1595 }
Iliyan Malchev4765c432012-06-11 14:36:16 -07001596 }
Iliyan Malchev4113f342012-06-11 14:39:47 -07001597#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001598 }
1599}
1600void s_set_volte_mic_mute(int state)
1601{
SathishKumar Mani9efed762012-09-18 18:52:48 -07001602 ALOGV("s_set_volte_mic_mute: state %d", state);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001603 ALSAControl control("/dev/snd/controlC0");
1604 control.set("VoLTE Tx Mute", state, 0);
1605}
1606
1607void s_set_voip_mic_mute(int state)
1608{
SathishKumar Mani9efed762012-09-18 18:52:48 -07001609 ALOGV("s_set_voip_mic_mute: state %d", state);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001610 ALSAControl control("/dev/snd/controlC0");
1611 control.set("Voip Tx Mute", state, 0);
1612}
1613
1614void s_set_voip_config(int mode, int rate)
1615{
SathishKumar Mani9efed762012-09-18 18:52:48 -07001616 ALOGV("s_set_voip_config: mode %d,rate %d", mode, rate);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001617 ALSAControl control("/dev/snd/controlC0");
1618 char** setValues;
1619 setValues = (char**)malloc(2*sizeof(char*));
1620 if (setValues == NULL) {
1621 return;
1622 }
1623 setValues[0] = (char*)malloc(4*sizeof(char));
1624 if (setValues[0] == NULL) {
1625 free(setValues);
1626 return;
1627 }
1628
1629 setValues[1] = (char*)malloc(8*sizeof(char));
1630 if (setValues[1] == NULL) {
1631 free(setValues);
1632 free(setValues[0]);
1633 return;
1634 }
1635
1636 sprintf(setValues[0], "%d",mode);
1637 sprintf(setValues[1], "%d",rate);
1638
1639 control.setext("Voip Mode Rate Config", 2, setValues);
1640 free(setValues[1]);
1641 free(setValues[0]);
1642 free(setValues);
1643 return;
1644}
1645
1646void s_set_btsco_rate(int rate)
1647{
1648 btsco_samplerate = rate;
1649}
1650
1651void s_enable_wide_voice(bool flag)
1652{
1653 int err = 0;
1654
SathishKumar Mani9efed762012-09-18 18:52:48 -07001655 ALOGV("s_enable_wide_voice: flag %d", flag);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001656 ALSAControl control("/dev/snd/controlC0");
1657 if(flag == true) {
1658 control.set("Widevoice Enable", 1, 0);
1659 } else {
1660 control.set("Widevoice Enable", 0, 0);
1661 }
1662
1663 if (platform_is_Fusion3()) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001664#ifdef QCOM_CSDCLIENT_ENABLED
SathishKumar Mani5ff7a022012-09-14 11:36:35 -07001665 if (csd_wide_voice == NULL) {
1666 ALOGE("dlsym:Error:%s Loading csd_wide_voice", dlerror());
1667 } else {
1668 err = csd_wide_voice(flag);
1669 if (err < 0) {
1670 ALOGE("enableWideVoice: csd_client_wide_voice error %d", err);
1671 }
Iliyan Malchev4765c432012-06-11 14:36:16 -07001672 }
Iliyan Malchev4113f342012-06-11 14:39:47 -07001673#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001674 }
1675}
1676
1677void s_set_voc_rec_mode(uint8_t mode)
1678{
SathishKumar Mani9efed762012-09-18 18:52:48 -07001679 ALOGV("s_set_voc_rec_mode: mode %d", mode);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001680 ALSAControl control("/dev/snd/controlC0");
1681 control.set("Incall Rec Mode", mode, 0);
1682}
1683
1684void s_enable_fens(bool flag)
1685{
1686 int err = 0;
1687
SathishKumar Mani9efed762012-09-18 18:52:48 -07001688 ALOGV("s_enable_fens: flag %d", flag);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001689 ALSAControl control("/dev/snd/controlC0");
1690 if(flag == true) {
1691 control.set("FENS Enable", 1, 0);
1692 } else {
1693 control.set("FENS Enable", 0, 0);
1694 }
1695
1696 if (platform_is_Fusion3()) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001697#ifdef QCOM_CSDCLIENT_ENABLED
SathishKumar Mani5ff7a022012-09-14 11:36:35 -07001698 if (csd_fens == NULL) {
1699 ALOGE("dlsym:Error:%s Loading csd_fens", dlerror());
1700 } else {
1701 err = csd_fens(flag);
1702 if (err < 0) {
1703 ALOGE("s_enable_fens: csd_client error %d", err);
1704 }
Iliyan Malchev4765c432012-06-11 14:36:16 -07001705 }
Iliyan Malchev4113f342012-06-11 14:39:47 -07001706#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001707 }
1708}
1709
1710void s_enable_slow_talk(bool flag)
1711{
1712 int err = 0;
1713
SathishKumar Mani9efed762012-09-18 18:52:48 -07001714 ALOGV("s_enable_slow_talk: flag %d", flag);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001715 ALSAControl control("/dev/snd/controlC0");
1716 if(flag == true) {
1717 control.set("Slowtalk Enable", 1, 0);
1718 } else {
1719 control.set("Slowtalk Enable", 0, 0);
1720 }
1721
1722 if (platform_is_Fusion3()) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001723#ifdef QCOM_CSDCLIENT_ENABLED
SathishKumar Mani5ff7a022012-09-14 11:36:35 -07001724 if (csd_slow_talk == NULL) {
1725 ALOGE("dlsym:Error:%s Loading csd_slow_talk", dlerror());
1726 } else {
1727 err = csd_slow_talk(flag);
1728 if (err < 0) {
1729 ALOGE("s_enable_slow_talk: csd_client error %d", err);
1730 }
Iliyan Malchev4765c432012-06-11 14:36:16 -07001731 }
Iliyan Malchev4113f342012-06-11 14:39:47 -07001732#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001733 }
1734}
1735
1736void s_set_flags(uint32_t flags)
1737{
Iliyan Malchev4113f342012-06-11 14:39:47 -07001738 ALOGV("s_set_flags: flags %d", flags);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001739 mDevSettingsFlag = flags;
1740}
1741
1742static status_t s_set_compressed_vol(int value)
1743{
1744 status_t err = NO_ERROR;
1745
1746 ALSAControl control("/dev/snd/controlC0");
1747 control.set("COMPRESSED RX Volume",value,0);
1748
1749 return err;
1750}
1751
ty.lee74060de2012-08-02 00:47:00 +09001752#ifdef SEPERATED_AUDIO_INPUT
1753void s_setInput(int input)
1754{
1755 input_source = input;
1756 ALOGD("s_setInput() : input_source = %d",input_source);
1757}
1758#endif
SathishKumar Mani5ff7a022012-09-14 11:36:35 -07001759
1760#ifdef QCOM_CSDCLIENT_ENABLED
1761static void s_set_csd_handle(void* handle)
1762{
1763 csd_handle = static_cast<void*>(handle);
1764 ALOGI("%s csd_handle: %p", __func__, csd_handle);
1765
1766 csd_disable_device = (int (*)())::dlsym(csd_handle,"csd_client_disable_device");
1767 csd_enable_device = (int (*)(int,int,uint32_t))::dlsym(csd_handle,"csd_client_enable_device");
1768 csd_start_voice = (int (*)())::dlsym(csd_handle,"csd_client_start_voice");
1769 csd_stop_voice = (int (*)())::dlsym(csd_handle,"csd_client_stop_voice");
1770 csd_volume = (int (*)(int))::dlsym(csd_handle,"csd_client_volume");
1771 csd_mic_mute = (int (*)(int))::dlsym(csd_handle,"csd_client_mic_mute");
1772 csd_wide_voice = (int (*)(uint8_t))::dlsym(csd_handle,"csd_client_wide_voice");
1773 csd_fens = (int (*)(uint8_t))::dlsym(csd_handle,"csd_client_fens");
1774 csd_slow_talk = (int (*)(uint8_t))::dlsym(csd_handle,"csd_client_slow_talk");
1775}
1776#endif
1777
Iliyan Malchev4765c432012-06-11 14:36:16 -07001778}