blob: 18a28d2938a543fa63bb8d7b3838fac61d9315ed [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;
Iliyan Malchev4765c432012-06-11 14:36:16 -0700101static ALSAUseCaseList mUseCaseList;
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700102static void *csd_handle;
Iliyan Malchev4765c432012-06-11 14:36:16 -0700103
104static hw_module_methods_t s_module_methods = {
105 open : s_device_open
106};
107
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700108extern "C" {
109hw_module_t HAL_MODULE_INFO_SYM = {
Iliyan Malchev4765c432012-06-11 14:36:16 -0700110 tag : HARDWARE_MODULE_TAG,
111 version_major : 1,
112 version_minor : 0,
113 id : ALSA_HARDWARE_MODULE_ID,
114 name : "QCOM ALSA module",
115 author : "QuIC Inc",
116 methods : &s_module_methods,
117 dso : 0,
118 reserved : {0,},
119};
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700120}
Iliyan Malchev4765c432012-06-11 14:36:16 -0700121
122static int s_device_open(const hw_module_t* module, const char* name,
123 hw_device_t** device)
124{
125 char value[128];
126 alsa_device_t *dev;
127 dev = (alsa_device_t *) malloc(sizeof(*dev));
128 if (!dev) return -ENOMEM;
129
130 memset(dev, 0, sizeof(*dev));
131
132 /* initialize the procs */
133 dev->common.tag = HARDWARE_DEVICE_TAG;
134 dev->common.version = 0;
135 dev->common.module = (hw_module_t *) module;
136 dev->common.close = s_device_close;
137 dev->init = s_init;
138 dev->open = s_open;
139 dev->close = s_close;
140 dev->route = s_route;
141 dev->standby = s_standby;
142 dev->startVoiceCall = s_start_voice_call;
143 dev->startVoipCall = s_start_voip_call;
144 dev->startFm = s_start_fm;
145 dev->setVoiceVolume = s_set_voice_volume;
146 dev->setVoipVolume = s_set_voip_volume;
147 dev->setMicMute = s_set_mic_mute;
148 dev->setVoipMicMute = s_set_voip_mic_mute;
149 dev->setVoipConfig = s_set_voip_config;
150 dev->setFmVolume = s_set_fm_vol;
151 dev->setBtscoRate = s_set_btsco_rate;
152 dev->setLpaVolume = s_set_lpa_vol;
153 dev->enableWideVoice = s_enable_wide_voice;
154 dev->enableFENS = s_enable_fens;
155 dev->setFlags = s_set_flags;
156 dev->setCompressedVolume = s_set_compressed_vol;
157 dev->enableSlowTalk = s_enable_slow_talk;
158 dev->setVocRecMode = s_set_voc_rec_mode;
159 dev->setVoLTEMicMute = s_set_volte_mic_mute;
160 dev->setVoLTEVolume = s_set_volte_volume;
ty.lee74060de2012-08-02 00:47:00 +0900161#ifdef SEPERATED_AUDIO_INPUT
162 dev->setInput = s_setInput;
163#endif
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700164#ifdef QCOM_CSDCLIENT_ENABLED
165 dev->setCsdHandle = s_set_csd_handle;
166#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700167 *device = &dev->common;
168
169 property_get("persist.audio.handset.mic",value,"0");
170 strlcpy(mic_type, value, sizeof(mic_type));
171 property_get("persist.audio.fluence.mode",value,"0");
172 if (!strcmp("broadside", value)) {
173 fluence_mode = FLUENCE_MODE_BROADSIDE;
174 } else {
175 fluence_mode = FLUENCE_MODE_ENDFIRE;
176 }
177 strlcpy(curRxUCMDevice, "None", sizeof(curRxUCMDevice));
178 strlcpy(curTxUCMDevice, "None", sizeof(curTxUCMDevice));
SathishKumar Mani9efed762012-09-18 18:52:48 -0700179 ALOGV("ALSA module opened");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700180
181 return 0;
182}
183
184static int s_device_close(hw_device_t* device)
185{
186 free(device);
187 device = NULL;
188 return 0;
189}
190
191// ----------------------------------------------------------------------------
192
193static const int DEFAULT_SAMPLE_RATE = ALSA_DEFAULT_SAMPLE_RATE;
194
195static void switchDevice(alsa_handle_t *handle, uint32_t devices, uint32_t mode);
196static char *getUCMDevice(uint32_t devices, int input, char *rxDevice);
197static void disableDevice(alsa_handle_t *handle);
198int getUseCaseType(const char *useCase);
199
200static int callMode = AudioSystem::MODE_NORMAL;
201// ----------------------------------------------------------------------------
202
203bool platform_is_Fusion3()
204{
205 char platform[128], baseband[128];
206 property_get("ro.board.platform", platform, "");
207 property_get("ro.baseband", baseband, "");
208 if (!strcmp("msm8960", platform) && !strcmp("mdm", baseband))
209 return true;
210 else
211 return false;
212}
213
214int deviceName(alsa_handle_t *handle, unsigned flags, char **value)
215{
216 int ret = 0;
217 char ident[70];
218
219 if (flags & PCM_IN) {
220 strlcpy(ident, "CapturePCM/", sizeof(ident));
221 } else {
222 strlcpy(ident, "PlaybackPCM/", sizeof(ident));
223 }
224 strlcat(ident, handle->useCase, sizeof(ident));
225 ret = snd_use_case_get(handle->ucMgr, ident, (const char **)value);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700226 ALOGD("Device value returned is %s", (*value));
Iliyan Malchev4765c432012-06-11 14:36:16 -0700227 return ret;
228}
229
SathishKumar Manib357a772012-09-25 23:28:29 -0700230status_t setHDMIChannelCount()
231{
232 status_t err = NO_ERROR;
233 int channel_count = 0;
234 const char *channel_cnt_str = NULL;
235 EDID_AUDIO_INFO info = { 0 };
236
237 ALSAControl control("/dev/snd/controlC0");
238 if (AudioUtil::getHDMIAudioSinkCaps(&info)) {
239 for (int i = 0; i < info.nAudioBlocks && i < MAX_EDID_BLOCKS; i++) {
240 if (info.AudioBlocksArray[i].nChannels > channel_count &&
241 info.AudioBlocksArray[i].nChannels <= MAX_HDMI_CHANNEL_CNT) {
242 channel_count = info.AudioBlocksArray[i].nChannels;
243 }
244 }
245 }
246
247 switch (channel_count) {
248 case 6: channel_cnt_str = "Six"; break;
249 case 5: channel_cnt_str = "Five"; break;
250 case 4: channel_cnt_str = "Four"; break;
251 case 3: channel_cnt_str = "Three"; break;
252 default: channel_cnt_str = "Two"; break;
253 }
254 ALOGD("HDMI channel count: %s", channel_cnt_str);
255 control.set("HDMI_RX Channels", channel_cnt_str);
256
257 return err;
258}
259
Iliyan Malchev4765c432012-06-11 14:36:16 -0700260status_t setHardwareParams(alsa_handle_t *handle)
261{
262 struct snd_pcm_hw_params *params;
263 unsigned long bufferSize, reqBuffSize;
264 unsigned int periodTime, bufferTime;
265 unsigned int requestedRate = handle->sampleRate;
266 int status = 0;
267 int channels = handle->channels;
268 snd_pcm_format_t format = SNDRV_PCM_FORMAT_S16_LE;
269
270 params = (snd_pcm_hw_params*) calloc(1, sizeof(struct snd_pcm_hw_params));
271 if (!params) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700272 ALOGE("Failed to allocate ALSA hardware parameters!");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700273 return NO_INIT;
274 }
275
276 reqBuffSize = handle->bufferSize;
Iliyan Malchev4113f342012-06-11 14:39:47 -0700277 ALOGD("setHardwareParams: reqBuffSize %d channels %d sampleRate %d",
Iliyan Malchev4765c432012-06-11 14:36:16 -0700278 (int) reqBuffSize, handle->channels, handle->sampleRate);
279
Ajay Dudani9746c472012-06-18 16:01:16 -0700280#ifdef QCOM_SSR_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700281 if (channels == 6) {
282 if (!strncmp(handle->useCase, SND_USE_CASE_VERB_HIFI_REC, strlen(SND_USE_CASE_VERB_HIFI_REC))
283 || !strncmp(handle->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, strlen(SND_USE_CASE_MOD_CAPTURE_MUSIC))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700284 ALOGV("HWParams: Use 4 channels in kernel for 5.1(%s) recording ", handle->useCase);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700285 channels = 4;
Iliyan Malchev4765c432012-06-11 14:36:16 -0700286 }
287 }
288#endif
289
290 param_init(params);
291 param_set_mask(params, SNDRV_PCM_HW_PARAM_ACCESS,
292 SNDRV_PCM_ACCESS_RW_INTERLEAVED);
293 if (handle->format != SNDRV_PCM_FORMAT_S16_LE) {
Ajay Dudani9746c472012-06-18 16:01:16 -0700294 if (handle->format == AudioSystem::AMR_NB
295 || handle->format == AudioSystem::AMR_WB
296#ifdef QCOM_QCHAT_ENABLED
297 || handle->format == AudioSystem::EVRC
298 || handle->format == AudioSystem::EVRCB
299 || handle->format == AudioSystem::EVRCWB
300#endif
301 )
Iliyan Malchev4765c432012-06-11 14:36:16 -0700302 format = SNDRV_PCM_FORMAT_SPECIAL;
303 }
304 param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
305 format);
306 param_set_mask(params, SNDRV_PCM_HW_PARAM_SUBFORMAT,
307 SNDRV_PCM_SUBFORMAT_STD);
SathishKumar Mani77780382012-09-21 20:58:33 -0700308 param_set_int(params, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, reqBuffSize);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700309 param_set_int(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS, 16);
310 param_set_int(params, SNDRV_PCM_HW_PARAM_FRAME_BITS,
311 channels * 16);
312 param_set_int(params, SNDRV_PCM_HW_PARAM_CHANNELS,
313 channels);
314 param_set_int(params, SNDRV_PCM_HW_PARAM_RATE, handle->sampleRate);
315 param_set_hw_refine(handle->handle, params);
316
317 if (param_set_hw_params(handle->handle, params)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700318 ALOGE("cannot set hw params");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700319 return NO_INIT;
320 }
321 param_dump(params);
322
323 handle->handle->buffer_size = pcm_buffer_size(params);
324 handle->handle->period_size = pcm_period_size(params);
325 handle->handle->period_cnt = handle->handle->buffer_size/handle->handle->period_size;
Iliyan Malchev4113f342012-06-11 14:39:47 -0700326 ALOGD("setHardwareParams: buffer_size %d, period_size %d, period_cnt %d",
Iliyan Malchev4765c432012-06-11 14:36:16 -0700327 handle->handle->buffer_size, handle->handle->period_size,
328 handle->handle->period_cnt);
329 handle->handle->rate = handle->sampleRate;
330 handle->handle->channels = handle->channels;
331 handle->periodSize = handle->handle->period_size;
332 if (strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_REC) &&
333 strcmp(handle->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC) &&
334 (6 != handle->channels)) {
335 //Do not update buffersize for 5.1 recording
336 handle->bufferSize = handle->handle->period_size;
337 }
338
339 return NO_ERROR;
340}
341
342status_t setSoftwareParams(alsa_handle_t *handle)
343{
344 struct snd_pcm_sw_params* params;
345 struct pcm* pcm = handle->handle;
346
347 unsigned long periodSize = pcm->period_size;
348 int channels = handle->channels;
349
350 params = (snd_pcm_sw_params*) calloc(1, sizeof(struct snd_pcm_sw_params));
351 if (!params) {
352 LOG_ALWAYS_FATAL("Failed to allocate ALSA software parameters!");
353 return NO_INIT;
354 }
355
Ajay Dudani9746c472012-06-18 16:01:16 -0700356#ifdef QCOM_SSR_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700357 if (channels == 6) {
358 if (!strncmp(handle->useCase, SND_USE_CASE_VERB_HIFI_REC, strlen(SND_USE_CASE_VERB_HIFI_REC))
359 || !strncmp(handle->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, strlen(SND_USE_CASE_MOD_CAPTURE_MUSIC))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700360 ALOGV("SWParams: Use 4 channels in kernel for 5.1(%s) recording ", handle->useCase);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700361 channels = 4;
362 }
363 }
364#endif
365
366 // Get the current software parameters
367 params->tstamp_mode = SNDRV_PCM_TSTAMP_NONE;
368 params->period_step = 1;
369 if(((!strcmp(handle->useCase,SND_USE_CASE_MOD_PLAY_VOIP)) ||
370 (!strcmp(handle->useCase,SND_USE_CASE_VERB_IP_VOICECALL)))){
Iliyan Malchev4113f342012-06-11 14:39:47 -0700371 ALOGV("setparam: start & stop threshold for Voip ");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700372 params->avail_min = handle->channels - 1 ? periodSize/4 : periodSize/2;
373 params->start_threshold = periodSize/2;
374 params->stop_threshold = INT_MAX;
375 } else {
SathishKumar Manibf1c8742012-09-25 23:34:51 -0700376 params->avail_min = periodSize/(channels * 2);
377 params->start_threshold = periodSize/(channels * 2);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700378 params->stop_threshold = INT_MAX;
379 }
380 params->silence_threshold = 0;
381 params->silence_size = 0;
382
383 if (param_set_sw_params(handle->handle, params)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700384 ALOGE("cannot set sw params");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700385 return NO_INIT;
386 }
387 return NO_ERROR;
388}
389
390void switchDevice(alsa_handle_t *handle, uint32_t devices, uint32_t mode)
391{
392 const char **mods_list;
393 use_case_t useCaseNode;
394 unsigned usecase_type = 0;
395 bool inCallDevSwitch = false;
396 char *rxDevice, *txDevice, ident[70], *use_case = NULL;
397 int err = 0, index, mods_size;
398 int rx_dev_id, tx_dev_id;
SathishKumar Mani9efed762012-09-18 18:52:48 -0700399 ALOGD("%s: device %d mode:%d", __FUNCTION__, devices, mode);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700400
401 if ((mode == AudioSystem::MODE_IN_CALL) || (mode == AudioSystem::MODE_IN_COMMUNICATION)) {
402 if ((devices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) ||
403 (devices & AudioSystem::DEVICE_IN_WIRED_HEADSET)) {
404 devices = devices | (AudioSystem::DEVICE_OUT_WIRED_HEADSET |
405 AudioSystem::DEVICE_IN_WIRED_HEADSET);
406 } else if (devices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE) {
407 devices = devices | (AudioSystem::DEVICE_OUT_WIRED_HEADPHONE |
408 AudioSystem::DEVICE_IN_BUILTIN_MIC);
SathishKumar Manic669c272012-09-21 20:12:08 -0700409 } else if (devices & AudioSystem::DEVICE_IN_BUILTIN_MIC) {
410 if (mode == AudioSystem::MODE_IN_CALL) {
411 devices |= AudioSystem::DEVICE_OUT_EARPIECE;
412 }
413 } else if (devices & AudioSystem::DEVICE_OUT_EARPIECE) {
414 devices = devices | AudioSystem::DEVICE_IN_BUILTIN_MIC;
Iliyan Malchev4765c432012-06-11 14:36:16 -0700415 } else if (devices & AudioSystem::DEVICE_OUT_SPEAKER) {
ty.lee10dfa852012-08-01 21:09:45 +0900416 devices = devices | (AudioSystem::DEVICE_IN_BACK_MIC |
Iliyan Malchev4765c432012-06-11 14:36:16 -0700417 AudioSystem::DEVICE_OUT_SPEAKER);
418 } else if ((devices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO) ||
419 (devices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET) ||
420 (devices & AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET)) {
421 devices = devices | (AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET |
422 AudioSystem::DEVICE_OUT_BLUETOOTH_SCO);
Ajay Dudani9746c472012-06-18 16:01:16 -0700423#ifdef QCOM_ANC_HEADSET_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700424 } else if ((devices & AudioSystem::DEVICE_OUT_ANC_HEADSET) ||
425 (devices & AudioSystem::DEVICE_IN_ANC_HEADSET)) {
426 devices = devices | (AudioSystem::DEVICE_OUT_ANC_HEADSET |
427 AudioSystem::DEVICE_IN_ANC_HEADSET);
428 } else if (devices & AudioSystem::DEVICE_OUT_ANC_HEADPHONE) {
429 devices = devices | (AudioSystem::DEVICE_OUT_ANC_HEADPHONE |
430 AudioSystem::DEVICE_IN_BUILTIN_MIC);
431#endif
432 } else if (devices & AudioSystem::DEVICE_OUT_AUX_DIGITAL) {
Sungmin Choi6ebf0aa2012-09-28 16:09:12 -0700433 if (mode == AudioSystem::MODE_IN_CALL)
434 devices = devices | (AudioSystem::DEVICE_IN_BACK_MIC |
435 AudioSystem::DEVICE_OUT_SPEAKER);
436 else
437 devices = devices | (AudioSystem::DEVICE_OUT_AUX_DIGITAL |
438 AudioSystem::DEVICE_IN_BACK_MIC);
Ajay Dudani9746c472012-06-18 16:01:16 -0700439#ifdef QCOM_PROXY_DEVICE_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700440 } else if ((devices & AudioSystem::DEVICE_OUT_PROXY) ||
441 (devices & AudioSystem::DEVICE_IN_PROXY)) {
442 devices = devices | (AudioSystem::DEVICE_OUT_PROXY |
443 AudioSystem::DEVICE_IN_PROXY);
444#endif
445 }
446 }
Ajay Dudani9746c472012-06-18 16:01:16 -0700447#ifdef QCOM_SSR_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700448 if ((devices & AudioSystem::DEVICE_IN_BUILTIN_MIC) && ( 6 == handle->channels)) {
449 if (!strncmp(handle->useCase, SND_USE_CASE_VERB_HIFI_REC, strlen(SND_USE_CASE_VERB_HIFI_REC))
450 || !strncmp(handle->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, strlen(SND_USE_CASE_MOD_CAPTURE_MUSIC))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700451 ALOGV(" switchDevice , use ssr devices for channels:%d usecase:%s",handle->channels,handle->useCase);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700452 s_set_flags(SSRQMIC_FLAG);
453 }
454 }
455#endif
456
457 rxDevice = getUCMDevice(devices & AudioSystem::DEVICE_OUT_ALL, 0, NULL);
458 txDevice = getUCMDevice(devices & AudioSystem::DEVICE_IN_ALL, 1, rxDevice);
459
Iliyan Malchev4765c432012-06-11 14:36:16 -0700460 if ((rxDevice != NULL) && (txDevice != NULL)) {
461 if (((strncmp(rxDevice, curRxUCMDevice, MAX_STR_LEN)) ||
SathishKumar Manic669c272012-09-21 20:12:08 -0700462 (strncmp(txDevice, curTxUCMDevice, MAX_STR_LEN))) &&
463 ((mode == AudioSystem::MODE_IN_CALL) ||
464 (mode == AudioSystem::MODE_IN_COMMUNICATION)))
Iliyan Malchev4765c432012-06-11 14:36:16 -0700465 inCallDevSwitch = true;
466 }
Ajay Dudani91bf8912012-08-20 18:48:13 -0700467
468#ifdef QCOM_CSDCLIENT_ENABLED
SathishKumar Manic669c272012-09-21 20:12:08 -0700469 if (platform_is_Fusion3() && (inCallDevSwitch == true)) {
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700470 if (csd_disable_device == NULL) {
471 ALOGE("dlsym:Error:%s Loading csd_client_disable_device", dlerror());
472 } else {
473 err = csd_disable_device();
474 if (err < 0)
475 {
476 ALOGE("csd_client_disable_device, failed, error %d", err);
477 }
Ajay Dudani91bf8912012-08-20 18:48:13 -0700478 }
479 }
480#endif
481
Iliyan Malchev4765c432012-06-11 14:36:16 -0700482 snd_use_case_get(handle->ucMgr, "_verb", (const char **)&use_case);
483 mods_size = snd_use_case_get_list(handle->ucMgr, "_enamods", &mods_list);
484 if (rxDevice != NULL) {
485 if ((strncmp(curRxUCMDevice, "None", 4)) &&
486 ((strncmp(rxDevice, curRxUCMDevice, MAX_STR_LEN)) || (inCallDevSwitch == true))) {
487 if ((use_case != NULL) && (strncmp(use_case, SND_USE_CASE_VERB_INACTIVE,
488 strlen(SND_USE_CASE_VERB_INACTIVE)))) {
489 usecase_type = getUseCaseType(use_case);
490 if (usecase_type & USECASE_TYPE_RX) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700491 ALOGD("Deroute use case %s type is %d\n", use_case, usecase_type);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700492 strlcpy(useCaseNode.useCase, use_case, MAX_STR_LEN);
493 snd_use_case_set(handle->ucMgr, "_verb", SND_USE_CASE_VERB_INACTIVE);
494 mUseCaseList.push_front(useCaseNode);
495 }
496 }
497 if (mods_size) {
498 for(index = 0; index < mods_size; index++) {
499 usecase_type = getUseCaseType(mods_list[index]);
500 if (usecase_type & USECASE_TYPE_RX) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700501 ALOGD("Deroute use case %s type is %d\n", mods_list[index], usecase_type);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700502 strlcpy(useCaseNode.useCase, mods_list[index], MAX_STR_LEN);
503 snd_use_case_set(handle->ucMgr, "_dismod", mods_list[index]);
504 mUseCaseList.push_back(useCaseNode);
505 }
506 }
507 }
508 snd_use_case_set(handle->ucMgr, "_disdev", curRxUCMDevice);
509 }
510 }
511 if (txDevice != NULL) {
512 if ((strncmp(curTxUCMDevice, "None", 4)) &&
513 ((strncmp(txDevice, curTxUCMDevice, MAX_STR_LEN)) || (inCallDevSwitch == true))) {
514 if ((use_case != NULL) && (strncmp(use_case, SND_USE_CASE_VERB_INACTIVE,
515 strlen(SND_USE_CASE_VERB_INACTIVE)))) {
516 usecase_type = getUseCaseType(use_case);
517 if ((usecase_type & USECASE_TYPE_TX) && (!(usecase_type & USECASE_TYPE_RX))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700518 ALOGD("Deroute use case %s type is %d\n", use_case, usecase_type);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700519 strlcpy(useCaseNode.useCase, use_case, MAX_STR_LEN);
520 snd_use_case_set(handle->ucMgr, "_verb", SND_USE_CASE_VERB_INACTIVE);
521 mUseCaseList.push_front(useCaseNode);
522 }
523 }
524 if (mods_size) {
525 for(index = 0; index < mods_size; index++) {
526 usecase_type = getUseCaseType(mods_list[index]);
527 if ((usecase_type & USECASE_TYPE_TX) && (!(usecase_type & USECASE_TYPE_RX))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700528 ALOGD("Deroute use case %s type is %d\n", mods_list[index], usecase_type);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700529 strlcpy(useCaseNode.useCase, mods_list[index], MAX_STR_LEN);
530 snd_use_case_set(handle->ucMgr, "_dismod", mods_list[index]);
531 mUseCaseList.push_back(useCaseNode);
532 }
533 }
534 }
535 snd_use_case_set(handle->ucMgr, "_disdev", curTxUCMDevice);
536 }
537 }
SathishKumar Mani9efed762012-09-18 18:52:48 -0700538 ALOGD("%s,rxDev:%s, txDev:%s, curRxDev:%s, curTxDev:%s\n", __FUNCTION__, rxDevice, txDevice, curRxUCMDevice, curTxUCMDevice);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700539
540 if (rxDevice != NULL) {
541 snd_use_case_set(handle->ucMgr, "_enadev", rxDevice);
542 strlcpy(curRxUCMDevice, rxDevice, sizeof(curRxUCMDevice));
Ajay Dudani9746c472012-06-18 16:01:16 -0700543#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700544 if (devices & AudioSystem::DEVICE_OUT_FM)
545 s_set_fm_vol(fmVolume);
546#endif
547 }
548 if (txDevice != NULL) {
549 snd_use_case_set(handle->ucMgr, "_enadev", txDevice);
550 strlcpy(curTxUCMDevice, txDevice, sizeof(curTxUCMDevice));
551 }
552 for(ALSAUseCaseList::iterator it = mUseCaseList.begin(); it != mUseCaseList.end(); ++it) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700553 ALOGD("Route use case %s\n", it->useCase);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700554 if ((use_case != NULL) && (strncmp(use_case, SND_USE_CASE_VERB_INACTIVE,
555 strlen(SND_USE_CASE_VERB_INACTIVE))) && (!strncmp(use_case, it->useCase, MAX_UC_LEN))) {
556 snd_use_case_set(handle->ucMgr, "_verb", it->useCase);
557 } else {
558 snd_use_case_set(handle->ucMgr, "_enamod", it->useCase);
559 }
560 }
561 if (!mUseCaseList.empty())
562 mUseCaseList.clear();
563 if (use_case != NULL) {
564 free(use_case);
565 use_case = NULL;
566 }
Iliyan Malchev4113f342012-06-11 14:39:47 -0700567 ALOGD("switchDevice: curTxUCMDevivce %s curRxDevDevice %s", curTxUCMDevice, curRxUCMDevice);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700568
SathishKumar Manic669c272012-09-21 20:12:08 -0700569 if (platform_is_Fusion3() && (inCallDevSwitch == true)) {
Iliyan Malchev4765c432012-06-11 14:36:16 -0700570 /* get tx acdb id */
571 memset(&ident,0,sizeof(ident));
572 strlcpy(ident, "ACDBID/", sizeof(ident));
573 strlcat(ident, curTxUCMDevice, sizeof(ident));
574 tx_dev_id = snd_use_case_get(handle->ucMgr, ident, NULL);
575
576 /* get rx acdb id */
577 memset(&ident,0,sizeof(ident));
578 strlcpy(ident, "ACDBID/", sizeof(ident));
579 strlcat(ident, curRxUCMDevice, sizeof(ident));
580 rx_dev_id = snd_use_case_get(handle->ucMgr, ident, NULL);
581
ehgrace.kim91e9fad2012-07-02 18:27:28 -0700582 if (((rx_dev_id == DEVICE_SPEAKER_MONO_RX_ACDB_ID ) || (rx_dev_id == DEVICE_SPEAKER_STEREO_RX_ACDB_ID ))
SathishKumar Manibf1c8742012-09-25 23:34:51 -0700583 && tx_dev_id == DEVICE_HANDSET_TX_ACDB_ID) {
Iliyan Malchev4765c432012-06-11 14:36:16 -0700584 tx_dev_id = DEVICE_SPEAKER_TX_ACDB_ID;
585 }
586
Ajay Dudani9746c472012-06-18 16:01:16 -0700587#ifdef QCOM_CSDCLIENT_ENABLED
Iliyan Malchev4113f342012-06-11 14:39:47 -0700588 ALOGV("rx_dev_id=%d, tx_dev_id=%d\n", rx_dev_id, tx_dev_id);
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700589 if (csd_enable_device == NULL) {
590 ALOGE("dlsym:Error:%s Loading csd_client_enable_device", dlerror());
591 } else {
592 err = csd_enable_device(rx_dev_id, tx_dev_id, mDevSettingsFlag);
593 if (err < 0)
594 {
595 ALOGE("csd_client_disable_device failed, error %d", err);
596 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700597 }
Iliyan Malchev4113f342012-06-11 14:39:47 -0700598#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700599 }
600
601 if (rxDevice != NULL) {
Iliyan Malchev4765c432012-06-11 14:36:16 -0700602 free(rxDevice);
603 rxDevice = NULL;
604 }
605 if (txDevice != NULL) {
606 free(txDevice);
607 txDevice = NULL;
608 }
609}
610
611// ----------------------------------------------------------------------------
612
613static status_t s_init(alsa_device_t *module, ALSAHandleList &list)
614{
SathishKumar Mani9efed762012-09-18 18:52:48 -0700615 ALOGV("s_init: Initializing devices for ALSA module");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700616
617 list.clear();
618
619 return NO_ERROR;
620}
621
622static status_t s_open(alsa_handle_t *handle)
623{
624 char *devName;
625 unsigned flags = 0;
626 int err = NO_ERROR;
627
SathishKumar Manib357a772012-09-25 23:28:29 -0700628 if(handle->devices & AudioSystem::DEVICE_OUT_AUX_DIGITAL) {
629 err = setHDMIChannelCount();
630 if(err != OK) {
631 ALOGE("setHDMIChannelCount err = %d", err);
632 return err;
633 }
634 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700635 /* No need to call s_close for LPA as pcm device open and close is handled by LPAPlayer in stagefright */
636 if((!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER)) || (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_LPA))
637 ||(!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 -0700638 ALOGV("s_open: Opening LPA /Tunnel playback");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700639 return NO_ERROR;
640 }
641
642 s_close(handle);
643
SathishKumar Mani9efed762012-09-18 18:52:48 -0700644 ALOGV("s_open: handle %p", handle);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700645
646 // ASoC multicomponent requires a valid path (frontend/backend) for
647 // the device to be opened
648
649 // The PCM stream is opened in blocking mode, per ALSA defaults. The
650 // AudioFlinger seems to assume blocking mode too, so asynchronous mode
651 // should not be used.
SathishKumar Mani88613382012-08-13 18:40:18 -0700652 if ((!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER)) ||
653 (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_LPA)) ||
654 (!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_TUNNEL)) ||
655 (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_TUNNEL))) {
656 ALOGV("LPA/tunnel use case");
657 flags |= PCM_MMAP;
658 flags |= DEBUG_ON;
659 } else if ((!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI)) ||
SathishKumar Manibf1c8742012-09-25 23:34:51 -0700660 (!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI2)) ||
SathishKumar Mani88613382012-08-13 18:40:18 -0700661 (!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC)) ||
662 (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC)) ||
SathishKumar Manibf1c8742012-09-25 23:34:51 -0700663 (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_MUSIC2)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -0700664 (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_MUSIC))) {
SathishKumar Mani88613382012-08-13 18:40:18 -0700665 ALOGV("Music case");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700666 flags = PCM_OUT;
667 } else {
668 flags = PCM_IN;
669 }
670 if (handle->channels == 1) {
671 flags |= PCM_MONO;
SathishKumar Manie42406e2012-08-29 16:25:54 -0700672 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700673 else if (handle->channels == 4 ) {
674 flags |= PCM_QUAD;
675 } else if (handle->channels == 6 ) {
SathishKumar Manibf1c8742012-09-25 23:34:51 -0700676#ifdef QCOM_SSR_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700677 if (!strncmp(handle->useCase, SND_USE_CASE_VERB_HIFI_REC, strlen(SND_USE_CASE_VERB_HIFI_REC))
678 || !strncmp(handle->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, strlen(SND_USE_CASE_MOD_CAPTURE_MUSIC))) {
679 flags |= PCM_QUAD;
680 } else {
681 flags |= PCM_5POINT1;
682 }
SathishKumar Manibf1c8742012-09-25 23:34:51 -0700683#else
684 flags |= PCM_5POINT1;
Iliyan Malchev4765c432012-06-11 14:36:16 -0700685#endif
SathishKumar Manibf1c8742012-09-25 23:34:51 -0700686 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700687 else {
688 flags |= PCM_STEREO;
689 }
690 if (deviceName(handle, flags, &devName) < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700691 ALOGE("Failed to get pcm device node: %s", devName);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700692 return NO_INIT;
693 }
694 if (devName != NULL) {
695 handle->handle = pcm_open(flags, (char*)devName);
696 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700697 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700698 return NO_INIT;
699 }
700
701 if (!handle->handle) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700702 ALOGE("s_open: Failed to initialize ALSA device '%s'", devName);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700703 free(devName);
704 return NO_INIT;
705 }
706
707 handle->handle->flags = flags;
708 err = setHardwareParams(handle);
709
710 if (err == NO_ERROR) {
711 err = setSoftwareParams(handle);
712 }
713
714 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700715 ALOGE("Set HW/SW params failed: Closing the pcm stream");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700716 s_standby(handle);
717 }
718
719 free(devName);
720 return NO_ERROR;
721}
722
723static status_t s_start_voip_call(alsa_handle_t *handle)
724{
725
726 char* devName;
727 char* devName1;
728 unsigned flags = 0;
729 int err = NO_ERROR;
730 uint8_t voc_pkt[VOIP_BUFFER_MAX_SIZE];
731
732 s_close(handle);
733 flags = PCM_OUT;
734 flags |= PCM_MONO;
Iliyan Malchev4113f342012-06-11 14:39:47 -0700735 ALOGV("s_open:s_start_voip_call handle %p", handle);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700736
737 if (deviceName(handle, flags, &devName) < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700738 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700739 return NO_INIT;
740 }
741
742 if (devName != NULL) {
743 handle->handle = pcm_open(flags, (char*)devName);
744 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700745 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700746 return NO_INIT;
747 }
748
749 if (!handle->handle) {
750 free(devName);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700751 ALOGE("s_open: Failed to initialize ALSA device '%s'", devName);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700752 return NO_INIT;
753 }
754
755 if (!pcm_ready(handle->handle)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700756 ALOGE(" pcm ready failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700757 }
758
759 handle->handle->flags = flags;
760 err = setHardwareParams(handle);
761
762 if (err == NO_ERROR) {
763 err = setSoftwareParams(handle);
764 }
765
766 err = pcm_prepare(handle->handle);
767 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700768 ALOGE("DEVICE_OUT_DIRECTOUTPUT: pcm_prepare failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700769 }
770
771 /* first write required start dsp */
772 memset(&voc_pkt,0,sizeof(voc_pkt));
773 pcm_write(handle->handle,&voc_pkt,handle->handle->period_size);
774 handle->rxHandle = handle->handle;
775 free(devName);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700776 ALOGV("s_open: DEVICE_IN_COMMUNICATION ");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700777 flags = PCM_IN;
778 flags |= PCM_MONO;
779 handle->handle = 0;
780
781 if (deviceName(handle, flags, &devName1) < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700782 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700783 return NO_INIT;
784 }
785 if (devName != NULL) {
786 handle->handle = pcm_open(flags, (char*)devName1);
787 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700788 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700789 return NO_INIT;
790 }
791
792 if (!handle->handle) {
793 free(devName);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700794 ALOGE("s_open: Failed to initialize ALSA device '%s'", devName);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700795 return NO_INIT;
796 }
797
798 if (!pcm_ready(handle->handle)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700799 ALOGE(" pcm ready in failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700800 }
801
802 handle->handle->flags = flags;
803
804 err = setHardwareParams(handle);
805
806 if (err == NO_ERROR) {
807 err = setSoftwareParams(handle);
808 }
809
810
811 err = pcm_prepare(handle->handle);
812 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700813 ALOGE("DEVICE_IN_COMMUNICATION: pcm_prepare failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700814 }
815
816 /* first read required start dsp */
817 memset(&voc_pkt,0,sizeof(voc_pkt));
818 pcm_read(handle->handle,&voc_pkt,handle->handle->period_size);
819 return NO_ERROR;
820}
821
822static status_t s_start_voice_call(alsa_handle_t *handle)
823{
824 char* devName;
825 unsigned flags = 0;
826 int err = NO_ERROR;
827
SathishKumar Mani9efed762012-09-18 18:52:48 -0700828 ALOGV("s_start_voice_call: handle %p", handle);
Ajay Dudani86c852b2012-07-19 15:28:45 -0700829
Iliyan Malchev4765c432012-06-11 14:36:16 -0700830 // ASoC multicomponent requires a valid path (frontend/backend) for
831 // the device to be opened
832
833 flags = PCM_OUT | PCM_MONO;
834 if (deviceName(handle, flags, &devName) < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700835 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700836 return NO_INIT;
837 }
838 if (devName != NULL) {
839 handle->handle = pcm_open(flags, (char*)devName);
840 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700841 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700842 return NO_INIT;
843 }
844 if (!handle->handle) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700845 ALOGE("s_start_voicecall: could not open PCM device");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700846 goto Error;
847 }
848
849 handle->handle->flags = flags;
850 err = setHardwareParams(handle);
851 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700852 ALOGE("s_start_voice_call: setHardwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700853 goto Error;
854 }
855
856 err = setSoftwareParams(handle);
857 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700858 ALOGE("s_start_voice_call: setSoftwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700859 goto Error;
860 }
861
862 err = pcm_prepare(handle->handle);
863 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700864 ALOGE("s_start_voice_call: pcm_prepare failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700865 goto Error;
866 }
867
868 if (ioctl(handle->handle->fd, SNDRV_PCM_IOCTL_START)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700869 ALOGE("s_start_voice_call:SNDRV_PCM_IOCTL_START failed\n");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700870 goto Error;
871 }
872
873 // Store the PCM playback device pointer in rxHandle
874 handle->rxHandle = handle->handle;
875 free(devName);
876
877 // Open PCM capture device
878 flags = PCM_IN | PCM_MONO;
879 if (deviceName(handle, flags, &devName) < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700880 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700881 goto Error;
882 }
883 if (devName != NULL) {
884 handle->handle = pcm_open(flags, (char*)devName);
885 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700886 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700887 return NO_INIT;
888 }
889 if (!handle->handle) {
890 free(devName);
891 goto Error;
892 }
893
894 handle->handle->flags = flags;
895 err = setHardwareParams(handle);
896 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700897 ALOGE("s_start_voice_call: setHardwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700898 goto Error;
899 }
900
901 err = setSoftwareParams(handle);
902 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700903 ALOGE("s_start_voice_call: setSoftwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700904 goto Error;
905 }
906
907 err = pcm_prepare(handle->handle);
908 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700909 ALOGE("s_start_voice_call: pcm_prepare failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700910 goto Error;
911 }
912
913 if (ioctl(handle->handle->fd, SNDRV_PCM_IOCTL_START)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700914 ALOGE("s_start_voice_call:SNDRV_PCM_IOCTL_START failed\n");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700915 goto Error;
916 }
917
918 if (platform_is_Fusion3()) {
Ajay Dudani9746c472012-06-18 16:01:16 -0700919#ifdef QCOM_CSDCLIENT_ENABLED
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700920 if (csd_start_voice == NULL) {
921 ALOGE("dlsym:Error:%s Loading csd_client_start_voice", dlerror());
922 } else {
923 err = csd_start_voice();
924 if (err < 0){
925 ALOGE("s_start_voice_call: csd_client error %d\n", err);
926 goto Error;
927 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700928 }
Iliyan Malchev4113f342012-06-11 14:39:47 -0700929#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700930 }
931
932 free(devName);
933 return NO_ERROR;
934
935Error:
Iliyan Malchev4113f342012-06-11 14:39:47 -0700936 ALOGE("s_start_voice_call: Failed to initialize ALSA device '%s'", devName);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700937 free(devName);
938 s_close(handle);
939 return NO_INIT;
940}
941
942static status_t s_start_fm(alsa_handle_t *handle)
943{
944 char *devName;
945 unsigned flags = 0;
946 int err = NO_ERROR;
947
SathishKumar Mani9efed762012-09-18 18:52:48 -0700948 ALOGV("s_start_fm: handle %p", handle);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700949
950 // ASoC multicomponent requires a valid path (frontend/backend) for
951 // the device to be opened
952
953 flags = PCM_OUT | PCM_STEREO;
954 if (deviceName(handle, flags, &devName) < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700955 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700956 goto Error;
957 }
958 if (devName != NULL) {
959 handle->handle = pcm_open(flags, (char*)devName);
960 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700961 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700962 return NO_INIT;
963 }
964 if (!handle->handle) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700965 ALOGE("s_start_fm: could not open PCM device");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700966 goto Error;
967 }
968
969 handle->handle->flags = flags;
970 err = setHardwareParams(handle);
971 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700972 ALOGE("s_start_fm: setHardwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700973 goto Error;
974 }
975
976 err = setSoftwareParams(handle);
977 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700978 ALOGE("s_start_fm: setSoftwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700979 goto Error;
980 }
981
982 err = pcm_prepare(handle->handle);
983 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700984 ALOGE("s_start_fm: setSoftwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700985 goto Error;
986 }
987
988 if (ioctl(handle->handle->fd, SNDRV_PCM_IOCTL_START)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700989 ALOGE("s_start_fm: SNDRV_PCM_IOCTL_START failed\n");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700990 goto Error;
991 }
992
993 // Store the PCM playback device pointer in rxHandle
994 handle->rxHandle = handle->handle;
995 free(devName);
996
997 // Open PCM capture device
998 flags = PCM_IN | PCM_STEREO;
999 if (deviceName(handle, flags, &devName) < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001000 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001001 goto Error;
1002 }
1003 if (devName != NULL) {
1004 handle->handle = pcm_open(flags, (char*)devName);
1005 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001006 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001007 return NO_INIT;
1008 }
1009 if (!handle->handle) {
1010 goto Error;
1011 }
1012
1013 handle->handle->flags = flags;
1014 err = setHardwareParams(handle);
1015 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001016 ALOGE("s_start_fm: setHardwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001017 goto Error;
1018 }
1019
1020 err = setSoftwareParams(handle);
1021 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001022 ALOGE("s_start_fm: setSoftwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001023 goto Error;
1024 }
1025
1026 err = pcm_prepare(handle->handle);
1027 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001028 ALOGE("s_start_fm: pcm_prepare failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001029 goto Error;
1030 }
1031
1032 if (ioctl(handle->handle->fd, SNDRV_PCM_IOCTL_START)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001033 ALOGE("s_start_fm: SNDRV_PCM_IOCTL_START failed\n");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001034 goto Error;
1035 }
1036
1037 s_set_fm_vol(fmVolume);
1038 free(devName);
1039 return NO_ERROR;
1040
1041Error:
1042 free(devName);
1043 s_close(handle);
1044 return NO_INIT;
1045}
1046
1047static status_t s_set_fm_vol(int value)
1048{
1049 status_t err = NO_ERROR;
1050
1051 ALSAControl control("/dev/snd/controlC0");
1052 control.set("Internal FM RX Volume",value,0);
1053 fmVolume = value;
1054
1055 return err;
1056}
1057
1058static status_t s_set_lpa_vol(int value)
1059{
1060 status_t err = NO_ERROR;
1061
1062 ALSAControl control("/dev/snd/controlC0");
1063 control.set("LPA RX Volume",value,0);
1064
1065 return err;
1066}
1067
1068static status_t s_start(alsa_handle_t *handle)
1069{
1070 status_t err = NO_ERROR;
1071
1072 if(!handle->handle) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001073 ALOGE("No active PCM driver to start");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001074 return err;
1075 }
1076
1077 err = pcm_prepare(handle->handle);
1078
1079 return err;
1080}
1081
1082static status_t s_close(alsa_handle_t *handle)
1083{
1084 int ret;
1085 status_t err = NO_ERROR;
1086 struct pcm *h = handle->rxHandle;
1087
1088 handle->rxHandle = 0;
SathishKumar Mani9efed762012-09-18 18:52:48 -07001089 ALOGV("s_close: handle %p h %p", handle, h);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001090 if (h) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001091 ALOGV("s_close rxHandle\n");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001092 err = pcm_close(h);
1093 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001094 ALOGE("s_close: pcm_close failed for rxHandle with err %d", err);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001095 }
1096 }
1097
1098 h = handle->handle;
1099 handle->handle = 0;
1100
1101 if (h) {
SathishKumar Mani9efed762012-09-18 18:52:48 -07001102 ALOGV("s_close handle h %p\n", h);
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 handle with err %d", err);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001106 }
1107
1108 if ((!strcmp(handle->useCase, SND_USE_CASE_VERB_VOICECALL) ||
1109 !strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_VOICE)) &&
1110 platform_is_Fusion3()) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001111#ifdef QCOM_CSDCLIENT_ENABLED
SathishKumar Mani5ff7a022012-09-14 11:36:35 -07001112 if (csd_stop_voice == NULL) {
1113 ALOGE("dlsym:Error:%s Loading csd_client_disable_device", dlerror());
1114 } else {
1115 err = csd_stop_voice();
1116 if (err < 0) {
1117 ALOGE("s_close: csd_client error %d\n", err);
1118 }
Iliyan Malchev4765c432012-06-11 14:36:16 -07001119 }
Iliyan Malchev4113f342012-06-11 14:39:47 -07001120#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001121 }
1122
1123 disableDevice(handle);
1124 } else if((!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER)) ||
1125 (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_LPA)) ||
1126 (!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_TUNNEL)) ||
1127 (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_TUNNEL))){
1128 disableDevice(handle);
1129 }
1130
1131 return err;
1132}
1133
1134/*
1135 this is same as s_close, but don't discard
1136 the device/mode info. This way we can still
1137 close the device, hit idle and power-save, reopen the pcm
1138 for the same device/mode after resuming
1139*/
1140static status_t s_standby(alsa_handle_t *handle)
1141{
1142 int ret;
SathishKumar Manie42406e2012-08-29 16:25:54 -07001143 status_t err = NO_ERROR;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001144 struct pcm *h = handle->rxHandle;
1145 handle->rxHandle = 0;
SathishKumar Mani9efed762012-09-18 18:52:48 -07001146 ALOGV("s_standby: handle %p h %p", handle, h);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001147 if (h) {
SathishKumar Mani0a019912012-09-11 12:33:11 -07001148 ALOGD("s_standby rxHandle\n");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001149 err = pcm_close(h);
1150 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001151 ALOGE("s_standby: pcm_close failed for rxHandle with err %d", err);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001152 }
1153 }
1154
1155 h = handle->handle;
1156 handle->handle = 0;
1157
1158 if (h) {
SathishKumar Mani9efed762012-09-18 18:52:48 -07001159 ALOGV("s_standby handle h %p\n", h);
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 handle with err %d", err);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001163 }
1164 disableDevice(handle);
1165 } else if((!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER)) ||
1166 (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_LPA)) ||
1167 (!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_TUNNEL)) ||
1168 (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_TUNNEL))) {
1169 disableDevice(handle);
1170 }
1171
1172 return err;
1173}
1174
1175static status_t s_route(alsa_handle_t *handle, uint32_t devices, int mode)
1176{
1177 status_t status = NO_ERROR;
1178
Iliyan Malchev4113f342012-06-11 14:39:47 -07001179 ALOGD("s_route: devices 0x%x in mode %d", devices, mode);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001180 callMode = mode;
1181 switchDevice(handle, devices, mode);
1182 return status;
1183}
1184
1185int getUseCaseType(const char *useCase)
1186{
SathishKumar Mani0a019912012-09-11 12:33:11 -07001187 ALOGD("use case is %s\n", useCase);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001188 if (!strncmp(useCase, SND_USE_CASE_VERB_HIFI,
chahee.kima8b76532012-10-01 16:34:06 +09001189 MAX_LEN(useCase,SND_USE_CASE_VERB_HIFI)) ||
SathishKumar Manibf1c8742012-09-25 23:34:51 -07001190 !strncmp(useCase, SND_USE_CASE_VERB_HIFI2,
1191 MAX_LEN(useCase, SND_USE_CASE_VERB_HIFI2)) ||
SathishKumar Mani88613382012-08-13 18:40:18 -07001192 !strncmp(useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC,
chahee.kima8b76532012-10-01 16:34:06 +09001193 MAX_LEN(useCase,SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001194 !strncmp(useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER,
chahee.kima8b76532012-10-01 16:34:06 +09001195 MAX_LEN(useCase,SND_USE_CASE_VERB_HIFI_LOW_POWER)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001196 !strncmp(useCase, SND_USE_CASE_VERB_HIFI_TUNNEL,
chahee.kima8b76532012-10-01 16:34:06 +09001197 MAX_LEN(useCase,SND_USE_CASE_VERB_HIFI_TUNNEL)) ||
1198 !strncmp(useCase, SND_USE_CASE_VERB_HIFI2,
1199 MAX_LEN(useCase,SND_USE_CASE_VERB_HIFI2)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001200 !strncmp(useCase, SND_USE_CASE_VERB_DIGITAL_RADIO,
chahee.kima8b76532012-10-01 16:34:06 +09001201 MAX_LEN(useCase,SND_USE_CASE_VERB_DIGITAL_RADIO)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001202 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_MUSIC,
chahee.kima8b76532012-10-01 16:34:06 +09001203 MAX_LEN(useCase,SND_USE_CASE_MOD_PLAY_MUSIC)) ||
SathishKumar Manibf1c8742012-09-25 23:34:51 -07001204 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_MUSIC2,
1205 MAX_LEN(useCase, SND_USE_CASE_MOD_PLAY_MUSIC2)) ||
SathishKumar Mani88613382012-08-13 18:40:18 -07001206 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC,
chahee.kima8b76532012-10-01 16:34:06 +09001207 MAX_LEN(useCase,SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC)) ||
1208 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_MUSIC2,
1209 MAX_LEN(useCase,SND_USE_CASE_MOD_PLAY_MUSIC2)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001210 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_LPA,
chahee.kima8b76532012-10-01 16:34:06 +09001211 MAX_LEN(useCase,SND_USE_CASE_MOD_PLAY_LPA)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001212 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_TUNNEL,
chahee.kima8b76532012-10-01 16:34:06 +09001213 MAX_LEN(useCase,SND_USE_CASE_MOD_PLAY_TUNNEL)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001214 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_FM,
chahee.kima8b76532012-10-01 16:34:06 +09001215 MAX_LEN(useCase,SND_USE_CASE_MOD_PLAY_FM))) {
Iliyan Malchev4765c432012-06-11 14:36:16 -07001216 return USECASE_TYPE_RX;
1217 } else if (!strncmp(useCase, SND_USE_CASE_VERB_HIFI_REC,
chahee.kima8b76532012-10-01 16:34:06 +09001218 MAX_LEN(useCase,SND_USE_CASE_VERB_HIFI_REC)) ||
SathishKumar Mani88613382012-08-13 18:40:18 -07001219 !strncmp(useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_REC,
chahee.kima8b76532012-10-01 16:34:06 +09001220 MAX_LEN(useCase,SND_USE_CASE_VERB_HIFI_LOWLATENCY_REC)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001221 !strncmp(useCase, SND_USE_CASE_VERB_FM_REC,
chahee.kima8b76532012-10-01 16:34:06 +09001222 MAX_LEN(useCase,SND_USE_CASE_VERB_FM_REC)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001223 !strncmp(useCase, SND_USE_CASE_VERB_FM_A2DP_REC,
chahee.kima8b76532012-10-01 16:34:06 +09001224 MAX_LEN(useCase,SND_USE_CASE_VERB_FM_A2DP_REC)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001225 !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC,
chahee.kima8b76532012-10-01 16:34:06 +09001226 MAX_LEN(useCase,SND_USE_CASE_MOD_CAPTURE_MUSIC)) ||
SathishKumar Mani88613382012-08-13 18:40:18 -07001227 !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_LOWLATENCY_MUSIC,
chahee.kima8b76532012-10-01 16:34:06 +09001228 MAX_LEN(useCase,SND_USE_CASE_MOD_CAPTURE_LOWLATENCY_MUSIC)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001229 !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_FM,
chahee.kima8b76532012-10-01 16:34:06 +09001230 MAX_LEN(useCase,SND_USE_CASE_MOD_CAPTURE_FM)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001231 !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_A2DP_FM,
chahee.kima8b76532012-10-01 16:34:06 +09001232 MAX_LEN(useCase,SND_USE_CASE_MOD_CAPTURE_A2DP_FM))) {
Iliyan Malchev4765c432012-06-11 14:36:16 -07001233 return USECASE_TYPE_TX;
1234 } else if (!strncmp(useCase, SND_USE_CASE_VERB_VOICECALL,
chahee.kima8b76532012-10-01 16:34:06 +09001235 MAX_LEN(useCase,SND_USE_CASE_VERB_VOICECALL)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001236 !strncmp(useCase, SND_USE_CASE_VERB_IP_VOICECALL,
chahee.kima8b76532012-10-01 16:34:06 +09001237 MAX_LEN(useCase,SND_USE_CASE_VERB_IP_VOICECALL)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001238 !strncmp(useCase, SND_USE_CASE_VERB_DL_REC,
chahee.kima8b76532012-10-01 16:34:06 +09001239 MAX_LEN(useCase,SND_USE_CASE_VERB_DL_REC)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001240 !strncmp(useCase, SND_USE_CASE_VERB_UL_DL_REC,
chahee.kima8b76532012-10-01 16:34:06 +09001241 MAX_LEN(useCase,SND_USE_CASE_VERB_UL_DL_REC)) ||
1242 !strncmp(useCase, SND_USE_CASE_VERB_INCALL_REC,
1243 MAX_LEN(useCase,SND_USE_CASE_VERB_INCALL_REC)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001244 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_VOICE,
chahee.kima8b76532012-10-01 16:34:06 +09001245 MAX_LEN(useCase,SND_USE_CASE_MOD_PLAY_VOICE)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001246 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_VOIP,
chahee.kima8b76532012-10-01 16:34:06 +09001247 MAX_LEN(useCase,SND_USE_CASE_MOD_PLAY_VOIP)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001248 !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_VOICE_DL,
chahee.kima8b76532012-10-01 16:34:06 +09001249 MAX_LEN(useCase,SND_USE_CASE_MOD_CAPTURE_VOICE_DL)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001250 !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_VOICE_UL_DL,
chahee.kima8b76532012-10-01 16:34:06 +09001251 MAX_LEN(useCase,SND_USE_CASE_MOD_CAPTURE_VOICE_UL_DL)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001252 !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_VOICE,
chahee.kima8b76532012-10-01 16:34:06 +09001253 MAX_LEN(useCase, SND_USE_CASE_MOD_CAPTURE_VOICE)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001254 !strncmp(useCase, SND_USE_CASE_VERB_VOLTE,
chahee.kima8b76532012-10-01 16:34:06 +09001255 MAX_LEN(useCase,SND_USE_CASE_VERB_VOLTE)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001256 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_VOLTE,
chahee.kima8b76532012-10-01 16:34:06 +09001257 MAX_LEN(useCase, SND_USE_CASE_MOD_PLAY_VOLTE))) {
Iliyan Malchev4765c432012-06-11 14:36:16 -07001258 return (USECASE_TYPE_RX | USECASE_TYPE_TX);
1259 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001260 ALOGE("unknown use case %s\n", useCase);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001261 return 0;
1262 }
1263}
1264
1265static void disableDevice(alsa_handle_t *handle)
1266{
1267 unsigned usecase_type = 0;
1268 int i, mods_size;
1269 char *useCase;
1270 const char **mods_list;
1271
1272 snd_use_case_get(handle->ucMgr, "_verb", (const char **)&useCase);
1273 if (useCase != NULL) {
1274 if (!strncmp(useCase, handle->useCase, MAX_UC_LEN)) {
1275 snd_use_case_set(handle->ucMgr, "_verb", SND_USE_CASE_VERB_INACTIVE);
1276 } else {
1277 snd_use_case_set(handle->ucMgr, "_dismod", handle->useCase);
1278 }
1279 free(useCase);
1280 snd_use_case_get(handle->ucMgr, "_verb", (const char **)&useCase);
1281 if (strncmp(useCase, SND_USE_CASE_VERB_INACTIVE,
1282 strlen(SND_USE_CASE_VERB_INACTIVE)))
1283 usecase_type |= getUseCaseType(useCase);
1284 mods_size = snd_use_case_get_list(handle->ucMgr, "_enamods", &mods_list);
SathishKumar Mani9efed762012-09-18 18:52:48 -07001285 ALOGV("Number of modifiers %d\n", mods_size);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001286 if (mods_size) {
1287 for(i = 0; i < mods_size; i++) {
SathishKumar Mani9efed762012-09-18 18:52:48 -07001288 ALOGV("index %d modifier %s\n", i, mods_list[i]);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001289 usecase_type |= getUseCaseType(mods_list[i]);
1290 }
1291 }
SathishKumar Mani9efed762012-09-18 18:52:48 -07001292 ALOGV("usecase_type is %d\n", usecase_type);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001293 if (!(usecase_type & USECASE_TYPE_TX) && (strncmp(curTxUCMDevice, "None", 4)))
1294 snd_use_case_set(handle->ucMgr, "_disdev", curTxUCMDevice);
1295 if (!(usecase_type & USECASE_TYPE_RX) && (strncmp(curRxUCMDevice, "None", 4)))
1296 snd_use_case_set(handle->ucMgr, "_disdev", curRxUCMDevice);
1297 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001298 ALOGE("Invalid state, no valid use case found to disable");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001299 }
1300 free(useCase);
1301}
1302
1303char *getUCMDevice(uint32_t devices, int input, char *rxDevice)
1304{
1305 if (!input) {
1306 if (!(mDevSettingsFlag & TTY_OFF) &&
1307 (callMode == AudioSystem::MODE_IN_CALL) &&
1308 ((devices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) ||
ty.lee924f7982012-08-01 23:15:30 +09001309 (devices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE))) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001310#ifdef QCOM_ANC_HEADSET_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001311 ||
1312 (devices & AudioSystem::DEVICE_OUT_ANC_HEADSET) ||
1313 (devices & AudioSystem::DEVICE_OUT_ANC_HEADPHONE))) {
1314#endif
1315 if (mDevSettingsFlag & TTY_VCO) {
1316 return strdup(SND_USE_CASE_DEV_TTY_HEADSET_RX);
1317 } else if (mDevSettingsFlag & TTY_FULL) {
1318 return strdup(SND_USE_CASE_DEV_TTY_FULL_RX);
1319 } else if (mDevSettingsFlag & TTY_HCO) {
1320 return strdup(SND_USE_CASE_DEV_TTY_HANDSET_RX); /* HANDSET RX */
1321 }
1322 }else if ((devices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET) ||
1323 (devices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)) {
1324 return strdup(SND_USE_CASE_DEV_PROXY_RX); /* PROXY RX */
1325 } else if ((devices & AudioSystem::DEVICE_OUT_SPEAKER) &&
1326 ((devices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) ||
1327 (devices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE))) {
1328 if (mDevSettingsFlag & ANC_FLAG) {
1329 return strdup(SND_USE_CASE_DEV_SPEAKER_ANC_HEADSET); /* COMBO SPEAKER+ANC HEADSET RX */
1330 } else {
1331 return strdup(SND_USE_CASE_DEV_SPEAKER_HEADSET); /* COMBO SPEAKER+HEADSET RX */
1332 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001333#ifdef QCOM_ANC_HEADSET_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001334 } else if ((devices & AudioSystem::DEVICE_OUT_SPEAKER) &&
1335 ((devices & AudioSystem::DEVICE_OUT_ANC_HEADSET) ||
1336 (devices & AudioSystem::DEVICE_OUT_ANC_HEADPHONE))) {
1337 return strdup(SND_USE_CASE_DEV_SPEAKER_ANC_HEADSET); /* COMBO SPEAKER+ANC HEADSET RX */
1338 } else if ((devices & AudioSystem::DEVICE_OUT_SPEAKER) &&
1339 (devices & AudioSystem::DEVICE_OUT_FM_TX)) {
1340 return strdup(SND_USE_CASE_DEV_SPEAKER_FM_TX); /* COMBO SPEAKER+FM_TX RX */
1341#endif
1342 } else if (devices & AudioSystem::DEVICE_OUT_EARPIECE) {
ty.lee925596f2012-09-12 18:23:59 +09001343 if (callMode == AudioSystem::MODE_IN_CALL) {
1344 return strdup(SND_USE_CASE_DEV_VOC_EARPIECE); /* Voice HANDSET RX */
1345 } else
1346 return strdup(SND_USE_CASE_DEV_EARPIECE); /* HANDSET RX */
Iliyan Malchev4765c432012-06-11 14:36:16 -07001347 } else if (devices & AudioSystem::DEVICE_OUT_SPEAKER) {
ty.lee925596f2012-09-12 18:23:59 +09001348 if (callMode == AudioSystem::MODE_IN_CALL) {
1349 return strdup(SND_USE_CASE_DEV_VOC_SPEAKER); /* Voice SPEAKER RX */
1350 } else
1351 return strdup(SND_USE_CASE_DEV_SPEAKER); /* SPEAKER RX */
Iliyan Malchev4765c432012-06-11 14:36:16 -07001352 } else if ((devices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) ||
1353 (devices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE)) {
1354 if (mDevSettingsFlag & ANC_FLAG) {
ty.lee925596f2012-09-12 18:23:59 +09001355 if (callMode == AudioSystem::MODE_IN_CALL) {
1356 return strdup(SND_USE_CASE_DEV_VOC_ANC_HEADSET); /* Voice ANC HEADSET RX */
1357 } else
1358 return strdup(SND_USE_CASE_DEV_ANC_HEADSET); /* ANC HEADSET RX */
Iliyan Malchev4765c432012-06-11 14:36:16 -07001359 } else {
ty.lee925596f2012-09-12 18:23:59 +09001360 if (callMode == AudioSystem::MODE_IN_CALL) {
1361 return strdup(SND_USE_CASE_DEV_VOC_HEADPHONE); /* Voice HEADSET RX */
1362 } else
1363 return strdup(SND_USE_CASE_DEV_HEADPHONES); /* HEADSET RX */
Iliyan Malchev4765c432012-06-11 14:36:16 -07001364 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001365#ifdef QCOM_ANC_HEADSET_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001366 } else if ((devices & AudioSystem::DEVICE_OUT_ANC_HEADSET) ||
1367 (devices & AudioSystem::DEVICE_OUT_ANC_HEADPHONE)) {
ty.lee925596f2012-09-12 18:23:59 +09001368 if (callMode == AudioSystem::MODE_IN_CALL) {
1369 return strdup(SND_USE_CASE_DEV_VOC_ANC_HEADSET); /* Voice ANC HEADSET RX */
1370 } else
1371 return strdup(SND_USE_CASE_DEV_ANC_HEADSET); /* ANC HEADSET RX */
Iliyan Malchev4765c432012-06-11 14:36:16 -07001372#endif
1373 } else if ((devices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO) ||
1374 (devices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET) ||
1375 (devices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT)) {
1376 if (btsco_samplerate == BTSCO_RATE_16KHZ)
1377 return strdup(SND_USE_CASE_DEV_BTSCO_WB_RX); /* BTSCO RX*/
1378 else
1379 return strdup(SND_USE_CASE_DEV_BTSCO_NB_RX); /* BTSCO RX*/
1380 } else if ((devices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP) ||
1381 (devices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES) ||
Ajay Dudani9746c472012-06-18 16:01:16 -07001382#ifdef QCOM_VOIP_ENABLED
1383 (devices & AudioSystem::DEVICE_OUT_DIRECTOUTPUT) ||
1384#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001385 (devices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER)) {
1386 /* Nothing to be done, use current active device */
1387 if (strncmp(curRxUCMDevice, "None", 4)) {
1388 return strdup(curRxUCMDevice);
1389 }
1390 } else if (devices & AudioSystem::DEVICE_OUT_AUX_DIGITAL) {
1391 return strdup(SND_USE_CASE_DEV_HDMI); /* HDMI RX */
Ajay Dudani9746c472012-06-18 16:01:16 -07001392#ifdef QCOM_PROXY_DEVICE_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001393 } else if (devices & AudioSystem::DEVICE_OUT_PROXY) {
1394 return strdup(SND_USE_CASE_DEV_PROXY_RX); /* PROXY RX */
Ajay Dudani9746c472012-06-18 16:01:16 -07001395#endif
1396#ifdef QCOM_FM_TX_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001397 } else if (devices & AudioSystem::DEVICE_OUT_FM_TX) {
1398 return strdup(SND_USE_CASE_DEV_FM_TX); /* FM Tx */
1399#endif
1400 } else if (devices & AudioSystem::DEVICE_OUT_DEFAULT) {
ty.lee925596f2012-09-12 18:23:59 +09001401 if (callMode == AudioSystem::MODE_IN_CALL) {
1402 return strdup(SND_USE_CASE_DEV_VOC_SPEAKER); /* Voice SPEAKER RX */
1403 } else
1404 return strdup(SND_USE_CASE_DEV_SPEAKER); /* SPEAKER RX */
Iliyan Malchev4765c432012-06-11 14:36:16 -07001405 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001406 ALOGD("No valid output device: %u", devices);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001407 }
1408 } else {
1409 if (!(mDevSettingsFlag & TTY_OFF) &&
1410 (callMode == AudioSystem::MODE_IN_CALL) &&
ty.lee924f7982012-08-01 23:15:30 +09001411 ((devices & AudioSystem::DEVICE_IN_WIRED_HEADSET))) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001412#ifdef QCOM_ANC_HEADSET_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001413 ||(devices & AudioSystem::DEVICE_IN_ANC_HEADSET))) {
1414#endif
1415 if (mDevSettingsFlag & TTY_HCO) {
1416 return strdup(SND_USE_CASE_DEV_TTY_HEADSET_TX);
1417 } else if (mDevSettingsFlag & TTY_FULL) {
1418 return strdup(SND_USE_CASE_DEV_TTY_FULL_TX);
1419 } else if (mDevSettingsFlag & TTY_VCO) {
1420 if (!strncmp(mic_type, "analog", 6)) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001421 return strdup(SND_USE_CASE_DEV_TTY_HANDSET_ANALOG_TX);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001422 } else {
1423 return strdup(SND_USE_CASE_DEV_TTY_HANDSET_TX);
1424 }
1425 }
1426 } else if (devices & AudioSystem::DEVICE_IN_BUILTIN_MIC) {
1427 if (!strncmp(mic_type, "analog", 6)) {
1428 return strdup(SND_USE_CASE_DEV_HANDSET); /* HANDSET TX */
1429 } else {
1430 if (mDevSettingsFlag & DMIC_FLAG) {
ty.lee924f7982012-08-01 23:15:30 +09001431#ifdef USES_FLUENCE_INCALL
1432 if(callMode == AudioSystem::MODE_IN_CALL) {
1433 if (fluence_mode == FLUENCE_MODE_ENDFIRE) {
1434 return strdup(SND_USE_CASE_DEV_DUAL_MIC_ENDFIRE); /* DUALMIC EF TX */
1435 } else if (fluence_mode == FLUENCE_MODE_BROADSIDE) {
1436 return strdup(SND_USE_CASE_DEV_DUAL_MIC_BROADSIDE); /* DUALMIC BS TX */
1437 } else {
1438 return strdup(SND_USE_CASE_DEV_HANDSET); /* BUILTIN-MIC TX */
1439 }
1440 }
1441#else
Iliyan Malchev4765c432012-06-11 14:36:16 -07001442 if (((rxDevice != NULL) &&
1443 !strncmp(rxDevice, SND_USE_CASE_DEV_SPEAKER,
1444 (strlen(SND_USE_CASE_DEV_SPEAKER)+1))) ||
1445 !strncmp(curRxUCMDevice, SND_USE_CASE_DEV_SPEAKER,
1446 (strlen(SND_USE_CASE_DEV_SPEAKER)+1))) {
1447 if (fluence_mode == FLUENCE_MODE_ENDFIRE) {
1448 return strdup(SND_USE_CASE_DEV_SPEAKER_DUAL_MIC_ENDFIRE); /* DUALMIC EF TX */
1449 } else if (fluence_mode == FLUENCE_MODE_BROADSIDE) {
1450 return strdup(SND_USE_CASE_DEV_SPEAKER_DUAL_MIC_BROADSIDE); /* DUALMIC BS TX */
1451 }
1452 } else {
1453 if (fluence_mode == FLUENCE_MODE_ENDFIRE) {
1454 return strdup(SND_USE_CASE_DEV_DUAL_MIC_ENDFIRE); /* DUALMIC EF TX */
1455 } else if (fluence_mode == FLUENCE_MODE_BROADSIDE) {
1456 return strdup(SND_USE_CASE_DEV_DUAL_MIC_BROADSIDE); /* DUALMIC BS TX */
1457 }
1458 }
ty.lee924f7982012-08-01 23:15:30 +09001459#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001460 } else if (mDevSettingsFlag & QMIC_FLAG){
1461 return strdup(SND_USE_CASE_DEV_QUAD_MIC);
ty.lee924f7982012-08-01 23:15:30 +09001462 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001463#ifdef QCOM_SSR_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001464 else if (mDevSettingsFlag & SSRQMIC_FLAG){
Iliyan Malchev4113f342012-06-11 14:39:47 -07001465 ALOGV("return SSRQMIC_FLAG: 0x%x devices:0x%x",mDevSettingsFlag,devices);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001466 // Mapping for quad mic input device.
1467 return strdup(SND_USE_CASE_DEV_SSR_QUAD_MIC); /* SSR Quad MIC */
ty.lee924f7982012-08-01 23:15:30 +09001468 }
Iliyan Malchev4765c432012-06-11 14:36:16 -07001469#endif
ty.lee74060de2012-08-02 00:47:00 +09001470#ifdef SEPERATED_AUDIO_INPUT
1471 if(input_source == AUDIO_SOURCE_VOICE_RECOGNITION) {
ty.lee74060de2012-08-02 00:47:00 +09001472 return strdup(SND_USE_CASE_DEV_VOICE_RECOGNITION ); /* VOICE RECOGNITION TX */
ty.lee74060de2012-08-02 00:47:00 +09001473 }
1474#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001475 else {
ty.lee74060de2012-08-02 00:47:00 +09001476 return strdup(SND_USE_CASE_DEV_HANDSET); /* BUILTIN-MIC TX */
Iliyan Malchev4765c432012-06-11 14:36:16 -07001477 }
1478 }
1479 } else if (devices & AudioSystem::DEVICE_IN_AUX_DIGITAL) {
1480 return strdup(SND_USE_CASE_DEV_HDMI_TX); /* HDMI TX */
Ajay Dudani9746c472012-06-18 16:01:16 -07001481#ifdef QCOM_ANC_HEADSET_ENABLED
ehgrace.kim249f87d2012-08-12 20:40:32 -07001482 } else if (devices & AudioSystem::DEVICE_IN_ANC_HEADSET) {
Iliyan Malchev4765c432012-06-11 14:36:16 -07001483 return strdup(SND_USE_CASE_DEV_HEADSET); /* HEADSET TX */
1484#endif
ehgrace.kim249f87d2012-08-12 20:40:32 -07001485 } else if (devices & AudioSystem::DEVICE_IN_WIRED_HEADSET) {
ty.lee925596f2012-09-12 18:23:59 +09001486 if (callMode == AudioSystem::MODE_IN_CALL) {
1487 return strdup(SND_USE_CASE_DEV_VOC_HEADSET); /* Voice HEADSET TX */
1488 } else
1489 return strdup(SND_USE_CASE_DEV_HEADSET); /* HEADSET TX */
Iliyan Malchev4765c432012-06-11 14:36:16 -07001490 } else if (devices & AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
1491 if (btsco_samplerate == BTSCO_RATE_16KHZ)
1492 return strdup(SND_USE_CASE_DEV_BTSCO_WB_TX); /* BTSCO TX*/
1493 else
1494 return strdup(SND_USE_CASE_DEV_BTSCO_NB_TX); /* BTSCO TX*/
Ajay Dudani9746c472012-06-18 16:01:16 -07001495#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001496 } else if ((devices & AudioSystem::DEVICE_IN_ANLG_DOCK_HEADSET) ||
1497 (devices & AudioSystem::DEVICE_IN_PROXY)) {
1498 return strdup(SND_USE_CASE_DEV_PROXY_TX); /* PROXY TX */
1499#endif
1500 } else if ((devices & AudioSystem::DEVICE_IN_COMMUNICATION) ||
1501 (devices & AudioSystem::DEVICE_IN_VOICE_CALL)) {
1502 /* Nothing to be done, use current active device */
1503 if (strncmp(curTxUCMDevice, "None", 4)) {
1504 return strdup(curTxUCMDevice);
1505 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001506#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001507 } else if ((devices & AudioSystem::DEVICE_IN_FM_RX) ||
1508 (devices & AudioSystem::DEVICE_IN_FM_RX_A2DP)) {
1509 /* Nothing to be done, use current tx device or set dummy device */
1510 if (strncmp(curTxUCMDevice, "None", 4)) {
1511 return strdup(curTxUCMDevice);
1512 } else {
1513 return strdup(SND_USE_CASE_DEV_DUMMY_TX);
1514 }
1515#endif
1516 } else if ((devices & AudioSystem::DEVICE_IN_AMBIENT) ||
1517 (devices & AudioSystem::DEVICE_IN_BACK_MIC)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001518 ALOGI("No proper mapping found with UCM device list, setting default");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001519 if (!strncmp(mic_type, "analog", 6)) {
1520 return strdup(SND_USE_CASE_DEV_HANDSET); /* HANDSET TX */
1521 } else {
ty.lee925596f2012-09-12 18:23:59 +09001522 if (callMode == AudioSystem::MODE_IN_CALL) {
1523 return strdup(SND_USE_CASE_DEV_VOC_LINE); /* Voice BUILTIN-MIC TX */
ty.lee87459f02012-09-29 18:49:05 +09001524#ifdef SEPERATED_AUDIO_INPUT
1525 } else if(input_source == AUDIO_SOURCE_CAMCORDER) {
1526 return strdup(SND_USE_CASE_DEV_CAMCORDER_TX ); /* CAMCORDER TX */
1527#endif
ty.lee925596f2012-09-12 18:23:59 +09001528 } else
1529 return strdup(SND_USE_CASE_DEV_LINE); /* BUILTIN-MIC TX */
Iliyan Malchev4765c432012-06-11 14:36:16 -07001530 }
1531 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001532 ALOGD("No valid input device: %u", devices);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001533 }
1534 }
1535 return NULL;
1536}
1537
1538void s_set_voice_volume(int vol)
1539{
1540 int err = 0;
SathishKumar Mani9efed762012-09-18 18:52:48 -07001541 ALOGV("s_set_voice_volume: volume %d", vol);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001542 ALSAControl control("/dev/snd/controlC0");
1543 control.set("Voice Rx Volume", vol, 0);
1544
1545 if (platform_is_Fusion3()) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001546#ifdef QCOM_CSDCLIENT_ENABLED
SathishKumar Mani5ff7a022012-09-14 11:36:35 -07001547 if (csd_volume == NULL) {
1548 ALOGE("dlsym:Error:%s Loading csd_client_volume", dlerror());
1549 } else {
1550 err = csd_volume(vol);
1551 if (err < 0) {
1552 ALOGE("s_set_voice_volume: csd_client error %d", err);
1553 }
SathishKumar Manie42406e2012-08-29 16:25:54 -07001554 }
Iliyan Malchev4113f342012-06-11 14:39:47 -07001555#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001556 }
1557}
1558
1559void s_set_volte_volume(int vol)
1560{
SathishKumar Mani9efed762012-09-18 18:52:48 -07001561 ALOGV("s_set_volte_volume: volume %d", vol);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001562 ALSAControl control("/dev/snd/controlC0");
1563 control.set("VoLTE Rx Volume", vol, 0);
1564}
1565
1566
1567void s_set_voip_volume(int vol)
1568{
SathishKumar Mani9efed762012-09-18 18:52:48 -07001569 ALOGV("s_set_voip_volume: volume %d", vol);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001570 ALSAControl control("/dev/snd/controlC0");
1571 control.set("Voip Rx Volume", vol, 0);
1572}
1573void s_set_mic_mute(int state)
1574{
1575 int err = 0;
SathishKumar Mani9efed762012-09-18 18:52:48 -07001576 ALOGV("s_set_mic_mute: state %d", state);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001577 ALSAControl control("/dev/snd/controlC0");
1578 control.set("Voice Tx Mute", state, 0);
1579
1580 if (platform_is_Fusion3()) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001581#ifdef QCOM_CSDCLIENT_ENABLED
SathishKumar Mani5ff7a022012-09-14 11:36:35 -07001582 if (csd_mic_mute == NULL) {
1583 ALOGE("dlsym:Error:%s Loading csd_mic_mute", dlerror());
1584 } else {
1585 err=csd_mic_mute(state);
1586 if (err < 0) {
1587 ALOGE("s_set_mic_mute: csd_client error %d", err);
1588 }
Iliyan Malchev4765c432012-06-11 14:36:16 -07001589 }
Iliyan Malchev4113f342012-06-11 14:39:47 -07001590#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001591 }
1592}
1593void s_set_volte_mic_mute(int state)
1594{
SathishKumar Mani9efed762012-09-18 18:52:48 -07001595 ALOGV("s_set_volte_mic_mute: state %d", state);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001596 ALSAControl control("/dev/snd/controlC0");
1597 control.set("VoLTE Tx Mute", state, 0);
1598}
1599
1600void s_set_voip_mic_mute(int state)
1601{
SathishKumar Mani9efed762012-09-18 18:52:48 -07001602 ALOGV("s_set_voip_mic_mute: state %d", state);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001603 ALSAControl control("/dev/snd/controlC0");
1604 control.set("Voip Tx Mute", state, 0);
1605}
1606
1607void s_set_voip_config(int mode, int rate)
1608{
SathishKumar Mani9efed762012-09-18 18:52:48 -07001609 ALOGV("s_set_voip_config: mode %d,rate %d", mode, rate);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001610 ALSAControl control("/dev/snd/controlC0");
1611 char** setValues;
1612 setValues = (char**)malloc(2*sizeof(char*));
1613 if (setValues == NULL) {
1614 return;
1615 }
1616 setValues[0] = (char*)malloc(4*sizeof(char));
1617 if (setValues[0] == NULL) {
1618 free(setValues);
1619 return;
1620 }
1621
1622 setValues[1] = (char*)malloc(8*sizeof(char));
1623 if (setValues[1] == NULL) {
1624 free(setValues);
1625 free(setValues[0]);
1626 return;
1627 }
1628
1629 sprintf(setValues[0], "%d",mode);
1630 sprintf(setValues[1], "%d",rate);
1631
1632 control.setext("Voip Mode Rate Config", 2, setValues);
1633 free(setValues[1]);
1634 free(setValues[0]);
1635 free(setValues);
1636 return;
1637}
1638
1639void s_set_btsco_rate(int rate)
1640{
1641 btsco_samplerate = rate;
1642}
1643
1644void s_enable_wide_voice(bool flag)
1645{
1646 int err = 0;
1647
SathishKumar Mani9efed762012-09-18 18:52:48 -07001648 ALOGV("s_enable_wide_voice: flag %d", flag);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001649 ALSAControl control("/dev/snd/controlC0");
1650 if(flag == true) {
1651 control.set("Widevoice Enable", 1, 0);
1652 } else {
1653 control.set("Widevoice Enable", 0, 0);
1654 }
1655
1656 if (platform_is_Fusion3()) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001657#ifdef QCOM_CSDCLIENT_ENABLED
SathishKumar Mani5ff7a022012-09-14 11:36:35 -07001658 if (csd_wide_voice == NULL) {
1659 ALOGE("dlsym:Error:%s Loading csd_wide_voice", dlerror());
1660 } else {
1661 err = csd_wide_voice(flag);
1662 if (err < 0) {
1663 ALOGE("enableWideVoice: csd_client_wide_voice error %d", err);
1664 }
Iliyan Malchev4765c432012-06-11 14:36:16 -07001665 }
Iliyan Malchev4113f342012-06-11 14:39:47 -07001666#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001667 }
1668}
1669
1670void s_set_voc_rec_mode(uint8_t mode)
1671{
SathishKumar Mani9efed762012-09-18 18:52:48 -07001672 ALOGV("s_set_voc_rec_mode: mode %d", mode);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001673 ALSAControl control("/dev/snd/controlC0");
1674 control.set("Incall Rec Mode", mode, 0);
1675}
1676
1677void s_enable_fens(bool flag)
1678{
1679 int err = 0;
1680
SathishKumar Mani9efed762012-09-18 18:52:48 -07001681 ALOGV("s_enable_fens: flag %d", flag);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001682 ALSAControl control("/dev/snd/controlC0");
1683 if(flag == true) {
1684 control.set("FENS Enable", 1, 0);
1685 } else {
1686 control.set("FENS Enable", 0, 0);
1687 }
1688
1689 if (platform_is_Fusion3()) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001690#ifdef QCOM_CSDCLIENT_ENABLED
SathishKumar Mani5ff7a022012-09-14 11:36:35 -07001691 if (csd_fens == NULL) {
1692 ALOGE("dlsym:Error:%s Loading csd_fens", dlerror());
1693 } else {
1694 err = csd_fens(flag);
1695 if (err < 0) {
1696 ALOGE("s_enable_fens: csd_client error %d", err);
1697 }
Iliyan Malchev4765c432012-06-11 14:36:16 -07001698 }
Iliyan Malchev4113f342012-06-11 14:39:47 -07001699#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001700 }
1701}
1702
1703void s_enable_slow_talk(bool flag)
1704{
1705 int err = 0;
1706
SathishKumar Mani9efed762012-09-18 18:52:48 -07001707 ALOGV("s_enable_slow_talk: flag %d", flag);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001708 ALSAControl control("/dev/snd/controlC0");
1709 if(flag == true) {
1710 control.set("Slowtalk Enable", 1, 0);
1711 } else {
1712 control.set("Slowtalk Enable", 0, 0);
1713 }
1714
1715 if (platform_is_Fusion3()) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001716#ifdef QCOM_CSDCLIENT_ENABLED
SathishKumar Mani5ff7a022012-09-14 11:36:35 -07001717 if (csd_slow_talk == NULL) {
1718 ALOGE("dlsym:Error:%s Loading csd_slow_talk", dlerror());
1719 } else {
1720 err = csd_slow_talk(flag);
1721 if (err < 0) {
1722 ALOGE("s_enable_slow_talk: csd_client error %d", err);
1723 }
Iliyan Malchev4765c432012-06-11 14:36:16 -07001724 }
Iliyan Malchev4113f342012-06-11 14:39:47 -07001725#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001726 }
1727}
1728
1729void s_set_flags(uint32_t flags)
1730{
Iliyan Malchev4113f342012-06-11 14:39:47 -07001731 ALOGV("s_set_flags: flags %d", flags);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001732 mDevSettingsFlag = flags;
1733}
1734
1735static status_t s_set_compressed_vol(int value)
1736{
1737 status_t err = NO_ERROR;
1738
1739 ALSAControl control("/dev/snd/controlC0");
1740 control.set("COMPRESSED RX Volume",value,0);
1741
1742 return err;
1743}
1744
ty.lee74060de2012-08-02 00:47:00 +09001745#ifdef SEPERATED_AUDIO_INPUT
1746void s_setInput(int input)
1747{
1748 input_source = input;
1749 ALOGD("s_setInput() : input_source = %d",input_source);
1750}
1751#endif
SathishKumar Mani5ff7a022012-09-14 11:36:35 -07001752
1753#ifdef QCOM_CSDCLIENT_ENABLED
1754static void s_set_csd_handle(void* handle)
1755{
1756 csd_handle = static_cast<void*>(handle);
1757 ALOGI("%s csd_handle: %p", __func__, csd_handle);
1758
1759 csd_disable_device = (int (*)())::dlsym(csd_handle,"csd_client_disable_device");
1760 csd_enable_device = (int (*)(int,int,uint32_t))::dlsym(csd_handle,"csd_client_enable_device");
1761 csd_start_voice = (int (*)())::dlsym(csd_handle,"csd_client_start_voice");
1762 csd_stop_voice = (int (*)())::dlsym(csd_handle,"csd_client_stop_voice");
1763 csd_volume = (int (*)(int))::dlsym(csd_handle,"csd_client_volume");
1764 csd_mic_mute = (int (*)(int))::dlsym(csd_handle,"csd_client_mic_mute");
1765 csd_wide_voice = (int (*)(uint8_t))::dlsym(csd_handle,"csd_client_wide_voice");
1766 csd_fens = (int (*)(uint8_t))::dlsym(csd_handle,"csd_client_fens");
1767 csd_slow_talk = (int (*)(uint8_t))::dlsym(csd_handle,"csd_client_slow_talk");
1768}
1769#endif
1770
Iliyan Malchev4765c432012-06-11 14:36:16 -07001771}