blob: 7c2449e88dbd84202c16bed39dd3d3e88833f02f [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;
samin.ryu5062cce2012-10-11 13:07:57 +0900412 } else if (mode == AudioSystem::MODE_IN_COMMUNICATION) {
413 if (!strncmp(curRxUCMDevice, SND_USE_CASE_DEV_SPEAKER, MAX_LEN(curRxUCMDevice, SND_USE_CASE_DEV_SPEAKER))) {
414 devices &= ~AudioSystem::DEVICE_IN_BUILTIN_MIC;
415 devices |= AudioSystem::DEVICE_IN_BACK_MIC;
416 }
SathishKumar Manic669c272012-09-21 20:12:08 -0700417 }
418 } else if (devices & AudioSystem::DEVICE_OUT_EARPIECE) {
419 devices = devices | AudioSystem::DEVICE_IN_BUILTIN_MIC;
Iliyan Malchev4765c432012-06-11 14:36:16 -0700420 } else if (devices & AudioSystem::DEVICE_OUT_SPEAKER) {
ty.lee10dfa852012-08-01 21:09:45 +0900421 devices = devices | (AudioSystem::DEVICE_IN_BACK_MIC |
Iliyan Malchev4765c432012-06-11 14:36:16 -0700422 AudioSystem::DEVICE_OUT_SPEAKER);
423 } else if ((devices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO) ||
424 (devices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET) ||
425 (devices & AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET)) {
426 devices = devices | (AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET |
427 AudioSystem::DEVICE_OUT_BLUETOOTH_SCO);
Ajay Dudani9746c472012-06-18 16:01:16 -0700428#ifdef QCOM_ANC_HEADSET_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700429 } else if ((devices & AudioSystem::DEVICE_OUT_ANC_HEADSET) ||
430 (devices & AudioSystem::DEVICE_IN_ANC_HEADSET)) {
431 devices = devices | (AudioSystem::DEVICE_OUT_ANC_HEADSET |
432 AudioSystem::DEVICE_IN_ANC_HEADSET);
433 } else if (devices & AudioSystem::DEVICE_OUT_ANC_HEADPHONE) {
434 devices = devices | (AudioSystem::DEVICE_OUT_ANC_HEADPHONE |
435 AudioSystem::DEVICE_IN_BUILTIN_MIC);
436#endif
437 } else if (devices & AudioSystem::DEVICE_OUT_AUX_DIGITAL) {
Sungmin Choi6ebf0aa2012-09-28 16:09:12 -0700438 if (mode == AudioSystem::MODE_IN_CALL)
439 devices = devices | (AudioSystem::DEVICE_IN_BACK_MIC |
440 AudioSystem::DEVICE_OUT_SPEAKER);
441 else
442 devices = devices | (AudioSystem::DEVICE_OUT_AUX_DIGITAL |
443 AudioSystem::DEVICE_IN_BACK_MIC);
Ajay Dudani9746c472012-06-18 16:01:16 -0700444#ifdef QCOM_PROXY_DEVICE_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700445 } else if ((devices & AudioSystem::DEVICE_OUT_PROXY) ||
446 (devices & AudioSystem::DEVICE_IN_PROXY)) {
447 devices = devices | (AudioSystem::DEVICE_OUT_PROXY |
448 AudioSystem::DEVICE_IN_PROXY);
449#endif
450 }
451 }
Ajay Dudani9746c472012-06-18 16:01:16 -0700452#ifdef QCOM_SSR_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700453 if ((devices & AudioSystem::DEVICE_IN_BUILTIN_MIC) && ( 6 == handle->channels)) {
454 if (!strncmp(handle->useCase, SND_USE_CASE_VERB_HIFI_REC, strlen(SND_USE_CASE_VERB_HIFI_REC))
455 || !strncmp(handle->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, strlen(SND_USE_CASE_MOD_CAPTURE_MUSIC))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700456 ALOGV(" switchDevice , use ssr devices for channels:%d usecase:%s",handle->channels,handle->useCase);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700457 s_set_flags(SSRQMIC_FLAG);
458 }
459 }
460#endif
461
462 rxDevice = getUCMDevice(devices & AudioSystem::DEVICE_OUT_ALL, 0, NULL);
463 txDevice = getUCMDevice(devices & AudioSystem::DEVICE_IN_ALL, 1, rxDevice);
464
Iliyan Malchev4765c432012-06-11 14:36:16 -0700465 if ((rxDevice != NULL) && (txDevice != NULL)) {
466 if (((strncmp(rxDevice, curRxUCMDevice, MAX_STR_LEN)) ||
SathishKumar Manic669c272012-09-21 20:12:08 -0700467 (strncmp(txDevice, curTxUCMDevice, MAX_STR_LEN))) &&
468 ((mode == AudioSystem::MODE_IN_CALL) ||
469 (mode == AudioSystem::MODE_IN_COMMUNICATION)))
Iliyan Malchev4765c432012-06-11 14:36:16 -0700470 inCallDevSwitch = true;
471 }
Ajay Dudani91bf8912012-08-20 18:48:13 -0700472
473#ifdef QCOM_CSDCLIENT_ENABLED
SathishKumar Manic669c272012-09-21 20:12:08 -0700474 if (platform_is_Fusion3() && (inCallDevSwitch == true)) {
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700475 if (csd_disable_device == NULL) {
476 ALOGE("dlsym:Error:%s Loading csd_client_disable_device", dlerror());
477 } else {
478 err = csd_disable_device();
479 if (err < 0)
480 {
481 ALOGE("csd_client_disable_device, failed, error %d", err);
482 }
Ajay Dudani91bf8912012-08-20 18:48:13 -0700483 }
484 }
485#endif
486
Iliyan Malchev4765c432012-06-11 14:36:16 -0700487 snd_use_case_get(handle->ucMgr, "_verb", (const char **)&use_case);
488 mods_size = snd_use_case_get_list(handle->ucMgr, "_enamods", &mods_list);
489 if (rxDevice != NULL) {
490 if ((strncmp(curRxUCMDevice, "None", 4)) &&
491 ((strncmp(rxDevice, curRxUCMDevice, MAX_STR_LEN)) || (inCallDevSwitch == true))) {
492 if ((use_case != NULL) && (strncmp(use_case, SND_USE_CASE_VERB_INACTIVE,
493 strlen(SND_USE_CASE_VERB_INACTIVE)))) {
494 usecase_type = getUseCaseType(use_case);
495 if (usecase_type & USECASE_TYPE_RX) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700496 ALOGD("Deroute use case %s type is %d\n", use_case, usecase_type);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700497 strlcpy(useCaseNode.useCase, use_case, MAX_STR_LEN);
498 snd_use_case_set(handle->ucMgr, "_verb", SND_USE_CASE_VERB_INACTIVE);
499 mUseCaseList.push_front(useCaseNode);
500 }
501 }
502 if (mods_size) {
503 for(index = 0; index < mods_size; index++) {
504 usecase_type = getUseCaseType(mods_list[index]);
505 if (usecase_type & USECASE_TYPE_RX) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700506 ALOGD("Deroute use case %s type is %d\n", mods_list[index], usecase_type);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700507 strlcpy(useCaseNode.useCase, mods_list[index], MAX_STR_LEN);
508 snd_use_case_set(handle->ucMgr, "_dismod", mods_list[index]);
509 mUseCaseList.push_back(useCaseNode);
510 }
511 }
512 }
513 snd_use_case_set(handle->ucMgr, "_disdev", curRxUCMDevice);
514 }
515 }
516 if (txDevice != NULL) {
517 if ((strncmp(curTxUCMDevice, "None", 4)) &&
518 ((strncmp(txDevice, curTxUCMDevice, MAX_STR_LEN)) || (inCallDevSwitch == true))) {
519 if ((use_case != NULL) && (strncmp(use_case, SND_USE_CASE_VERB_INACTIVE,
520 strlen(SND_USE_CASE_VERB_INACTIVE)))) {
521 usecase_type = getUseCaseType(use_case);
522 if ((usecase_type & USECASE_TYPE_TX) && (!(usecase_type & USECASE_TYPE_RX))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700523 ALOGD("Deroute use case %s type is %d\n", use_case, usecase_type);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700524 strlcpy(useCaseNode.useCase, use_case, MAX_STR_LEN);
525 snd_use_case_set(handle->ucMgr, "_verb", SND_USE_CASE_VERB_INACTIVE);
526 mUseCaseList.push_front(useCaseNode);
527 }
528 }
529 if (mods_size) {
530 for(index = 0; index < mods_size; index++) {
531 usecase_type = getUseCaseType(mods_list[index]);
532 if ((usecase_type & USECASE_TYPE_TX) && (!(usecase_type & USECASE_TYPE_RX))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700533 ALOGD("Deroute use case %s type is %d\n", mods_list[index], usecase_type);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700534 strlcpy(useCaseNode.useCase, mods_list[index], MAX_STR_LEN);
535 snd_use_case_set(handle->ucMgr, "_dismod", mods_list[index]);
536 mUseCaseList.push_back(useCaseNode);
537 }
538 }
539 }
540 snd_use_case_set(handle->ucMgr, "_disdev", curTxUCMDevice);
541 }
542 }
SathishKumar Mani9efed762012-09-18 18:52:48 -0700543 ALOGD("%s,rxDev:%s, txDev:%s, curRxDev:%s, curTxDev:%s\n", __FUNCTION__, rxDevice, txDevice, curRxUCMDevice, curTxUCMDevice);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700544
545 if (rxDevice != NULL) {
546 snd_use_case_set(handle->ucMgr, "_enadev", rxDevice);
547 strlcpy(curRxUCMDevice, rxDevice, sizeof(curRxUCMDevice));
Ajay Dudani9746c472012-06-18 16:01:16 -0700548#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700549 if (devices & AudioSystem::DEVICE_OUT_FM)
550 s_set_fm_vol(fmVolume);
551#endif
552 }
553 if (txDevice != NULL) {
554 snd_use_case_set(handle->ucMgr, "_enadev", txDevice);
555 strlcpy(curTxUCMDevice, txDevice, sizeof(curTxUCMDevice));
556 }
557 for(ALSAUseCaseList::iterator it = mUseCaseList.begin(); it != mUseCaseList.end(); ++it) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700558 ALOGD("Route use case %s\n", it->useCase);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700559 if ((use_case != NULL) && (strncmp(use_case, SND_USE_CASE_VERB_INACTIVE,
560 strlen(SND_USE_CASE_VERB_INACTIVE))) && (!strncmp(use_case, it->useCase, MAX_UC_LEN))) {
561 snd_use_case_set(handle->ucMgr, "_verb", it->useCase);
562 } else {
563 snd_use_case_set(handle->ucMgr, "_enamod", it->useCase);
564 }
565 }
566 if (!mUseCaseList.empty())
567 mUseCaseList.clear();
568 if (use_case != NULL) {
569 free(use_case);
570 use_case = NULL;
571 }
Iliyan Malchev4113f342012-06-11 14:39:47 -0700572 ALOGD("switchDevice: curTxUCMDevivce %s curRxDevDevice %s", curTxUCMDevice, curRxUCMDevice);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700573
SathishKumar Manic669c272012-09-21 20:12:08 -0700574 if (platform_is_Fusion3() && (inCallDevSwitch == true)) {
Iliyan Malchev4765c432012-06-11 14:36:16 -0700575 /* get tx acdb id */
576 memset(&ident,0,sizeof(ident));
577 strlcpy(ident, "ACDBID/", sizeof(ident));
578 strlcat(ident, curTxUCMDevice, sizeof(ident));
579 tx_dev_id = snd_use_case_get(handle->ucMgr, ident, NULL);
580
581 /* get rx acdb id */
582 memset(&ident,0,sizeof(ident));
583 strlcpy(ident, "ACDBID/", sizeof(ident));
584 strlcat(ident, curRxUCMDevice, sizeof(ident));
585 rx_dev_id = snd_use_case_get(handle->ucMgr, ident, NULL);
586
ehgrace.kim91e9fad2012-07-02 18:27:28 -0700587 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 -0700588 && tx_dev_id == DEVICE_HANDSET_TX_ACDB_ID) {
Iliyan Malchev4765c432012-06-11 14:36:16 -0700589 tx_dev_id = DEVICE_SPEAKER_TX_ACDB_ID;
590 }
591
Ajay Dudani9746c472012-06-18 16:01:16 -0700592#ifdef QCOM_CSDCLIENT_ENABLED
Iliyan Malchev4113f342012-06-11 14:39:47 -0700593 ALOGV("rx_dev_id=%d, tx_dev_id=%d\n", rx_dev_id, tx_dev_id);
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700594 if (csd_enable_device == NULL) {
595 ALOGE("dlsym:Error:%s Loading csd_client_enable_device", dlerror());
596 } else {
597 err = csd_enable_device(rx_dev_id, tx_dev_id, mDevSettingsFlag);
598 if (err < 0)
599 {
600 ALOGE("csd_client_disable_device failed, error %d", err);
601 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700602 }
Iliyan Malchev4113f342012-06-11 14:39:47 -0700603#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700604 }
605
606 if (rxDevice != NULL) {
Iliyan Malchev4765c432012-06-11 14:36:16 -0700607 free(rxDevice);
608 rxDevice = NULL;
609 }
610 if (txDevice != NULL) {
611 free(txDevice);
612 txDevice = NULL;
613 }
614}
615
616// ----------------------------------------------------------------------------
617
618static status_t s_init(alsa_device_t *module, ALSAHandleList &list)
619{
SathishKumar Mani9efed762012-09-18 18:52:48 -0700620 ALOGV("s_init: Initializing devices for ALSA module");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700621
622 list.clear();
623
624 return NO_ERROR;
625}
626
627static status_t s_open(alsa_handle_t *handle)
628{
629 char *devName;
630 unsigned flags = 0;
631 int err = NO_ERROR;
632
SathishKumar Manib357a772012-09-25 23:28:29 -0700633 if(handle->devices & AudioSystem::DEVICE_OUT_AUX_DIGITAL) {
634 err = setHDMIChannelCount();
635 if(err != OK) {
636 ALOGE("setHDMIChannelCount err = %d", err);
637 return err;
638 }
639 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700640 /* No need to call s_close for LPA as pcm device open and close is handled by LPAPlayer in stagefright */
641 if((!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER)) || (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_LPA))
642 ||(!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 -0700643 ALOGV("s_open: Opening LPA /Tunnel playback");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700644 return NO_ERROR;
645 }
646
647 s_close(handle);
648
SathishKumar Mani9efed762012-09-18 18:52:48 -0700649 ALOGV("s_open: handle %p", handle);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700650
651 // ASoC multicomponent requires a valid path (frontend/backend) for
652 // the device to be opened
653
654 // The PCM stream is opened in blocking mode, per ALSA defaults. The
655 // AudioFlinger seems to assume blocking mode too, so asynchronous mode
656 // should not be used.
SathishKumar Mani88613382012-08-13 18:40:18 -0700657 if ((!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER)) ||
658 (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_LPA)) ||
659 (!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_TUNNEL)) ||
660 (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_TUNNEL))) {
661 ALOGV("LPA/tunnel use case");
662 flags |= PCM_MMAP;
663 flags |= DEBUG_ON;
664 } else if ((!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI)) ||
SathishKumar Manibf1c8742012-09-25 23:34:51 -0700665 (!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI2)) ||
SathishKumar Mani88613382012-08-13 18:40:18 -0700666 (!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC)) ||
667 (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC)) ||
SathishKumar Manibf1c8742012-09-25 23:34:51 -0700668 (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_MUSIC2)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -0700669 (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_MUSIC))) {
SathishKumar Mani88613382012-08-13 18:40:18 -0700670 ALOGV("Music case");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700671 flags = PCM_OUT;
672 } else {
673 flags = PCM_IN;
674 }
675 if (handle->channels == 1) {
676 flags |= PCM_MONO;
SathishKumar Manie42406e2012-08-29 16:25:54 -0700677 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700678 else if (handle->channels == 4 ) {
679 flags |= PCM_QUAD;
680 } else if (handle->channels == 6 ) {
SathishKumar Manibf1c8742012-09-25 23:34:51 -0700681#ifdef QCOM_SSR_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -0700682 if (!strncmp(handle->useCase, SND_USE_CASE_VERB_HIFI_REC, strlen(SND_USE_CASE_VERB_HIFI_REC))
683 || !strncmp(handle->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, strlen(SND_USE_CASE_MOD_CAPTURE_MUSIC))) {
684 flags |= PCM_QUAD;
685 } else {
686 flags |= PCM_5POINT1;
687 }
SathishKumar Manibf1c8742012-09-25 23:34:51 -0700688#else
689 flags |= PCM_5POINT1;
Iliyan Malchev4765c432012-06-11 14:36:16 -0700690#endif
SathishKumar Manibf1c8742012-09-25 23:34:51 -0700691 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700692 else {
693 flags |= PCM_STEREO;
694 }
695 if (deviceName(handle, flags, &devName) < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700696 ALOGE("Failed to get pcm device node: %s", devName);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700697 return NO_INIT;
698 }
699 if (devName != NULL) {
700 handle->handle = pcm_open(flags, (char*)devName);
701 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700702 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700703 return NO_INIT;
704 }
705
706 if (!handle->handle) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700707 ALOGE("s_open: Failed to initialize ALSA device '%s'", devName);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700708 free(devName);
709 return NO_INIT;
710 }
711
712 handle->handle->flags = flags;
713 err = setHardwareParams(handle);
714
715 if (err == NO_ERROR) {
716 err = setSoftwareParams(handle);
717 }
718
719 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700720 ALOGE("Set HW/SW params failed: Closing the pcm stream");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700721 s_standby(handle);
722 }
723
724 free(devName);
725 return NO_ERROR;
726}
727
728static status_t s_start_voip_call(alsa_handle_t *handle)
729{
730
731 char* devName;
732 char* devName1;
733 unsigned flags = 0;
734 int err = NO_ERROR;
735 uint8_t voc_pkt[VOIP_BUFFER_MAX_SIZE];
736
737 s_close(handle);
738 flags = PCM_OUT;
739 flags |= PCM_MONO;
Iliyan Malchev4113f342012-06-11 14:39:47 -0700740 ALOGV("s_open:s_start_voip_call handle %p", handle);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700741
742 if (deviceName(handle, flags, &devName) < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700743 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700744 return NO_INIT;
745 }
746
747 if (devName != NULL) {
748 handle->handle = pcm_open(flags, (char*)devName);
749 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700750 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700751 return NO_INIT;
752 }
753
754 if (!handle->handle) {
755 free(devName);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700756 ALOGE("s_open: Failed to initialize ALSA device '%s'", devName);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700757 return NO_INIT;
758 }
759
760 if (!pcm_ready(handle->handle)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700761 ALOGE(" pcm ready failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700762 }
763
764 handle->handle->flags = flags;
765 err = setHardwareParams(handle);
766
767 if (err == NO_ERROR) {
768 err = setSoftwareParams(handle);
769 }
770
771 err = pcm_prepare(handle->handle);
772 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700773 ALOGE("DEVICE_OUT_DIRECTOUTPUT: pcm_prepare failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700774 }
775
776 /* first write required start dsp */
777 memset(&voc_pkt,0,sizeof(voc_pkt));
778 pcm_write(handle->handle,&voc_pkt,handle->handle->period_size);
779 handle->rxHandle = handle->handle;
780 free(devName);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700781 ALOGV("s_open: DEVICE_IN_COMMUNICATION ");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700782 flags = PCM_IN;
783 flags |= PCM_MONO;
784 handle->handle = 0;
785
786 if (deviceName(handle, flags, &devName1) < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700787 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700788 return NO_INIT;
789 }
790 if (devName != NULL) {
791 handle->handle = pcm_open(flags, (char*)devName1);
792 } else {
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
797 if (!handle->handle) {
798 free(devName);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700799 ALOGE("s_open: Failed to initialize ALSA device '%s'", devName);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700800 return NO_INIT;
801 }
802
803 if (!pcm_ready(handle->handle)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700804 ALOGE(" pcm ready in failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700805 }
806
807 handle->handle->flags = flags;
808
809 err = setHardwareParams(handle);
810
811 if (err == NO_ERROR) {
812 err = setSoftwareParams(handle);
813 }
814
815
816 err = pcm_prepare(handle->handle);
817 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700818 ALOGE("DEVICE_IN_COMMUNICATION: pcm_prepare failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700819 }
820
821 /* first read required start dsp */
822 memset(&voc_pkt,0,sizeof(voc_pkt));
823 pcm_read(handle->handle,&voc_pkt,handle->handle->period_size);
824 return NO_ERROR;
825}
826
827static status_t s_start_voice_call(alsa_handle_t *handle)
828{
829 char* devName;
830 unsigned flags = 0;
831 int err = NO_ERROR;
832
SathishKumar Mani9efed762012-09-18 18:52:48 -0700833 ALOGV("s_start_voice_call: handle %p", handle);
Ajay Dudani86c852b2012-07-19 15:28:45 -0700834
Iliyan Malchev4765c432012-06-11 14:36:16 -0700835 // ASoC multicomponent requires a valid path (frontend/backend) for
836 // the device to be opened
837
838 flags = PCM_OUT | PCM_MONO;
839 if (deviceName(handle, flags, &devName) < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700840 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700841 return NO_INIT;
842 }
843 if (devName != NULL) {
844 handle->handle = pcm_open(flags, (char*)devName);
845 } else {
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 (!handle->handle) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700850 ALOGE("s_start_voicecall: could not open PCM device");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700851 goto Error;
852 }
853
854 handle->handle->flags = flags;
855 err = setHardwareParams(handle);
856 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700857 ALOGE("s_start_voice_call: setHardwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700858 goto Error;
859 }
860
861 err = setSoftwareParams(handle);
862 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700863 ALOGE("s_start_voice_call: setSoftwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700864 goto Error;
865 }
866
867 err = pcm_prepare(handle->handle);
868 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700869 ALOGE("s_start_voice_call: pcm_prepare failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700870 goto Error;
871 }
872
873 if (ioctl(handle->handle->fd, SNDRV_PCM_IOCTL_START)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700874 ALOGE("s_start_voice_call:SNDRV_PCM_IOCTL_START failed\n");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700875 goto Error;
876 }
877
878 // Store the PCM playback device pointer in rxHandle
879 handle->rxHandle = handle->handle;
880 free(devName);
881
882 // Open PCM capture device
883 flags = PCM_IN | PCM_MONO;
884 if (deviceName(handle, flags, &devName) < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700885 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700886 goto Error;
887 }
888 if (devName != NULL) {
889 handle->handle = pcm_open(flags, (char*)devName);
890 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700891 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700892 return NO_INIT;
893 }
894 if (!handle->handle) {
895 free(devName);
896 goto Error;
897 }
898
899 handle->handle->flags = flags;
900 err = setHardwareParams(handle);
901 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700902 ALOGE("s_start_voice_call: setHardwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700903 goto Error;
904 }
905
906 err = setSoftwareParams(handle);
907 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700908 ALOGE("s_start_voice_call: setSoftwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700909 goto Error;
910 }
911
912 err = pcm_prepare(handle->handle);
913 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700914 ALOGE("s_start_voice_call: pcm_prepare failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700915 goto Error;
916 }
917
918 if (ioctl(handle->handle->fd, SNDRV_PCM_IOCTL_START)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700919 ALOGE("s_start_voice_call:SNDRV_PCM_IOCTL_START failed\n");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700920 goto Error;
921 }
922
923 if (platform_is_Fusion3()) {
Ajay Dudani9746c472012-06-18 16:01:16 -0700924#ifdef QCOM_CSDCLIENT_ENABLED
SathishKumar Mani5ff7a022012-09-14 11:36:35 -0700925 if (csd_start_voice == NULL) {
926 ALOGE("dlsym:Error:%s Loading csd_client_start_voice", dlerror());
927 } else {
928 err = csd_start_voice();
929 if (err < 0){
930 ALOGE("s_start_voice_call: csd_client error %d\n", err);
931 goto Error;
932 }
Iliyan Malchev4765c432012-06-11 14:36:16 -0700933 }
Iliyan Malchev4113f342012-06-11 14:39:47 -0700934#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700935 }
936
937 free(devName);
938 return NO_ERROR;
939
940Error:
Iliyan Malchev4113f342012-06-11 14:39:47 -0700941 ALOGE("s_start_voice_call: Failed to initialize ALSA device '%s'", devName);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700942 free(devName);
943 s_close(handle);
944 return NO_INIT;
945}
946
947static status_t s_start_fm(alsa_handle_t *handle)
948{
949 char *devName;
950 unsigned flags = 0;
951 int err = NO_ERROR;
952
SathishKumar Mani9efed762012-09-18 18:52:48 -0700953 ALOGV("s_start_fm: handle %p", handle);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700954
955 // ASoC multicomponent requires a valid path (frontend/backend) for
956 // the device to be opened
957
958 flags = PCM_OUT | PCM_STEREO;
959 if (deviceName(handle, flags, &devName) < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700960 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700961 goto Error;
962 }
963 if (devName != NULL) {
964 handle->handle = pcm_open(flags, (char*)devName);
965 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700966 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700967 return NO_INIT;
968 }
969 if (!handle->handle) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700970 ALOGE("s_start_fm: could not open PCM device");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700971 goto Error;
972 }
973
974 handle->handle->flags = flags;
975 err = setHardwareParams(handle);
976 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700977 ALOGE("s_start_fm: setHardwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700978 goto Error;
979 }
980
981 err = setSoftwareParams(handle);
982 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700983 ALOGE("s_start_fm: setSoftwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700984 goto Error;
985 }
986
987 err = pcm_prepare(handle->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 if (ioctl(handle->handle->fd, SNDRV_PCM_IOCTL_START)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700994 ALOGE("s_start_fm: SNDRV_PCM_IOCTL_START failed\n");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700995 goto Error;
996 }
997
998 // Store the PCM playback device pointer in rxHandle
999 handle->rxHandle = handle->handle;
1000 free(devName);
1001
1002 // Open PCM capture device
1003 flags = PCM_IN | PCM_STEREO;
1004 if (deviceName(handle, flags, &devName) < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001005 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001006 goto Error;
1007 }
1008 if (devName != NULL) {
1009 handle->handle = pcm_open(flags, (char*)devName);
1010 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001011 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001012 return NO_INIT;
1013 }
1014 if (!handle->handle) {
1015 goto Error;
1016 }
1017
1018 handle->handle->flags = flags;
1019 err = setHardwareParams(handle);
1020 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001021 ALOGE("s_start_fm: setHardwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001022 goto Error;
1023 }
1024
1025 err = setSoftwareParams(handle);
1026 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001027 ALOGE("s_start_fm: setSoftwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001028 goto Error;
1029 }
1030
1031 err = pcm_prepare(handle->handle);
1032 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001033 ALOGE("s_start_fm: pcm_prepare failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001034 goto Error;
1035 }
1036
1037 if (ioctl(handle->handle->fd, SNDRV_PCM_IOCTL_START)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001038 ALOGE("s_start_fm: SNDRV_PCM_IOCTL_START failed\n");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001039 goto Error;
1040 }
1041
1042 s_set_fm_vol(fmVolume);
1043 free(devName);
1044 return NO_ERROR;
1045
1046Error:
1047 free(devName);
1048 s_close(handle);
1049 return NO_INIT;
1050}
1051
1052static status_t s_set_fm_vol(int value)
1053{
1054 status_t err = NO_ERROR;
1055
1056 ALSAControl control("/dev/snd/controlC0");
1057 control.set("Internal FM RX Volume",value,0);
1058 fmVolume = value;
1059
1060 return err;
1061}
1062
1063static status_t s_set_lpa_vol(int value)
1064{
1065 status_t err = NO_ERROR;
1066
1067 ALSAControl control("/dev/snd/controlC0");
1068 control.set("LPA RX Volume",value,0);
1069
1070 return err;
1071}
1072
1073static status_t s_start(alsa_handle_t *handle)
1074{
1075 status_t err = NO_ERROR;
1076
1077 if(!handle->handle) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001078 ALOGE("No active PCM driver to start");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001079 return err;
1080 }
1081
1082 err = pcm_prepare(handle->handle);
1083
1084 return err;
1085}
1086
1087static status_t s_close(alsa_handle_t *handle)
1088{
1089 int ret;
1090 status_t err = NO_ERROR;
1091 struct pcm *h = handle->rxHandle;
1092
1093 handle->rxHandle = 0;
SathishKumar Mani9efed762012-09-18 18:52:48 -07001094 ALOGV("s_close: handle %p h %p", handle, h);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001095 if (h) {
SathishKumar Mani0f5426b2012-10-15 14:56:17 -07001096 if ((!strcmp(handle->useCase, SND_USE_CASE_VERB_VOICECALL) ||
1097 !strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_VOICE)) &&
1098 platform_is_Fusion3()) {
1099#ifdef QCOM_CSDCLIENT_ENABLED
1100 if (csd_stop_voice == NULL) {
1101 ALOGE("dlsym:Error:%s Loading csd_client_disable_device", dlerror());
1102 } else {
1103 err = csd_stop_voice();
1104 if (err < 0) {
1105 ALOGE("s_close: csd_client error %d\n", err);
1106 }
1107 }
1108#endif
1109 }
1110
Iliyan Malchev4113f342012-06-11 14:39:47 -07001111 ALOGV("s_close rxHandle\n");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001112 err = pcm_close(h);
1113 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001114 ALOGE("s_close: pcm_close failed for rxHandle with err %d", err);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001115 }
1116 }
1117
1118 h = handle->handle;
1119 handle->handle = 0;
1120
1121 if (h) {
SathishKumar Mani9efed762012-09-18 18:52:48 -07001122 ALOGV("s_close handle h %p\n", h);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001123 err = pcm_close(h);
1124 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001125 ALOGE("s_close: pcm_close failed for handle with err %d", err);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001126 }
1127
Iliyan Malchev4765c432012-06-11 14:36:16 -07001128 disableDevice(handle);
1129 } else if((!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER)) ||
1130 (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_LPA)) ||
1131 (!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_TUNNEL)) ||
1132 (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_TUNNEL))){
1133 disableDevice(handle);
1134 }
1135
1136 return err;
1137}
1138
1139/*
1140 this is same as s_close, but don't discard
1141 the device/mode info. This way we can still
1142 close the device, hit idle and power-save, reopen the pcm
1143 for the same device/mode after resuming
1144*/
1145static status_t s_standby(alsa_handle_t *handle)
1146{
1147 int ret;
SathishKumar Manie42406e2012-08-29 16:25:54 -07001148 status_t err = NO_ERROR;
Iliyan Malchev4765c432012-06-11 14:36:16 -07001149 struct pcm *h = handle->rxHandle;
1150 handle->rxHandle = 0;
SathishKumar Mani9efed762012-09-18 18:52:48 -07001151 ALOGV("s_standby: handle %p h %p", handle, h);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001152 if (h) {
SathishKumar Mani0a019912012-09-11 12:33:11 -07001153 ALOGD("s_standby rxHandle\n");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001154 err = pcm_close(h);
1155 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001156 ALOGE("s_standby: pcm_close failed for rxHandle with err %d", err);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001157 }
1158 }
1159
1160 h = handle->handle;
1161 handle->handle = 0;
1162
1163 if (h) {
SathishKumar Mani9efed762012-09-18 18:52:48 -07001164 ALOGV("s_standby handle h %p\n", h);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001165 err = pcm_close(h);
1166 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001167 ALOGE("s_standby: pcm_close failed for handle with err %d", err);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001168 }
1169 disableDevice(handle);
1170 } else if((!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER)) ||
1171 (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_LPA)) ||
1172 (!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_TUNNEL)) ||
1173 (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_TUNNEL))) {
1174 disableDevice(handle);
1175 }
1176
1177 return err;
1178}
1179
1180static status_t s_route(alsa_handle_t *handle, uint32_t devices, int mode)
1181{
1182 status_t status = NO_ERROR;
1183
Iliyan Malchev4113f342012-06-11 14:39:47 -07001184 ALOGD("s_route: devices 0x%x in mode %d", devices, mode);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001185 callMode = mode;
1186 switchDevice(handle, devices, mode);
1187 return status;
1188}
1189
1190int getUseCaseType(const char *useCase)
1191{
SathishKumar Mani0a019912012-09-11 12:33:11 -07001192 ALOGD("use case is %s\n", useCase);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001193 if (!strncmp(useCase, SND_USE_CASE_VERB_HIFI,
chahee.kima8b76532012-10-01 16:34:06 +09001194 MAX_LEN(useCase,SND_USE_CASE_VERB_HIFI)) ||
SathishKumar Manibf1c8742012-09-25 23:34:51 -07001195 !strncmp(useCase, SND_USE_CASE_VERB_HIFI2,
1196 MAX_LEN(useCase, SND_USE_CASE_VERB_HIFI2)) ||
SathishKumar Mani88613382012-08-13 18:40:18 -07001197 !strncmp(useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC,
chahee.kima8b76532012-10-01 16:34:06 +09001198 MAX_LEN(useCase,SND_USE_CASE_VERB_HIFI_LOWLATENCY_MUSIC)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001199 !strncmp(useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER,
chahee.kima8b76532012-10-01 16:34:06 +09001200 MAX_LEN(useCase,SND_USE_CASE_VERB_HIFI_LOW_POWER)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001201 !strncmp(useCase, SND_USE_CASE_VERB_HIFI_TUNNEL,
chahee.kima8b76532012-10-01 16:34:06 +09001202 MAX_LEN(useCase,SND_USE_CASE_VERB_HIFI_TUNNEL)) ||
1203 !strncmp(useCase, SND_USE_CASE_VERB_HIFI2,
1204 MAX_LEN(useCase,SND_USE_CASE_VERB_HIFI2)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001205 !strncmp(useCase, SND_USE_CASE_VERB_DIGITAL_RADIO,
chahee.kima8b76532012-10-01 16:34:06 +09001206 MAX_LEN(useCase,SND_USE_CASE_VERB_DIGITAL_RADIO)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001207 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_MUSIC,
chahee.kima8b76532012-10-01 16:34:06 +09001208 MAX_LEN(useCase,SND_USE_CASE_MOD_PLAY_MUSIC)) ||
SathishKumar Manibf1c8742012-09-25 23:34:51 -07001209 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_MUSIC2,
1210 MAX_LEN(useCase, SND_USE_CASE_MOD_PLAY_MUSIC2)) ||
SathishKumar Mani88613382012-08-13 18:40:18 -07001211 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC,
chahee.kima8b76532012-10-01 16:34:06 +09001212 MAX_LEN(useCase,SND_USE_CASE_MOD_PLAY_LOWLATENCY_MUSIC)) ||
1213 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_MUSIC2,
1214 MAX_LEN(useCase,SND_USE_CASE_MOD_PLAY_MUSIC2)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001215 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_LPA,
chahee.kima8b76532012-10-01 16:34:06 +09001216 MAX_LEN(useCase,SND_USE_CASE_MOD_PLAY_LPA)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001217 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_TUNNEL,
chahee.kima8b76532012-10-01 16:34:06 +09001218 MAX_LEN(useCase,SND_USE_CASE_MOD_PLAY_TUNNEL)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001219 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_FM,
chahee.kima8b76532012-10-01 16:34:06 +09001220 MAX_LEN(useCase,SND_USE_CASE_MOD_PLAY_FM))) {
Iliyan Malchev4765c432012-06-11 14:36:16 -07001221 return USECASE_TYPE_RX;
1222 } else if (!strncmp(useCase, SND_USE_CASE_VERB_HIFI_REC,
chahee.kima8b76532012-10-01 16:34:06 +09001223 MAX_LEN(useCase,SND_USE_CASE_VERB_HIFI_REC)) ||
SathishKumar Mani88613382012-08-13 18:40:18 -07001224 !strncmp(useCase, SND_USE_CASE_VERB_HIFI_LOWLATENCY_REC,
chahee.kima8b76532012-10-01 16:34:06 +09001225 MAX_LEN(useCase,SND_USE_CASE_VERB_HIFI_LOWLATENCY_REC)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001226 !strncmp(useCase, SND_USE_CASE_VERB_FM_REC,
chahee.kima8b76532012-10-01 16:34:06 +09001227 MAX_LEN(useCase,SND_USE_CASE_VERB_FM_REC)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001228 !strncmp(useCase, SND_USE_CASE_VERB_FM_A2DP_REC,
chahee.kima8b76532012-10-01 16:34:06 +09001229 MAX_LEN(useCase,SND_USE_CASE_VERB_FM_A2DP_REC)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001230 !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC,
chahee.kima8b76532012-10-01 16:34:06 +09001231 MAX_LEN(useCase,SND_USE_CASE_MOD_CAPTURE_MUSIC)) ||
SathishKumar Mani88613382012-08-13 18:40:18 -07001232 !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_LOWLATENCY_MUSIC,
chahee.kima8b76532012-10-01 16:34:06 +09001233 MAX_LEN(useCase,SND_USE_CASE_MOD_CAPTURE_LOWLATENCY_MUSIC)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001234 !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_FM,
chahee.kima8b76532012-10-01 16:34:06 +09001235 MAX_LEN(useCase,SND_USE_CASE_MOD_CAPTURE_FM)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001236 !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_A2DP_FM,
chahee.kima8b76532012-10-01 16:34:06 +09001237 MAX_LEN(useCase,SND_USE_CASE_MOD_CAPTURE_A2DP_FM))) {
Iliyan Malchev4765c432012-06-11 14:36:16 -07001238 return USECASE_TYPE_TX;
1239 } else if (!strncmp(useCase, SND_USE_CASE_VERB_VOICECALL,
chahee.kima8b76532012-10-01 16:34:06 +09001240 MAX_LEN(useCase,SND_USE_CASE_VERB_VOICECALL)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001241 !strncmp(useCase, SND_USE_CASE_VERB_IP_VOICECALL,
chahee.kima8b76532012-10-01 16:34:06 +09001242 MAX_LEN(useCase,SND_USE_CASE_VERB_IP_VOICECALL)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001243 !strncmp(useCase, SND_USE_CASE_VERB_DL_REC,
chahee.kima8b76532012-10-01 16:34:06 +09001244 MAX_LEN(useCase,SND_USE_CASE_VERB_DL_REC)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001245 !strncmp(useCase, SND_USE_CASE_VERB_UL_DL_REC,
chahee.kima8b76532012-10-01 16:34:06 +09001246 MAX_LEN(useCase,SND_USE_CASE_VERB_UL_DL_REC)) ||
1247 !strncmp(useCase, SND_USE_CASE_VERB_INCALL_REC,
1248 MAX_LEN(useCase,SND_USE_CASE_VERB_INCALL_REC)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001249 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_VOICE,
chahee.kima8b76532012-10-01 16:34:06 +09001250 MAX_LEN(useCase,SND_USE_CASE_MOD_PLAY_VOICE)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001251 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_VOIP,
chahee.kima8b76532012-10-01 16:34:06 +09001252 MAX_LEN(useCase,SND_USE_CASE_MOD_PLAY_VOIP)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001253 !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_VOICE_DL,
chahee.kima8b76532012-10-01 16:34:06 +09001254 MAX_LEN(useCase,SND_USE_CASE_MOD_CAPTURE_VOICE_DL)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001255 !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_VOICE_UL_DL,
chahee.kima8b76532012-10-01 16:34:06 +09001256 MAX_LEN(useCase,SND_USE_CASE_MOD_CAPTURE_VOICE_UL_DL)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001257 !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_VOICE,
chahee.kima8b76532012-10-01 16:34:06 +09001258 MAX_LEN(useCase, SND_USE_CASE_MOD_CAPTURE_VOICE)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001259 !strncmp(useCase, SND_USE_CASE_VERB_VOLTE,
chahee.kima8b76532012-10-01 16:34:06 +09001260 MAX_LEN(useCase,SND_USE_CASE_VERB_VOLTE)) ||
Iliyan Malchev4765c432012-06-11 14:36:16 -07001261 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_VOLTE,
chahee.kima8b76532012-10-01 16:34:06 +09001262 MAX_LEN(useCase, SND_USE_CASE_MOD_PLAY_VOLTE))) {
Iliyan Malchev4765c432012-06-11 14:36:16 -07001263 return (USECASE_TYPE_RX | USECASE_TYPE_TX);
1264 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001265 ALOGE("unknown use case %s\n", useCase);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001266 return 0;
1267 }
1268}
1269
1270static void disableDevice(alsa_handle_t *handle)
1271{
1272 unsigned usecase_type = 0;
1273 int i, mods_size;
1274 char *useCase;
1275 const char **mods_list;
1276
1277 snd_use_case_get(handle->ucMgr, "_verb", (const char **)&useCase);
1278 if (useCase != NULL) {
1279 if (!strncmp(useCase, handle->useCase, MAX_UC_LEN)) {
1280 snd_use_case_set(handle->ucMgr, "_verb", SND_USE_CASE_VERB_INACTIVE);
1281 } else {
1282 snd_use_case_set(handle->ucMgr, "_dismod", handle->useCase);
1283 }
1284 free(useCase);
1285 snd_use_case_get(handle->ucMgr, "_verb", (const char **)&useCase);
1286 if (strncmp(useCase, SND_USE_CASE_VERB_INACTIVE,
1287 strlen(SND_USE_CASE_VERB_INACTIVE)))
1288 usecase_type |= getUseCaseType(useCase);
1289 mods_size = snd_use_case_get_list(handle->ucMgr, "_enamods", &mods_list);
SathishKumar Mani9efed762012-09-18 18:52:48 -07001290 ALOGV("Number of modifiers %d\n", mods_size);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001291 if (mods_size) {
1292 for(i = 0; i < mods_size; i++) {
SathishKumar Mani9efed762012-09-18 18:52:48 -07001293 ALOGV("index %d modifier %s\n", i, mods_list[i]);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001294 usecase_type |= getUseCaseType(mods_list[i]);
1295 }
1296 }
SathishKumar Mani9efed762012-09-18 18:52:48 -07001297 ALOGV("usecase_type is %d\n", usecase_type);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001298 if (!(usecase_type & USECASE_TYPE_TX) && (strncmp(curTxUCMDevice, "None", 4)))
1299 snd_use_case_set(handle->ucMgr, "_disdev", curTxUCMDevice);
1300 if (!(usecase_type & USECASE_TYPE_RX) && (strncmp(curRxUCMDevice, "None", 4)))
1301 snd_use_case_set(handle->ucMgr, "_disdev", curRxUCMDevice);
1302 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001303 ALOGE("Invalid state, no valid use case found to disable");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001304 }
1305 free(useCase);
1306}
1307
1308char *getUCMDevice(uint32_t devices, int input, char *rxDevice)
1309{
1310 if (!input) {
1311 if (!(mDevSettingsFlag & TTY_OFF) &&
1312 (callMode == AudioSystem::MODE_IN_CALL) &&
1313 ((devices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) ||
ty.lee924f7982012-08-01 23:15:30 +09001314 (devices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE))) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001315#ifdef QCOM_ANC_HEADSET_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001316 ||
1317 (devices & AudioSystem::DEVICE_OUT_ANC_HEADSET) ||
1318 (devices & AudioSystem::DEVICE_OUT_ANC_HEADPHONE))) {
1319#endif
1320 if (mDevSettingsFlag & TTY_VCO) {
1321 return strdup(SND_USE_CASE_DEV_TTY_HEADSET_RX);
1322 } else if (mDevSettingsFlag & TTY_FULL) {
1323 return strdup(SND_USE_CASE_DEV_TTY_FULL_RX);
1324 } else if (mDevSettingsFlag & TTY_HCO) {
1325 return strdup(SND_USE_CASE_DEV_TTY_HANDSET_RX); /* HANDSET RX */
1326 }
1327 }else if ((devices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET) ||
1328 (devices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)) {
1329 return strdup(SND_USE_CASE_DEV_PROXY_RX); /* PROXY RX */
1330 } else if ((devices & AudioSystem::DEVICE_OUT_SPEAKER) &&
1331 ((devices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) ||
1332 (devices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE))) {
1333 if (mDevSettingsFlag & ANC_FLAG) {
1334 return strdup(SND_USE_CASE_DEV_SPEAKER_ANC_HEADSET); /* COMBO SPEAKER+ANC HEADSET RX */
1335 } else {
1336 return strdup(SND_USE_CASE_DEV_SPEAKER_HEADSET); /* COMBO SPEAKER+HEADSET RX */
1337 }
SathishKumar Mani9eb1a4f2012-10-04 14:14:14 -07001338 } else if ((devices & AudioSystem::DEVICE_OUT_SPEAKER) &&
1339 ((devices & AudioSystem::DEVICE_OUT_AUX_DIGITAL))) {
1340 return strdup(SND_USE_CASE_DEV_HDMI_SPEAKER);
Ajay Dudani9746c472012-06-18 16:01:16 -07001341#ifdef QCOM_ANC_HEADSET_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001342 } else if ((devices & AudioSystem::DEVICE_OUT_SPEAKER) &&
1343 ((devices & AudioSystem::DEVICE_OUT_ANC_HEADSET) ||
1344 (devices & AudioSystem::DEVICE_OUT_ANC_HEADPHONE))) {
1345 return strdup(SND_USE_CASE_DEV_SPEAKER_ANC_HEADSET); /* COMBO SPEAKER+ANC HEADSET RX */
1346 } else if ((devices & AudioSystem::DEVICE_OUT_SPEAKER) &&
1347 (devices & AudioSystem::DEVICE_OUT_FM_TX)) {
1348 return strdup(SND_USE_CASE_DEV_SPEAKER_FM_TX); /* COMBO SPEAKER+FM_TX RX */
1349#endif
1350 } else if (devices & AudioSystem::DEVICE_OUT_EARPIECE) {
ty.lee925596f2012-09-12 18:23:59 +09001351 if (callMode == AudioSystem::MODE_IN_CALL) {
1352 return strdup(SND_USE_CASE_DEV_VOC_EARPIECE); /* Voice HANDSET RX */
1353 } else
1354 return strdup(SND_USE_CASE_DEV_EARPIECE); /* HANDSET RX */
Iliyan Malchev4765c432012-06-11 14:36:16 -07001355 } else if (devices & AudioSystem::DEVICE_OUT_SPEAKER) {
ty.lee925596f2012-09-12 18:23:59 +09001356 if (callMode == AudioSystem::MODE_IN_CALL) {
1357 return strdup(SND_USE_CASE_DEV_VOC_SPEAKER); /* Voice SPEAKER RX */
1358 } else
1359 return strdup(SND_USE_CASE_DEV_SPEAKER); /* SPEAKER RX */
Iliyan Malchev4765c432012-06-11 14:36:16 -07001360 } else if ((devices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) ||
1361 (devices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE)) {
1362 if (mDevSettingsFlag & ANC_FLAG) {
ty.lee925596f2012-09-12 18:23:59 +09001363 if (callMode == AudioSystem::MODE_IN_CALL) {
1364 return strdup(SND_USE_CASE_DEV_VOC_ANC_HEADSET); /* Voice ANC HEADSET RX */
1365 } else
1366 return strdup(SND_USE_CASE_DEV_ANC_HEADSET); /* ANC HEADSET RX */
Iliyan Malchev4765c432012-06-11 14:36:16 -07001367 } else {
ty.lee925596f2012-09-12 18:23:59 +09001368 if (callMode == AudioSystem::MODE_IN_CALL) {
1369 return strdup(SND_USE_CASE_DEV_VOC_HEADPHONE); /* Voice HEADSET RX */
1370 } else
1371 return strdup(SND_USE_CASE_DEV_HEADPHONES); /* HEADSET RX */
Iliyan Malchev4765c432012-06-11 14:36:16 -07001372 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001373#ifdef QCOM_ANC_HEADSET_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001374 } else if ((devices & AudioSystem::DEVICE_OUT_ANC_HEADSET) ||
1375 (devices & AudioSystem::DEVICE_OUT_ANC_HEADPHONE)) {
ty.lee925596f2012-09-12 18:23:59 +09001376 if (callMode == AudioSystem::MODE_IN_CALL) {
1377 return strdup(SND_USE_CASE_DEV_VOC_ANC_HEADSET); /* Voice ANC HEADSET RX */
1378 } else
1379 return strdup(SND_USE_CASE_DEV_ANC_HEADSET); /* ANC HEADSET RX */
Iliyan Malchev4765c432012-06-11 14:36:16 -07001380#endif
1381 } else if ((devices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO) ||
1382 (devices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET) ||
1383 (devices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT)) {
1384 if (btsco_samplerate == BTSCO_RATE_16KHZ)
1385 return strdup(SND_USE_CASE_DEV_BTSCO_WB_RX); /* BTSCO RX*/
1386 else
1387 return strdup(SND_USE_CASE_DEV_BTSCO_NB_RX); /* BTSCO RX*/
1388 } else if ((devices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP) ||
1389 (devices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES) ||
Ajay Dudani9746c472012-06-18 16:01:16 -07001390#ifdef QCOM_VOIP_ENABLED
1391 (devices & AudioSystem::DEVICE_OUT_DIRECTOUTPUT) ||
1392#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001393 (devices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER)) {
1394 /* Nothing to be done, use current active device */
1395 if (strncmp(curRxUCMDevice, "None", 4)) {
1396 return strdup(curRxUCMDevice);
1397 }
1398 } else if (devices & AudioSystem::DEVICE_OUT_AUX_DIGITAL) {
1399 return strdup(SND_USE_CASE_DEV_HDMI); /* HDMI RX */
Ajay Dudani9746c472012-06-18 16:01:16 -07001400#ifdef QCOM_PROXY_DEVICE_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001401 } else if (devices & AudioSystem::DEVICE_OUT_PROXY) {
1402 return strdup(SND_USE_CASE_DEV_PROXY_RX); /* PROXY RX */
Ajay Dudani9746c472012-06-18 16:01:16 -07001403#endif
1404#ifdef QCOM_FM_TX_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001405 } else if (devices & AudioSystem::DEVICE_OUT_FM_TX) {
1406 return strdup(SND_USE_CASE_DEV_FM_TX); /* FM Tx */
1407#endif
1408 } else if (devices & AudioSystem::DEVICE_OUT_DEFAULT) {
ty.lee925596f2012-09-12 18:23:59 +09001409 if (callMode == AudioSystem::MODE_IN_CALL) {
1410 return strdup(SND_USE_CASE_DEV_VOC_SPEAKER); /* Voice SPEAKER RX */
1411 } else
1412 return strdup(SND_USE_CASE_DEV_SPEAKER); /* SPEAKER RX */
Iliyan Malchev4765c432012-06-11 14:36:16 -07001413 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001414 ALOGD("No valid output device: %u", devices);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001415 }
1416 } else {
1417 if (!(mDevSettingsFlag & TTY_OFF) &&
1418 (callMode == AudioSystem::MODE_IN_CALL) &&
ty.lee924f7982012-08-01 23:15:30 +09001419 ((devices & AudioSystem::DEVICE_IN_WIRED_HEADSET))) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001420#ifdef QCOM_ANC_HEADSET_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001421 ||(devices & AudioSystem::DEVICE_IN_ANC_HEADSET))) {
1422#endif
1423 if (mDevSettingsFlag & TTY_HCO) {
1424 return strdup(SND_USE_CASE_DEV_TTY_HEADSET_TX);
1425 } else if (mDevSettingsFlag & TTY_FULL) {
1426 return strdup(SND_USE_CASE_DEV_TTY_FULL_TX);
1427 } else if (mDevSettingsFlag & TTY_VCO) {
1428 if (!strncmp(mic_type, "analog", 6)) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001429 return strdup(SND_USE_CASE_DEV_TTY_HANDSET_ANALOG_TX);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001430 } else {
1431 return strdup(SND_USE_CASE_DEV_TTY_HANDSET_TX);
1432 }
1433 }
1434 } else if (devices & AudioSystem::DEVICE_IN_BUILTIN_MIC) {
1435 if (!strncmp(mic_type, "analog", 6)) {
1436 return strdup(SND_USE_CASE_DEV_HANDSET); /* HANDSET TX */
1437 } else {
1438 if (mDevSettingsFlag & DMIC_FLAG) {
ty.lee924f7982012-08-01 23:15:30 +09001439#ifdef USES_FLUENCE_INCALL
1440 if(callMode == AudioSystem::MODE_IN_CALL) {
1441 if (fluence_mode == FLUENCE_MODE_ENDFIRE) {
1442 return strdup(SND_USE_CASE_DEV_DUAL_MIC_ENDFIRE); /* DUALMIC EF TX */
1443 } else if (fluence_mode == FLUENCE_MODE_BROADSIDE) {
1444 return strdup(SND_USE_CASE_DEV_DUAL_MIC_BROADSIDE); /* DUALMIC BS TX */
1445 } else {
1446 return strdup(SND_USE_CASE_DEV_HANDSET); /* BUILTIN-MIC TX */
1447 }
1448 }
1449#else
Iliyan Malchev4765c432012-06-11 14:36:16 -07001450 if (((rxDevice != NULL) &&
1451 !strncmp(rxDevice, SND_USE_CASE_DEV_SPEAKER,
1452 (strlen(SND_USE_CASE_DEV_SPEAKER)+1))) ||
1453 !strncmp(curRxUCMDevice, SND_USE_CASE_DEV_SPEAKER,
1454 (strlen(SND_USE_CASE_DEV_SPEAKER)+1))) {
1455 if (fluence_mode == FLUENCE_MODE_ENDFIRE) {
1456 return strdup(SND_USE_CASE_DEV_SPEAKER_DUAL_MIC_ENDFIRE); /* DUALMIC EF TX */
1457 } else if (fluence_mode == FLUENCE_MODE_BROADSIDE) {
1458 return strdup(SND_USE_CASE_DEV_SPEAKER_DUAL_MIC_BROADSIDE); /* DUALMIC BS TX */
1459 }
1460 } else {
1461 if (fluence_mode == FLUENCE_MODE_ENDFIRE) {
1462 return strdup(SND_USE_CASE_DEV_DUAL_MIC_ENDFIRE); /* DUALMIC EF TX */
1463 } else if (fluence_mode == FLUENCE_MODE_BROADSIDE) {
1464 return strdup(SND_USE_CASE_DEV_DUAL_MIC_BROADSIDE); /* DUALMIC BS TX */
1465 }
1466 }
ty.lee924f7982012-08-01 23:15:30 +09001467#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001468 } else if (mDevSettingsFlag & QMIC_FLAG){
1469 return strdup(SND_USE_CASE_DEV_QUAD_MIC);
ty.lee924f7982012-08-01 23:15:30 +09001470 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001471#ifdef QCOM_SSR_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001472 else if (mDevSettingsFlag & SSRQMIC_FLAG){
Iliyan Malchev4113f342012-06-11 14:39:47 -07001473 ALOGV("return SSRQMIC_FLAG: 0x%x devices:0x%x",mDevSettingsFlag,devices);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001474 // Mapping for quad mic input device.
1475 return strdup(SND_USE_CASE_DEV_SSR_QUAD_MIC); /* SSR Quad MIC */
ty.lee924f7982012-08-01 23:15:30 +09001476 }
Iliyan Malchev4765c432012-06-11 14:36:16 -07001477#endif
ty.lee74060de2012-08-02 00:47:00 +09001478#ifdef SEPERATED_AUDIO_INPUT
1479 if(input_source == AUDIO_SOURCE_VOICE_RECOGNITION) {
ty.lee74060de2012-08-02 00:47:00 +09001480 return strdup(SND_USE_CASE_DEV_VOICE_RECOGNITION ); /* VOICE RECOGNITION TX */
ty.lee74060de2012-08-02 00:47:00 +09001481 }
1482#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001483 else {
ty.lee74060de2012-08-02 00:47:00 +09001484 return strdup(SND_USE_CASE_DEV_HANDSET); /* BUILTIN-MIC TX */
Iliyan Malchev4765c432012-06-11 14:36:16 -07001485 }
1486 }
1487 } else if (devices & AudioSystem::DEVICE_IN_AUX_DIGITAL) {
1488 return strdup(SND_USE_CASE_DEV_HDMI_TX); /* HDMI TX */
Ajay Dudani9746c472012-06-18 16:01:16 -07001489#ifdef QCOM_ANC_HEADSET_ENABLED
ehgrace.kim249f87d2012-08-12 20:40:32 -07001490 } else if (devices & AudioSystem::DEVICE_IN_ANC_HEADSET) {
Iliyan Malchev4765c432012-06-11 14:36:16 -07001491 return strdup(SND_USE_CASE_DEV_HEADSET); /* HEADSET TX */
1492#endif
ehgrace.kim249f87d2012-08-12 20:40:32 -07001493 } else if (devices & AudioSystem::DEVICE_IN_WIRED_HEADSET) {
ty.lee925596f2012-09-12 18:23:59 +09001494 if (callMode == AudioSystem::MODE_IN_CALL) {
1495 return strdup(SND_USE_CASE_DEV_VOC_HEADSET); /* Voice HEADSET TX */
1496 } else
1497 return strdup(SND_USE_CASE_DEV_HEADSET); /* HEADSET TX */
Iliyan Malchev4765c432012-06-11 14:36:16 -07001498 } else if (devices & AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
1499 if (btsco_samplerate == BTSCO_RATE_16KHZ)
1500 return strdup(SND_USE_CASE_DEV_BTSCO_WB_TX); /* BTSCO TX*/
1501 else
1502 return strdup(SND_USE_CASE_DEV_BTSCO_NB_TX); /* BTSCO TX*/
Ajay Dudani9746c472012-06-18 16:01:16 -07001503#ifdef QCOM_USBAUDIO_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001504 } else if ((devices & AudioSystem::DEVICE_IN_ANLG_DOCK_HEADSET) ||
1505 (devices & AudioSystem::DEVICE_IN_PROXY)) {
1506 return strdup(SND_USE_CASE_DEV_PROXY_TX); /* PROXY TX */
1507#endif
1508 } else if ((devices & AudioSystem::DEVICE_IN_COMMUNICATION) ||
1509 (devices & AudioSystem::DEVICE_IN_VOICE_CALL)) {
1510 /* Nothing to be done, use current active device */
1511 if (strncmp(curTxUCMDevice, "None", 4)) {
1512 return strdup(curTxUCMDevice);
1513 }
Ajay Dudani9746c472012-06-18 16:01:16 -07001514#ifdef QCOM_FM_ENABLED
Iliyan Malchev4765c432012-06-11 14:36:16 -07001515 } else if ((devices & AudioSystem::DEVICE_IN_FM_RX) ||
1516 (devices & AudioSystem::DEVICE_IN_FM_RX_A2DP)) {
1517 /* Nothing to be done, use current tx device or set dummy device */
1518 if (strncmp(curTxUCMDevice, "None", 4)) {
1519 return strdup(curTxUCMDevice);
1520 } else {
1521 return strdup(SND_USE_CASE_DEV_DUMMY_TX);
1522 }
1523#endif
1524 } else if ((devices & AudioSystem::DEVICE_IN_AMBIENT) ||
1525 (devices & AudioSystem::DEVICE_IN_BACK_MIC)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001526 ALOGI("No proper mapping found with UCM device list, setting default");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001527 if (!strncmp(mic_type, "analog", 6)) {
1528 return strdup(SND_USE_CASE_DEV_HANDSET); /* HANDSET TX */
1529 } else {
ty.lee925596f2012-09-12 18:23:59 +09001530 if (callMode == AudioSystem::MODE_IN_CALL) {
1531 return strdup(SND_USE_CASE_DEV_VOC_LINE); /* Voice BUILTIN-MIC TX */
ty.lee87459f02012-09-29 18:49:05 +09001532#ifdef SEPERATED_AUDIO_INPUT
1533 } else if(input_source == AUDIO_SOURCE_CAMCORDER) {
1534 return strdup(SND_USE_CASE_DEV_CAMCORDER_TX ); /* CAMCORDER TX */
1535#endif
ty.lee925596f2012-09-12 18:23:59 +09001536 } else
1537 return strdup(SND_USE_CASE_DEV_LINE); /* BUILTIN-MIC TX */
Iliyan Malchev4765c432012-06-11 14:36:16 -07001538 }
1539 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001540 ALOGD("No valid input device: %u", devices);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001541 }
1542 }
1543 return NULL;
1544}
1545
1546void s_set_voice_volume(int vol)
1547{
1548 int err = 0;
SathishKumar Mani9efed762012-09-18 18:52:48 -07001549 ALOGV("s_set_voice_volume: volume %d", vol);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001550 ALSAControl control("/dev/snd/controlC0");
1551 control.set("Voice Rx Volume", vol, 0);
1552
1553 if (platform_is_Fusion3()) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001554#ifdef QCOM_CSDCLIENT_ENABLED
SathishKumar Mani5ff7a022012-09-14 11:36:35 -07001555 if (csd_volume == NULL) {
1556 ALOGE("dlsym:Error:%s Loading csd_client_volume", dlerror());
1557 } else {
1558 err = csd_volume(vol);
1559 if (err < 0) {
1560 ALOGE("s_set_voice_volume: csd_client error %d", err);
1561 }
SathishKumar Manie42406e2012-08-29 16:25:54 -07001562 }
Iliyan Malchev4113f342012-06-11 14:39:47 -07001563#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001564 }
1565}
1566
1567void s_set_volte_volume(int vol)
1568{
SathishKumar Mani9efed762012-09-18 18:52:48 -07001569 ALOGV("s_set_volte_volume: volume %d", vol);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001570 ALSAControl control("/dev/snd/controlC0");
1571 control.set("VoLTE Rx Volume", vol, 0);
1572}
1573
1574
1575void s_set_voip_volume(int vol)
1576{
SathishKumar Mani9efed762012-09-18 18:52:48 -07001577 ALOGV("s_set_voip_volume: volume %d", vol);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001578 ALSAControl control("/dev/snd/controlC0");
1579 control.set("Voip Rx Volume", vol, 0);
1580}
1581void s_set_mic_mute(int state)
1582{
1583 int err = 0;
SathishKumar Mani9efed762012-09-18 18:52:48 -07001584 ALOGV("s_set_mic_mute: state %d", state);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001585 ALSAControl control("/dev/snd/controlC0");
1586 control.set("Voice Tx Mute", state, 0);
1587
1588 if (platform_is_Fusion3()) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001589#ifdef QCOM_CSDCLIENT_ENABLED
SathishKumar Mani5ff7a022012-09-14 11:36:35 -07001590 if (csd_mic_mute == NULL) {
1591 ALOGE("dlsym:Error:%s Loading csd_mic_mute", dlerror());
1592 } else {
1593 err=csd_mic_mute(state);
1594 if (err < 0) {
1595 ALOGE("s_set_mic_mute: csd_client error %d", err);
1596 }
Iliyan Malchev4765c432012-06-11 14:36:16 -07001597 }
Iliyan Malchev4113f342012-06-11 14:39:47 -07001598#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001599 }
1600}
1601void s_set_volte_mic_mute(int state)
1602{
SathishKumar Mani9efed762012-09-18 18:52:48 -07001603 ALOGV("s_set_volte_mic_mute: state %d", state);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001604 ALSAControl control("/dev/snd/controlC0");
1605 control.set("VoLTE Tx Mute", state, 0);
1606}
1607
1608void s_set_voip_mic_mute(int state)
1609{
SathishKumar Mani9efed762012-09-18 18:52:48 -07001610 ALOGV("s_set_voip_mic_mute: state %d", state);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001611 ALSAControl control("/dev/snd/controlC0");
1612 control.set("Voip Tx Mute", state, 0);
1613}
1614
1615void s_set_voip_config(int mode, int rate)
1616{
SathishKumar Mani9efed762012-09-18 18:52:48 -07001617 ALOGV("s_set_voip_config: mode %d,rate %d", mode, rate);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001618 ALSAControl control("/dev/snd/controlC0");
1619 char** setValues;
1620 setValues = (char**)malloc(2*sizeof(char*));
1621 if (setValues == NULL) {
1622 return;
1623 }
1624 setValues[0] = (char*)malloc(4*sizeof(char));
1625 if (setValues[0] == NULL) {
1626 free(setValues);
1627 return;
1628 }
1629
1630 setValues[1] = (char*)malloc(8*sizeof(char));
1631 if (setValues[1] == NULL) {
1632 free(setValues);
1633 free(setValues[0]);
1634 return;
1635 }
1636
1637 sprintf(setValues[0], "%d",mode);
1638 sprintf(setValues[1], "%d",rate);
1639
1640 control.setext("Voip Mode Rate Config", 2, setValues);
1641 free(setValues[1]);
1642 free(setValues[0]);
1643 free(setValues);
1644 return;
1645}
1646
1647void s_set_btsco_rate(int rate)
1648{
1649 btsco_samplerate = rate;
1650}
1651
1652void s_enable_wide_voice(bool flag)
1653{
1654 int err = 0;
1655
SathishKumar Mani9efed762012-09-18 18:52:48 -07001656 ALOGV("s_enable_wide_voice: flag %d", flag);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001657 ALSAControl control("/dev/snd/controlC0");
1658 if(flag == true) {
1659 control.set("Widevoice Enable", 1, 0);
1660 } else {
1661 control.set("Widevoice Enable", 0, 0);
1662 }
1663
1664 if (platform_is_Fusion3()) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001665#ifdef QCOM_CSDCLIENT_ENABLED
SathishKumar Mani5ff7a022012-09-14 11:36:35 -07001666 if (csd_wide_voice == NULL) {
1667 ALOGE("dlsym:Error:%s Loading csd_wide_voice", dlerror());
1668 } else {
1669 err = csd_wide_voice(flag);
1670 if (err < 0) {
1671 ALOGE("enableWideVoice: csd_client_wide_voice error %d", err);
1672 }
Iliyan Malchev4765c432012-06-11 14:36:16 -07001673 }
Iliyan Malchev4113f342012-06-11 14:39:47 -07001674#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001675 }
1676}
1677
1678void s_set_voc_rec_mode(uint8_t mode)
1679{
SathishKumar Mani9efed762012-09-18 18:52:48 -07001680 ALOGV("s_set_voc_rec_mode: mode %d", mode);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001681 ALSAControl control("/dev/snd/controlC0");
1682 control.set("Incall Rec Mode", mode, 0);
1683}
1684
1685void s_enable_fens(bool flag)
1686{
1687 int err = 0;
1688
SathishKumar Mani9efed762012-09-18 18:52:48 -07001689 ALOGV("s_enable_fens: flag %d", flag);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001690 ALSAControl control("/dev/snd/controlC0");
1691 if(flag == true) {
1692 control.set("FENS Enable", 1, 0);
1693 } else {
1694 control.set("FENS Enable", 0, 0);
1695 }
1696
1697 if (platform_is_Fusion3()) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001698#ifdef QCOM_CSDCLIENT_ENABLED
SathishKumar Mani5ff7a022012-09-14 11:36:35 -07001699 if (csd_fens == NULL) {
1700 ALOGE("dlsym:Error:%s Loading csd_fens", dlerror());
1701 } else {
1702 err = csd_fens(flag);
1703 if (err < 0) {
1704 ALOGE("s_enable_fens: csd_client error %d", err);
1705 }
Iliyan Malchev4765c432012-06-11 14:36:16 -07001706 }
Iliyan Malchev4113f342012-06-11 14:39:47 -07001707#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001708 }
1709}
1710
1711void s_enable_slow_talk(bool flag)
1712{
1713 int err = 0;
1714
SathishKumar Mani9efed762012-09-18 18:52:48 -07001715 ALOGV("s_enable_slow_talk: flag %d", flag);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001716 ALSAControl control("/dev/snd/controlC0");
1717 if(flag == true) {
1718 control.set("Slowtalk Enable", 1, 0);
1719 } else {
1720 control.set("Slowtalk Enable", 0, 0);
1721 }
1722
1723 if (platform_is_Fusion3()) {
Ajay Dudani9746c472012-06-18 16:01:16 -07001724#ifdef QCOM_CSDCLIENT_ENABLED
SathishKumar Mani5ff7a022012-09-14 11:36:35 -07001725 if (csd_slow_talk == NULL) {
1726 ALOGE("dlsym:Error:%s Loading csd_slow_talk", dlerror());
1727 } else {
1728 err = csd_slow_talk(flag);
1729 if (err < 0) {
1730 ALOGE("s_enable_slow_talk: csd_client error %d", err);
1731 }
Iliyan Malchev4765c432012-06-11 14:36:16 -07001732 }
Iliyan Malchev4113f342012-06-11 14:39:47 -07001733#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001734 }
1735}
1736
1737void s_set_flags(uint32_t flags)
1738{
Iliyan Malchev4113f342012-06-11 14:39:47 -07001739 ALOGV("s_set_flags: flags %d", flags);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001740 mDevSettingsFlag = flags;
1741}
1742
1743static status_t s_set_compressed_vol(int value)
1744{
1745 status_t err = NO_ERROR;
1746
1747 ALSAControl control("/dev/snd/controlC0");
1748 control.set("COMPRESSED RX Volume",value,0);
1749
1750 return err;
1751}
1752
ty.lee74060de2012-08-02 00:47:00 +09001753#ifdef SEPERATED_AUDIO_INPUT
1754void s_setInput(int input)
1755{
1756 input_source = input;
1757 ALOGD("s_setInput() : input_source = %d",input_source);
1758}
1759#endif
SathishKumar Mani5ff7a022012-09-14 11:36:35 -07001760
1761#ifdef QCOM_CSDCLIENT_ENABLED
1762static void s_set_csd_handle(void* handle)
1763{
1764 csd_handle = static_cast<void*>(handle);
1765 ALOGI("%s csd_handle: %p", __func__, csd_handle);
1766
1767 csd_disable_device = (int (*)())::dlsym(csd_handle,"csd_client_disable_device");
1768 csd_enable_device = (int (*)(int,int,uint32_t))::dlsym(csd_handle,"csd_client_enable_device");
1769 csd_start_voice = (int (*)())::dlsym(csd_handle,"csd_client_start_voice");
1770 csd_stop_voice = (int (*)())::dlsym(csd_handle,"csd_client_stop_voice");
1771 csd_volume = (int (*)(int))::dlsym(csd_handle,"csd_client_volume");
1772 csd_mic_mute = (int (*)(int))::dlsym(csd_handle,"csd_client_mic_mute");
1773 csd_wide_voice = (int (*)(uint8_t))::dlsym(csd_handle,"csd_client_wide_voice");
1774 csd_fens = (int (*)(uint8_t))::dlsym(csd_handle,"csd_client_fens");
1775 csd_slow_talk = (int (*)(uint8_t))::dlsym(csd_handle,"csd_client_slow_talk");
1776}
1777#endif
1778
Iliyan Malchev4765c432012-06-11 14:36:16 -07001779}