blob: b8767343e36128c7c08bc66097ff0f1f6661133c [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
Iliyan Malchev4113f342012-06-11 14:39:47 -070019#define LOG_TAG "alsa.msm8960"
Iliyan Malchev4765c432012-06-11 14:36:16 -070020//#define LOG_NDEBUG 0
Iliyan Malchev4765c432012-06-11 14:36:16 -070021#include <utils/Log.h>
Iliyan Malchev4113f342012-06-11 14:39:47 -070022
Iliyan Malchev4765c432012-06-11 14:36:16 -070023#include <cutils/properties.h>
24#include <linux/ioctl.h>
25#include "AudioHardwareALSA.h"
26#include <media/AudioRecord.h>
Iliyan Malchev4113f342012-06-11 14:39:47 -070027#if 0
Iliyan Malchev4765c432012-06-11 14:36:16 -070028extern "C" {
29#include "csd_client.h"
30}
Iliyan Malchev4113f342012-06-11 14:39:47 -070031#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -070032
33#ifndef ALSA_DEFAULT_SAMPLE_RATE
34#define ALSA_DEFAULT_SAMPLE_RATE 44100 // in Hz
35#endif
36
37#define BTSCO_RATE_16KHZ 16000
38#define USECASE_TYPE_RX 1
39#define USECASE_TYPE_TX 2
40
41namespace android_audio_legacy
42{
43
44static int s_device_open(const hw_module_t*, const char*, hw_device_t**);
45static int s_device_close(hw_device_t*);
46static status_t s_init(alsa_device_t *, ALSAHandleList &);
47static status_t s_open(alsa_handle_t *);
48static status_t s_close(alsa_handle_t *);
49static status_t s_standby(alsa_handle_t *);
50static status_t s_route(alsa_handle_t *, uint32_t, int);
51static status_t s_start_voice_call(alsa_handle_t *);
52static status_t s_start_voip_call(alsa_handle_t *);
53static status_t s_start_fm(alsa_handle_t *);
54static void s_set_voice_volume(int);
55static void s_set_voip_volume(int);
56static void s_set_mic_mute(int);
57static void s_set_voip_mic_mute(int);
58static void s_set_voip_config(int, int);
59static status_t s_set_fm_vol(int);
60static void s_set_btsco_rate(int);
61static status_t s_set_lpa_vol(int);
62static void s_enable_wide_voice(bool flag);
63static void s_enable_fens(bool flag);
64static void s_set_flags(uint32_t flags);
65static status_t s_set_compressed_vol(int);
66static void s_enable_slow_talk(bool flag);
67static void s_set_voc_rec_mode(uint8_t mode);
68static void s_set_volte_mic_mute(int state);
69static void s_set_volte_volume(int vol);
70
71static char mic_type[25];
72static char curRxUCMDevice[50];
73static char curTxUCMDevice[50];
74static int fluence_mode;
75static int fmVolume;
76static uint32_t mDevSettingsFlag = TTY_OFF;
77static int btsco_samplerate = 8000;
78static bool pflag = false;
79static ALSAUseCaseList mUseCaseList;
80
81static hw_module_methods_t s_module_methods = {
82 open : s_device_open
83};
84
Iliyan Malchev4113f342012-06-11 14:39:47 -070085extern "C" hw_module_t HAL_MODULE_INFO_SYM = {
Iliyan Malchev4765c432012-06-11 14:36:16 -070086 tag : HARDWARE_MODULE_TAG,
87 version_major : 1,
88 version_minor : 0,
89 id : ALSA_HARDWARE_MODULE_ID,
90 name : "QCOM ALSA module",
91 author : "QuIC Inc",
92 methods : &s_module_methods,
93 dso : 0,
94 reserved : {0,},
95};
96
97static int s_device_open(const hw_module_t* module, const char* name,
98 hw_device_t** device)
99{
100 char value[128];
101 alsa_device_t *dev;
102 dev = (alsa_device_t *) malloc(sizeof(*dev));
103 if (!dev) return -ENOMEM;
104
105 memset(dev, 0, sizeof(*dev));
106
107 /* initialize the procs */
108 dev->common.tag = HARDWARE_DEVICE_TAG;
109 dev->common.version = 0;
110 dev->common.module = (hw_module_t *) module;
111 dev->common.close = s_device_close;
112 dev->init = s_init;
113 dev->open = s_open;
114 dev->close = s_close;
115 dev->route = s_route;
116 dev->standby = s_standby;
117 dev->startVoiceCall = s_start_voice_call;
118 dev->startVoipCall = s_start_voip_call;
119 dev->startFm = s_start_fm;
120 dev->setVoiceVolume = s_set_voice_volume;
121 dev->setVoipVolume = s_set_voip_volume;
122 dev->setMicMute = s_set_mic_mute;
123 dev->setVoipMicMute = s_set_voip_mic_mute;
124 dev->setVoipConfig = s_set_voip_config;
125 dev->setFmVolume = s_set_fm_vol;
126 dev->setBtscoRate = s_set_btsco_rate;
127 dev->setLpaVolume = s_set_lpa_vol;
128 dev->enableWideVoice = s_enable_wide_voice;
129 dev->enableFENS = s_enable_fens;
130 dev->setFlags = s_set_flags;
131 dev->setCompressedVolume = s_set_compressed_vol;
132 dev->enableSlowTalk = s_enable_slow_talk;
133 dev->setVocRecMode = s_set_voc_rec_mode;
134 dev->setVoLTEMicMute = s_set_volte_mic_mute;
135 dev->setVoLTEVolume = s_set_volte_volume;
136
137 *device = &dev->common;
138
139 property_get("persist.audio.handset.mic",value,"0");
140 strlcpy(mic_type, value, sizeof(mic_type));
141 property_get("persist.audio.fluence.mode",value,"0");
142 if (!strcmp("broadside", value)) {
143 fluence_mode = FLUENCE_MODE_BROADSIDE;
144 } else {
145 fluence_mode = FLUENCE_MODE_ENDFIRE;
146 }
147 strlcpy(curRxUCMDevice, "None", sizeof(curRxUCMDevice));
148 strlcpy(curTxUCMDevice, "None", sizeof(curTxUCMDevice));
Iliyan Malchev4113f342012-06-11 14:39:47 -0700149 ALOGD("ALSA module opened");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700150
151 return 0;
152}
153
154static int s_device_close(hw_device_t* device)
155{
156 free(device);
157 device = NULL;
158 return 0;
159}
160
161// ----------------------------------------------------------------------------
162
163static const int DEFAULT_SAMPLE_RATE = ALSA_DEFAULT_SAMPLE_RATE;
164
165static void switchDevice(alsa_handle_t *handle, uint32_t devices, uint32_t mode);
166static char *getUCMDevice(uint32_t devices, int input, char *rxDevice);
167static void disableDevice(alsa_handle_t *handle);
168int getUseCaseType(const char *useCase);
169
170static int callMode = AudioSystem::MODE_NORMAL;
171// ----------------------------------------------------------------------------
172
173bool platform_is_Fusion3()
174{
175 char platform[128], baseband[128];
176 property_get("ro.board.platform", platform, "");
177 property_get("ro.baseband", baseband, "");
178 if (!strcmp("msm8960", platform) && !strcmp("mdm", baseband))
179 return true;
180 else
181 return false;
182}
183
184int deviceName(alsa_handle_t *handle, unsigned flags, char **value)
185{
186 int ret = 0;
187 char ident[70];
188
189 if (flags & PCM_IN) {
190 strlcpy(ident, "CapturePCM/", sizeof(ident));
191 } else {
192 strlcpy(ident, "PlaybackPCM/", sizeof(ident));
193 }
194 strlcat(ident, handle->useCase, sizeof(ident));
195 ret = snd_use_case_get(handle->ucMgr, ident, (const char **)value);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700196 ALOGD("Device value returned is %s", (*value));
Iliyan Malchev4765c432012-06-11 14:36:16 -0700197 return ret;
198}
199
200status_t setHardwareParams(alsa_handle_t *handle)
201{
202 struct snd_pcm_hw_params *params;
203 unsigned long bufferSize, reqBuffSize;
204 unsigned int periodTime, bufferTime;
205 unsigned int requestedRate = handle->sampleRate;
206 int status = 0;
207 int channels = handle->channels;
208 snd_pcm_format_t format = SNDRV_PCM_FORMAT_S16_LE;
209
210 params = (snd_pcm_hw_params*) calloc(1, sizeof(struct snd_pcm_hw_params));
211 if (!params) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700212 ALOGE("Failed to allocate ALSA hardware parameters!");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700213 return NO_INIT;
214 }
215
216 reqBuffSize = handle->bufferSize;
Iliyan Malchev4113f342012-06-11 14:39:47 -0700217 ALOGD("setHardwareParams: reqBuffSize %d channels %d sampleRate %d",
Iliyan Malchev4765c432012-06-11 14:36:16 -0700218 (int) reqBuffSize, handle->channels, handle->sampleRate);
219
220#ifdef SSR_ENABLED
221 if (channels == 6) {
222 if (!strncmp(handle->useCase, SND_USE_CASE_VERB_HIFI_REC, strlen(SND_USE_CASE_VERB_HIFI_REC))
223 || !strncmp(handle->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, strlen(SND_USE_CASE_MOD_CAPTURE_MUSIC))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700224 ALOGV("HWParams: Use 4 channels in kernel for 5.1(%s) recording ", handle->useCase);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700225 channels = 4;
226 reqBuffSize = DEFAULT_IN_BUFFER_SIZE;
227 }
228 }
229#endif
230
231 param_init(params);
232 param_set_mask(params, SNDRV_PCM_HW_PARAM_ACCESS,
233 SNDRV_PCM_ACCESS_RW_INTERLEAVED);
234 if (handle->format != SNDRV_PCM_FORMAT_S16_LE) {
235 if (handle->format == AudioSystem::AMR_NB ||
236 handle->format == AudioSystem::AMR_WB ||
237 handle->format == AudioSystem::EVRC ||
238 handle->format == AudioSystem::EVRCB ||
239 handle->format == AudioSystem::EVRCWB)
240 format = SNDRV_PCM_FORMAT_SPECIAL;
241 }
242 param_set_mask(params, SNDRV_PCM_HW_PARAM_FORMAT,
243 format);
244 param_set_mask(params, SNDRV_PCM_HW_PARAM_SUBFORMAT,
245 SNDRV_PCM_SUBFORMAT_STD);
246 param_set_min(params, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, reqBuffSize);
247 param_set_int(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS, 16);
248 param_set_int(params, SNDRV_PCM_HW_PARAM_FRAME_BITS,
249 channels * 16);
250 param_set_int(params, SNDRV_PCM_HW_PARAM_CHANNELS,
251 channels);
252 param_set_int(params, SNDRV_PCM_HW_PARAM_RATE, handle->sampleRate);
253 param_set_hw_refine(handle->handle, params);
254
255 if (param_set_hw_params(handle->handle, params)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700256 ALOGE("cannot set hw params");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700257 return NO_INIT;
258 }
259 param_dump(params);
260
261 handle->handle->buffer_size = pcm_buffer_size(params);
262 handle->handle->period_size = pcm_period_size(params);
263 handle->handle->period_cnt = handle->handle->buffer_size/handle->handle->period_size;
Iliyan Malchev4113f342012-06-11 14:39:47 -0700264 ALOGD("setHardwareParams: buffer_size %d, period_size %d, period_cnt %d",
Iliyan Malchev4765c432012-06-11 14:36:16 -0700265 handle->handle->buffer_size, handle->handle->period_size,
266 handle->handle->period_cnt);
267 handle->handle->rate = handle->sampleRate;
268 handle->handle->channels = handle->channels;
269 handle->periodSize = handle->handle->period_size;
270 if (strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_REC) &&
271 strcmp(handle->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC) &&
272 (6 != handle->channels)) {
273 //Do not update buffersize for 5.1 recording
274 handle->bufferSize = handle->handle->period_size;
275 }
276
277 return NO_ERROR;
278}
279
280status_t setSoftwareParams(alsa_handle_t *handle)
281{
282 struct snd_pcm_sw_params* params;
283 struct pcm* pcm = handle->handle;
284
285 unsigned long periodSize = pcm->period_size;
286 int channels = handle->channels;
287
288 params = (snd_pcm_sw_params*) calloc(1, sizeof(struct snd_pcm_sw_params));
289 if (!params) {
290 LOG_ALWAYS_FATAL("Failed to allocate ALSA software parameters!");
291 return NO_INIT;
292 }
293
294#ifdef SSR_ENABLED
295 if (channels == 6) {
296 if (!strncmp(handle->useCase, SND_USE_CASE_VERB_HIFI_REC, strlen(SND_USE_CASE_VERB_HIFI_REC))
297 || !strncmp(handle->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, strlen(SND_USE_CASE_MOD_CAPTURE_MUSIC))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700298 ALOGV("SWParams: Use 4 channels in kernel for 5.1(%s) recording ", handle->useCase);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700299 channels = 4;
300 }
301 }
302#endif
303
304 // Get the current software parameters
305 params->tstamp_mode = SNDRV_PCM_TSTAMP_NONE;
306 params->period_step = 1;
307 if(((!strcmp(handle->useCase,SND_USE_CASE_MOD_PLAY_VOIP)) ||
308 (!strcmp(handle->useCase,SND_USE_CASE_VERB_IP_VOICECALL)))){
Iliyan Malchev4113f342012-06-11 14:39:47 -0700309 ALOGV("setparam: start & stop threshold for Voip ");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700310 params->avail_min = handle->channels - 1 ? periodSize/4 : periodSize/2;
311 params->start_threshold = periodSize/2;
312 params->stop_threshold = INT_MAX;
313 } else {
314 params->avail_min = periodSize/2;
315 params->start_threshold = channels * (periodSize/4);
316 params->stop_threshold = INT_MAX;
317 }
318 params->silence_threshold = 0;
319 params->silence_size = 0;
320
321 if (param_set_sw_params(handle->handle, params)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700322 ALOGE("cannot set sw params");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700323 return NO_INIT;
324 }
325 return NO_ERROR;
326}
327
328void switchDevice(alsa_handle_t *handle, uint32_t devices, uint32_t mode)
329{
330 const char **mods_list;
331 use_case_t useCaseNode;
332 unsigned usecase_type = 0;
333 bool inCallDevSwitch = false;
334 char *rxDevice, *txDevice, ident[70], *use_case = NULL;
335 int err = 0, index, mods_size;
336 int rx_dev_id, tx_dev_id;
Iliyan Malchev4113f342012-06-11 14:39:47 -0700337 ALOGV("%s: device %d", __FUNCTION__, devices);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700338
339 if ((mode == AudioSystem::MODE_IN_CALL) || (mode == AudioSystem::MODE_IN_COMMUNICATION)) {
340 if ((devices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) ||
341 (devices & AudioSystem::DEVICE_IN_WIRED_HEADSET)) {
342 devices = devices | (AudioSystem::DEVICE_OUT_WIRED_HEADSET |
343 AudioSystem::DEVICE_IN_WIRED_HEADSET);
344 } else if (devices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE) {
345 devices = devices | (AudioSystem::DEVICE_OUT_WIRED_HEADPHONE |
346 AudioSystem::DEVICE_IN_BUILTIN_MIC);
347 } else if ((devices & AudioSystem::DEVICE_OUT_EARPIECE) ||
348 (devices & AudioSystem::DEVICE_IN_BUILTIN_MIC)) {
349 devices = devices | (AudioSystem::DEVICE_IN_BUILTIN_MIC |
350 AudioSystem::DEVICE_OUT_EARPIECE);
351 } else if (devices & AudioSystem::DEVICE_OUT_SPEAKER) {
352 devices = devices | (AudioSystem::DEVICE_IN_BUILTIN_MIC |
353 AudioSystem::DEVICE_OUT_SPEAKER);
354 } else if ((devices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO) ||
355 (devices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET) ||
356 (devices & AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET)) {
357 devices = devices | (AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET |
358 AudioSystem::DEVICE_OUT_BLUETOOTH_SCO);
359#if 0
360 } else if ((devices & AudioSystem::DEVICE_OUT_ANC_HEADSET) ||
361 (devices & AudioSystem::DEVICE_IN_ANC_HEADSET)) {
362 devices = devices | (AudioSystem::DEVICE_OUT_ANC_HEADSET |
363 AudioSystem::DEVICE_IN_ANC_HEADSET);
364 } else if (devices & AudioSystem::DEVICE_OUT_ANC_HEADPHONE) {
365 devices = devices | (AudioSystem::DEVICE_OUT_ANC_HEADPHONE |
366 AudioSystem::DEVICE_IN_BUILTIN_MIC);
367#endif
368 } else if (devices & AudioSystem::DEVICE_OUT_AUX_DIGITAL) {
369 devices = devices | (AudioSystem::DEVICE_OUT_AUX_DIGITAL |
370 AudioSystem::DEVICE_IN_AUX_DIGITAL);
371#if 0
372 } else if ((devices & AudioSystem::DEVICE_OUT_PROXY) ||
373 (devices & AudioSystem::DEVICE_IN_PROXY)) {
374 devices = devices | (AudioSystem::DEVICE_OUT_PROXY |
375 AudioSystem::DEVICE_IN_PROXY);
376#endif
377 }
378 }
379#ifdef SSR_ENABLED
380 if ((devices & AudioSystem::DEVICE_IN_BUILTIN_MIC) && ( 6 == handle->channels)) {
381 if (!strncmp(handle->useCase, SND_USE_CASE_VERB_HIFI_REC, strlen(SND_USE_CASE_VERB_HIFI_REC))
382 || !strncmp(handle->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, strlen(SND_USE_CASE_MOD_CAPTURE_MUSIC))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700383 ALOGV(" switchDevice , use ssr devices for channels:%d usecase:%s",handle->channels,handle->useCase);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700384 s_set_flags(SSRQMIC_FLAG);
385 }
386 }
387#endif
388
389 rxDevice = getUCMDevice(devices & AudioSystem::DEVICE_OUT_ALL, 0, NULL);
390 txDevice = getUCMDevice(devices & AudioSystem::DEVICE_IN_ALL, 1, rxDevice);
391
392 if (rxDevice != NULL) {
393 if ((handle->handle) && (((!strncmp(rxDevice, DEVICE_SPEAKER_HEADSET, strlen(DEVICE_SPEAKER_HEADSET))) &&
394 ((!strncmp(curRxUCMDevice, DEVICE_HEADPHONES, strlen(DEVICE_HEADPHONES))) ||
395 (!strncmp(curRxUCMDevice, DEVICE_HEADSET, strlen(DEVICE_HEADSET))))) ||
396 (((!strncmp(curRxUCMDevice, DEVICE_SPEAKER_HEADSET, strlen(DEVICE_SPEAKER_HEADSET))) &&
397 ((!strncmp(rxDevice, DEVICE_HEADPHONES, strlen(DEVICE_HEADPHONES))) ||
398 (!strncmp(rxDevice, DEVICE_HEADSET, strlen(DEVICE_HEADSET))))))) &&
399 ((!strncmp(handle->useCase, SND_USE_CASE_VERB_HIFI, strlen(SND_USE_CASE_VERB_HIFI))) ||
400 (!strncmp(handle->useCase, SND_USE_CASE_MOD_PLAY_MUSIC, strlen(SND_USE_CASE_MOD_PLAY_MUSIC))))) {
401 pcm_close(handle->handle);
402 handle->handle=NULL;
403 handle->rxHandle=NULL;
404 pflag = true;
405 }
406 }
407
408 if ((rxDevice != NULL) && (txDevice != NULL)) {
409 if (((strncmp(rxDevice, curRxUCMDevice, MAX_STR_LEN)) ||
410 (strncmp(txDevice, curTxUCMDevice, MAX_STR_LEN))) && (mode == AudioSystem::MODE_IN_CALL))
411 inCallDevSwitch = true;
412 }
413 snd_use_case_get(handle->ucMgr, "_verb", (const char **)&use_case);
414 mods_size = snd_use_case_get_list(handle->ucMgr, "_enamods", &mods_list);
415 if (rxDevice != NULL) {
416 if ((strncmp(curRxUCMDevice, "None", 4)) &&
417 ((strncmp(rxDevice, curRxUCMDevice, MAX_STR_LEN)) || (inCallDevSwitch == true))) {
418 if ((use_case != NULL) && (strncmp(use_case, SND_USE_CASE_VERB_INACTIVE,
419 strlen(SND_USE_CASE_VERB_INACTIVE)))) {
420 usecase_type = getUseCaseType(use_case);
421 if (usecase_type & USECASE_TYPE_RX) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700422 ALOGD("Deroute use case %s type is %d\n", use_case, usecase_type);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700423 strlcpy(useCaseNode.useCase, use_case, MAX_STR_LEN);
424 snd_use_case_set(handle->ucMgr, "_verb", SND_USE_CASE_VERB_INACTIVE);
425 mUseCaseList.push_front(useCaseNode);
426 }
427 }
428 if (mods_size) {
429 for(index = 0; index < mods_size; index++) {
430 usecase_type = getUseCaseType(mods_list[index]);
431 if (usecase_type & USECASE_TYPE_RX) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700432 ALOGD("Deroute use case %s type is %d\n", mods_list[index], usecase_type);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700433 strlcpy(useCaseNode.useCase, mods_list[index], MAX_STR_LEN);
434 snd_use_case_set(handle->ucMgr, "_dismod", mods_list[index]);
435 mUseCaseList.push_back(useCaseNode);
436 }
437 }
438 }
439 snd_use_case_set(handle->ucMgr, "_disdev", curRxUCMDevice);
440 }
441 }
442 if (txDevice != NULL) {
443 if ((strncmp(curTxUCMDevice, "None", 4)) &&
444 ((strncmp(txDevice, curTxUCMDevice, MAX_STR_LEN)) || (inCallDevSwitch == true))) {
445 if ((use_case != NULL) && (strncmp(use_case, SND_USE_CASE_VERB_INACTIVE,
446 strlen(SND_USE_CASE_VERB_INACTIVE)))) {
447 usecase_type = getUseCaseType(use_case);
448 if ((usecase_type & USECASE_TYPE_TX) && (!(usecase_type & USECASE_TYPE_RX))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700449 ALOGD("Deroute use case %s type is %d\n", use_case, usecase_type);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700450 strlcpy(useCaseNode.useCase, use_case, MAX_STR_LEN);
451 snd_use_case_set(handle->ucMgr, "_verb", SND_USE_CASE_VERB_INACTIVE);
452 mUseCaseList.push_front(useCaseNode);
453 }
454 }
455 if (mods_size) {
456 for(index = 0; index < mods_size; index++) {
457 usecase_type = getUseCaseType(mods_list[index]);
458 if ((usecase_type & USECASE_TYPE_TX) && (!(usecase_type & USECASE_TYPE_RX))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700459 ALOGD("Deroute use case %s type is %d\n", mods_list[index], usecase_type);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700460 strlcpy(useCaseNode.useCase, mods_list[index], MAX_STR_LEN);
461 snd_use_case_set(handle->ucMgr, "_dismod", mods_list[index]);
462 mUseCaseList.push_back(useCaseNode);
463 }
464 }
465 }
466 snd_use_case_set(handle->ucMgr, "_disdev", curTxUCMDevice);
467 }
468 }
Iliyan Malchev4113f342012-06-11 14:39:47 -0700469 ALOGV("%s,rxDev:%s, txDev:%s, curRxDev:%s, curTxDev:%s\n", __FUNCTION__, rxDevice, txDevice, curRxUCMDevice, curTxUCMDevice);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700470#if 0
471 if (mode == AudioSystem::MODE_IN_CALL && platform_is_Fusion3() && (inCallDevSwitch == true)) {
472 err = csd_client_disable_device();
473 if (err < 0)
474 {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700475 ALOGE("csd_client_disable_device, failed, error %d", err);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700476 }
477 }
478#endif
479
480 if (rxDevice != NULL) {
481 snd_use_case_set(handle->ucMgr, "_enadev", rxDevice);
482 strlcpy(curRxUCMDevice, rxDevice, sizeof(curRxUCMDevice));
483#if 0
484 if (devices & AudioSystem::DEVICE_OUT_FM)
485 s_set_fm_vol(fmVolume);
486#endif
487 }
488 if (txDevice != NULL) {
489 snd_use_case_set(handle->ucMgr, "_enadev", txDevice);
490 strlcpy(curTxUCMDevice, txDevice, sizeof(curTxUCMDevice));
491 }
492 for(ALSAUseCaseList::iterator it = mUseCaseList.begin(); it != mUseCaseList.end(); ++it) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700493 ALOGD("Route use case %s\n", it->useCase);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700494 if ((use_case != NULL) && (strncmp(use_case, SND_USE_CASE_VERB_INACTIVE,
495 strlen(SND_USE_CASE_VERB_INACTIVE))) && (!strncmp(use_case, it->useCase, MAX_UC_LEN))) {
496 snd_use_case_set(handle->ucMgr, "_verb", it->useCase);
497 } else {
498 snd_use_case_set(handle->ucMgr, "_enamod", it->useCase);
499 }
500 }
501 if (!mUseCaseList.empty())
502 mUseCaseList.clear();
503 if (use_case != NULL) {
504 free(use_case);
505 use_case = NULL;
506 }
Iliyan Malchev4113f342012-06-11 14:39:47 -0700507 ALOGD("switchDevice: curTxUCMDevivce %s curRxDevDevice %s", curTxUCMDevice, curRxUCMDevice);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700508
509 if (mode == AudioSystem::MODE_IN_CALL && platform_is_Fusion3() && (inCallDevSwitch == true)) {
510 /* get tx acdb id */
511 memset(&ident,0,sizeof(ident));
512 strlcpy(ident, "ACDBID/", sizeof(ident));
513 strlcat(ident, curTxUCMDevice, sizeof(ident));
514 tx_dev_id = snd_use_case_get(handle->ucMgr, ident, NULL);
515
516 /* get rx acdb id */
517 memset(&ident,0,sizeof(ident));
518 strlcpy(ident, "ACDBID/", sizeof(ident));
519 strlcat(ident, curRxUCMDevice, sizeof(ident));
520 rx_dev_id = snd_use_case_get(handle->ucMgr, ident, NULL);
521
522 if (rx_dev_id == DEVICE_SPEAKER_RX_ACDB_ID && tx_dev_id == DEVICE_HANDSET_TX_ACDB_ID) {
523 tx_dev_id = DEVICE_SPEAKER_TX_ACDB_ID;
524 }
525
Iliyan Malchev4113f342012-06-11 14:39:47 -0700526#if 0
527 ALOGV("rx_dev_id=%d, tx_dev_id=%d\n", rx_dev_id, tx_dev_id);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700528 err = csd_client_enable_device(rx_dev_id, tx_dev_id, mDevSettingsFlag);
529 if (err < 0)
530 {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700531 ALOGE("csd_client_disable_device failed, error %d", err);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700532 }
Iliyan Malchev4113f342012-06-11 14:39:47 -0700533#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700534 }
535
536 if (rxDevice != NULL) {
537 if (pflag && (((!strncmp(rxDevice, DEVICE_SPEAKER_HEADSET, strlen(DEVICE_SPEAKER_HEADSET))) &&
538 ((!strncmp(curRxUCMDevice, DEVICE_HEADPHONES, strlen(DEVICE_HEADPHONES))) ||
539 (!strncmp(curRxUCMDevice, DEVICE_HEADSET, strlen(DEVICE_HEADSET))))) ||
540 (((!strncmp(curRxUCMDevice, DEVICE_SPEAKER_HEADSET, strlen(DEVICE_SPEAKER_HEADSET))) &&
541 ((!strncmp(rxDevice, DEVICE_HEADPHONES, strlen(DEVICE_HEADPHONES))) ||
542 (!strncmp(rxDevice, DEVICE_HEADSET, strlen(DEVICE_HEADSET))))))) &&
543 ((!strncmp(handle->useCase, SND_USE_CASE_VERB_HIFI, strlen(SND_USE_CASE_VERB_HIFI))) ||
544 (!strncmp(handle->useCase, SND_USE_CASE_MOD_PLAY_MUSIC, strlen(SND_USE_CASE_MOD_PLAY_MUSIC))))) {
545 s_open(handle);
546 pflag = false;
547 }
548 }
549
550 if (rxDevice != NULL) {
551 free(rxDevice);
552 rxDevice = NULL;
553 }
554 if (txDevice != NULL) {
555 free(txDevice);
556 txDevice = NULL;
557 }
558}
559
560// ----------------------------------------------------------------------------
561
562static status_t s_init(alsa_device_t *module, ALSAHandleList &list)
563{
Iliyan Malchev4113f342012-06-11 14:39:47 -0700564 ALOGD("s_init: Initializing devices for ALSA module");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700565
566 list.clear();
567
568 return NO_ERROR;
569}
570
571static status_t s_open(alsa_handle_t *handle)
572{
573 char *devName;
574 unsigned flags = 0;
575 int err = NO_ERROR;
576
577 /* No need to call s_close for LPA as pcm device open and close is handled by LPAPlayer in stagefright */
578 if((!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER)) || (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_LPA))
579 ||(!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_TUNNEL)) || (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_TUNNEL))) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700580 ALOGD("s_open: Opening LPA /Tunnel playback");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700581 return NO_ERROR;
582 }
583
584 s_close(handle);
585
Iliyan Malchev4113f342012-06-11 14:39:47 -0700586 ALOGD("s_open: handle %p", handle);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700587
588 // ASoC multicomponent requires a valid path (frontend/backend) for
589 // the device to be opened
590
591 // The PCM stream is opened in blocking mode, per ALSA defaults. The
592 // AudioFlinger seems to assume blocking mode too, so asynchronous mode
593 // should not be used.
594 if ((!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI)) ||
595 (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_MUSIC))) {
596 flags = PCM_OUT;
597 } else {
598 flags = PCM_IN;
599 }
600 if (handle->channels == 1) {
601 flags |= PCM_MONO;
602 }
603#ifdef SSR_ENABLED
604 else if (handle->channels == 4 ) {
605 flags |= PCM_QUAD;
606 } else if (handle->channels == 6 ) {
607 if (!strncmp(handle->useCase, SND_USE_CASE_VERB_HIFI_REC, strlen(SND_USE_CASE_VERB_HIFI_REC))
608 || !strncmp(handle->useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC, strlen(SND_USE_CASE_MOD_CAPTURE_MUSIC))) {
609 flags |= PCM_QUAD;
610 } else {
611 flags |= PCM_5POINT1;
612 }
613 }
614#endif
615 else {
616 flags |= PCM_STEREO;
617 }
618 if (deviceName(handle, flags, &devName) < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700619 ALOGE("Failed to get pcm device node: %s", devName);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700620 return NO_INIT;
621 }
622 if (devName != NULL) {
623 handle->handle = pcm_open(flags, (char*)devName);
624 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700625 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700626 return NO_INIT;
627 }
628
629 if (!handle->handle) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700630 ALOGE("s_open: Failed to initialize ALSA device '%s'", devName);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700631 free(devName);
632 return NO_INIT;
633 }
634
635 handle->handle->flags = flags;
636 err = setHardwareParams(handle);
637
638 if (err == NO_ERROR) {
639 err = setSoftwareParams(handle);
640 }
641
642 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700643 ALOGE("Set HW/SW params failed: Closing the pcm stream");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700644 s_standby(handle);
645 }
646
647 free(devName);
648 return NO_ERROR;
649}
650
651static status_t s_start_voip_call(alsa_handle_t *handle)
652{
653
654 char* devName;
655 char* devName1;
656 unsigned flags = 0;
657 int err = NO_ERROR;
658 uint8_t voc_pkt[VOIP_BUFFER_MAX_SIZE];
659
660 s_close(handle);
661 flags = PCM_OUT;
662 flags |= PCM_MONO;
Iliyan Malchev4113f342012-06-11 14:39:47 -0700663 ALOGV("s_open:s_start_voip_call handle %p", handle);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700664
665 if (deviceName(handle, flags, &devName) < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700666 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700667 return NO_INIT;
668 }
669
670 if (devName != NULL) {
671 handle->handle = pcm_open(flags, (char*)devName);
672 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700673 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700674 return NO_INIT;
675 }
676
677 if (!handle->handle) {
678 free(devName);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700679 ALOGE("s_open: Failed to initialize ALSA device '%s'", devName);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700680 return NO_INIT;
681 }
682
683 if (!pcm_ready(handle->handle)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700684 ALOGE(" pcm ready failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700685 }
686
687 handle->handle->flags = flags;
688 err = setHardwareParams(handle);
689
690 if (err == NO_ERROR) {
691 err = setSoftwareParams(handle);
692 }
693
694 err = pcm_prepare(handle->handle);
695 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700696 ALOGE("DEVICE_OUT_DIRECTOUTPUT: pcm_prepare failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700697 }
698
699 /* first write required start dsp */
700 memset(&voc_pkt,0,sizeof(voc_pkt));
701 pcm_write(handle->handle,&voc_pkt,handle->handle->period_size);
702 handle->rxHandle = handle->handle;
703 free(devName);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700704 ALOGV("s_open: DEVICE_IN_COMMUNICATION ");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700705 flags = PCM_IN;
706 flags |= PCM_MONO;
707 handle->handle = 0;
708
709 if (deviceName(handle, flags, &devName1) < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700710 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700711 return NO_INIT;
712 }
713 if (devName != NULL) {
714 handle->handle = pcm_open(flags, (char*)devName1);
715 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700716 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700717 return NO_INIT;
718 }
719
720 if (!handle->handle) {
721 free(devName);
Iliyan Malchev4113f342012-06-11 14:39:47 -0700722 ALOGE("s_open: Failed to initialize ALSA device '%s'", devName);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700723 return NO_INIT;
724 }
725
726 if (!pcm_ready(handle->handle)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700727 ALOGE(" pcm ready in failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700728 }
729
730 handle->handle->flags = flags;
731
732 err = setHardwareParams(handle);
733
734 if (err == NO_ERROR) {
735 err = setSoftwareParams(handle);
736 }
737
738
739 err = pcm_prepare(handle->handle);
740 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700741 ALOGE("DEVICE_IN_COMMUNICATION: pcm_prepare failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700742 }
743
744 /* first read required start dsp */
745 memset(&voc_pkt,0,sizeof(voc_pkt));
746 pcm_read(handle->handle,&voc_pkt,handle->handle->period_size);
747 return NO_ERROR;
748}
749
750static status_t s_start_voice_call(alsa_handle_t *handle)
751{
752 char* devName;
753 unsigned flags = 0;
754 int err = NO_ERROR;
755
Iliyan Malchev4113f342012-06-11 14:39:47 -0700756 ALOGD("s_start_voice_call: handle %p", handle);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700757 // ASoC multicomponent requires a valid path (frontend/backend) for
758 // the device to be opened
759
760 flags = PCM_OUT | PCM_MONO;
761 if (deviceName(handle, flags, &devName) < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700762 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700763 return NO_INIT;
764 }
765 if (devName != NULL) {
766 handle->handle = pcm_open(flags, (char*)devName);
767 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700768 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700769 return NO_INIT;
770 }
771 if (!handle->handle) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700772 ALOGE("s_start_voicecall: could not open PCM device");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700773 goto Error;
774 }
775
776 handle->handle->flags = flags;
777 err = setHardwareParams(handle);
778 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700779 ALOGE("s_start_voice_call: setHardwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700780 goto Error;
781 }
782
783 err = setSoftwareParams(handle);
784 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700785 ALOGE("s_start_voice_call: setSoftwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700786 goto Error;
787 }
788
789 err = pcm_prepare(handle->handle);
790 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700791 ALOGE("s_start_voice_call: pcm_prepare failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700792 goto Error;
793 }
794
795 if (ioctl(handle->handle->fd, SNDRV_PCM_IOCTL_START)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700796 ALOGE("s_start_voice_call:SNDRV_PCM_IOCTL_START failed\n");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700797 goto Error;
798 }
799
800 // Store the PCM playback device pointer in rxHandle
801 handle->rxHandle = handle->handle;
802 free(devName);
803
804 // Open PCM capture device
805 flags = PCM_IN | PCM_MONO;
806 if (deviceName(handle, flags, &devName) < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700807 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700808 goto Error;
809 }
810 if (devName != NULL) {
811 handle->handle = pcm_open(flags, (char*)devName);
812 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700813 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700814 return NO_INIT;
815 }
816 if (!handle->handle) {
817 free(devName);
818 goto Error;
819 }
820
821 handle->handle->flags = flags;
822 err = setHardwareParams(handle);
823 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700824 ALOGE("s_start_voice_call: setHardwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700825 goto Error;
826 }
827
828 err = setSoftwareParams(handle);
829 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700830 ALOGE("s_start_voice_call: setSoftwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700831 goto Error;
832 }
833
834 err = pcm_prepare(handle->handle);
835 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700836 ALOGE("s_start_voice_call: pcm_prepare failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700837 goto Error;
838 }
839
840 if (ioctl(handle->handle->fd, SNDRV_PCM_IOCTL_START)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700841 ALOGE("s_start_voice_call:SNDRV_PCM_IOCTL_START failed\n");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700842 goto Error;
843 }
844
845 if (platform_is_Fusion3()) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700846#if 0
Iliyan Malchev4765c432012-06-11 14:36:16 -0700847 err = csd_client_start_voice();
848 if (err < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700849 ALOGE("s_start_voice_call: csd_client error %d\n", err);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700850 goto Error;
851 }
Iliyan Malchev4113f342012-06-11 14:39:47 -0700852#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -0700853 }
854
855 free(devName);
856 return NO_ERROR;
857
858Error:
Iliyan Malchev4113f342012-06-11 14:39:47 -0700859 ALOGE("s_start_voice_call: Failed to initialize ALSA device '%s'", devName);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700860 free(devName);
861 s_close(handle);
862 return NO_INIT;
863}
864
865static status_t s_start_fm(alsa_handle_t *handle)
866{
867 char *devName;
868 unsigned flags = 0;
869 int err = NO_ERROR;
870
Iliyan Malchev4113f342012-06-11 14:39:47 -0700871 ALOGE("s_start_fm: handle %p", handle);
Iliyan Malchev4765c432012-06-11 14:36:16 -0700872
873 // ASoC multicomponent requires a valid path (frontend/backend) for
874 // the device to be opened
875
876 flags = PCM_OUT | PCM_STEREO;
877 if (deviceName(handle, flags, &devName) < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700878 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700879 goto Error;
880 }
881 if (devName != NULL) {
882 handle->handle = pcm_open(flags, (char*)devName);
883 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700884 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700885 return NO_INIT;
886 }
887 if (!handle->handle) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700888 ALOGE("s_start_fm: could not open PCM device");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700889 goto Error;
890 }
891
892 handle->handle->flags = flags;
893 err = setHardwareParams(handle);
894 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700895 ALOGE("s_start_fm: setHardwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700896 goto Error;
897 }
898
899 err = setSoftwareParams(handle);
900 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700901 ALOGE("s_start_fm: setSoftwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700902 goto Error;
903 }
904
905 err = pcm_prepare(handle->handle);
906 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700907 ALOGE("s_start_fm: setSoftwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700908 goto Error;
909 }
910
911 if (ioctl(handle->handle->fd, SNDRV_PCM_IOCTL_START)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700912 ALOGE("s_start_fm: SNDRV_PCM_IOCTL_START failed\n");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700913 goto Error;
914 }
915
916 // Store the PCM playback device pointer in rxHandle
917 handle->rxHandle = handle->handle;
918 free(devName);
919
920 // Open PCM capture device
921 flags = PCM_IN | PCM_STEREO;
922 if (deviceName(handle, flags, &devName) < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700923 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700924 goto Error;
925 }
926 if (devName != NULL) {
927 handle->handle = pcm_open(flags, (char*)devName);
928 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700929 ALOGE("Failed to get pcm device node");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700930 return NO_INIT;
931 }
932 if (!handle->handle) {
933 goto Error;
934 }
935
936 handle->handle->flags = flags;
937 err = setHardwareParams(handle);
938 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700939 ALOGE("s_start_fm: setHardwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700940 goto Error;
941 }
942
943 err = setSoftwareParams(handle);
944 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700945 ALOGE("s_start_fm: setSoftwareParams failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700946 goto Error;
947 }
948
949 err = pcm_prepare(handle->handle);
950 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700951 ALOGE("s_start_fm: pcm_prepare failed");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700952 goto Error;
953 }
954
955 if (ioctl(handle->handle->fd, SNDRV_PCM_IOCTL_START)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700956 ALOGE("s_start_fm: SNDRV_PCM_IOCTL_START failed\n");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700957 goto Error;
958 }
959
960 s_set_fm_vol(fmVolume);
961 free(devName);
962 return NO_ERROR;
963
964Error:
965 free(devName);
966 s_close(handle);
967 return NO_INIT;
968}
969
970static status_t s_set_fm_vol(int value)
971{
972 status_t err = NO_ERROR;
973
974 ALSAControl control("/dev/snd/controlC0");
975 control.set("Internal FM RX Volume",value,0);
976 fmVolume = value;
977
978 return err;
979}
980
981static status_t s_set_lpa_vol(int value)
982{
983 status_t err = NO_ERROR;
984
985 ALSAControl control("/dev/snd/controlC0");
986 control.set("LPA RX Volume",value,0);
987
988 return err;
989}
990
991static status_t s_start(alsa_handle_t *handle)
992{
993 status_t err = NO_ERROR;
994
995 if(!handle->handle) {
Iliyan Malchev4113f342012-06-11 14:39:47 -0700996 ALOGE("No active PCM driver to start");
Iliyan Malchev4765c432012-06-11 14:36:16 -0700997 return err;
998 }
999
1000 err = pcm_prepare(handle->handle);
1001
1002 return err;
1003}
1004
1005static status_t s_close(alsa_handle_t *handle)
1006{
1007 int ret;
1008 status_t err = NO_ERROR;
1009 struct pcm *h = handle->rxHandle;
1010
1011 handle->rxHandle = 0;
Iliyan Malchev4113f342012-06-11 14:39:47 -07001012 ALOGD("s_close: handle %p h %p", handle, h);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001013 if (h) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001014 ALOGV("s_close rxHandle\n");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001015 err = pcm_close(h);
1016 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001017 ALOGE("s_close: pcm_close failed for rxHandle with err %d", err);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001018 }
1019 }
1020
1021 h = handle->handle;
1022 handle->handle = 0;
1023
1024 if (h) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001025 ALOGV("s_close handle h %p\n", h);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001026 err = pcm_close(h);
1027 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001028 ALOGE("s_close: pcm_close failed for handle with err %d", err);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001029 }
1030
1031 if ((!strcmp(handle->useCase, SND_USE_CASE_VERB_VOICECALL) ||
1032 !strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_VOICE)) &&
1033 platform_is_Fusion3()) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001034#if 0
Iliyan Malchev4765c432012-06-11 14:36:16 -07001035 err = csd_client_stop_voice();
1036 if (err < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001037 ALOGE("s_close: csd_client error %d\n", err);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001038 }
Iliyan Malchev4113f342012-06-11 14:39:47 -07001039#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001040 }
1041
1042 disableDevice(handle);
1043 } else if((!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER)) ||
1044 (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_LPA)) ||
1045 (!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_TUNNEL)) ||
1046 (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_TUNNEL))){
1047 disableDevice(handle);
1048 }
1049
1050 return err;
1051}
1052
1053/*
1054 this is same as s_close, but don't discard
1055 the device/mode info. This way we can still
1056 close the device, hit idle and power-save, reopen the pcm
1057 for the same device/mode after resuming
1058*/
1059static status_t s_standby(alsa_handle_t *handle)
1060{
1061 int ret;
1062 status_t err = NO_ERROR;
1063 struct pcm *h = handle->rxHandle;
1064 handle->rxHandle = 0;
Iliyan Malchev4113f342012-06-11 14:39:47 -07001065 ALOGD("s_standby: handle %p h %p", handle, h);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001066 if (h) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001067 ALOGE("s_standby rxHandle\n");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001068 err = pcm_close(h);
1069 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001070 ALOGE("s_standby: pcm_close failed for rxHandle with err %d", err);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001071 }
1072 }
1073
1074 h = handle->handle;
1075 handle->handle = 0;
1076
1077 if (h) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001078 ALOGE("s_standby handle h %p\n", h);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001079 err = pcm_close(h);
1080 if(err != NO_ERROR) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001081 ALOGE("s_standby: pcm_close failed for handle with err %d", err);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001082 }
1083 disableDevice(handle);
1084 } else if((!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER)) ||
1085 (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_LPA)) ||
1086 (!strcmp(handle->useCase, SND_USE_CASE_VERB_HIFI_TUNNEL)) ||
1087 (!strcmp(handle->useCase, SND_USE_CASE_MOD_PLAY_TUNNEL))) {
1088 disableDevice(handle);
1089 }
1090
1091 return err;
1092}
1093
1094static status_t s_route(alsa_handle_t *handle, uint32_t devices, int mode)
1095{
1096 status_t status = NO_ERROR;
1097
Iliyan Malchev4113f342012-06-11 14:39:47 -07001098 ALOGD("s_route: devices 0x%x in mode %d", devices, mode);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001099 callMode = mode;
1100 switchDevice(handle, devices, mode);
1101 return status;
1102}
1103
1104int getUseCaseType(const char *useCase)
1105{
Iliyan Malchev4113f342012-06-11 14:39:47 -07001106 ALOGE("use case is %s\n", useCase);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001107 if (!strncmp(useCase, SND_USE_CASE_VERB_HIFI,
1108 strlen(SND_USE_CASE_VERB_HIFI)) ||
1109 !strncmp(useCase, SND_USE_CASE_VERB_HIFI_LOW_POWER,
1110 strlen(SND_USE_CASE_VERB_HIFI_LOW_POWER)) ||
1111 !strncmp(useCase, SND_USE_CASE_VERB_HIFI_TUNNEL,
1112 strlen(SND_USE_CASE_VERB_HIFI_TUNNEL)) ||
1113 !strncmp(useCase, SND_USE_CASE_VERB_DIGITAL_RADIO,
1114 strlen(SND_USE_CASE_VERB_DIGITAL_RADIO)) ||
1115 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_MUSIC,
1116 strlen(SND_USE_CASE_MOD_PLAY_MUSIC)) ||
1117 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_LPA,
1118 strlen(SND_USE_CASE_MOD_PLAY_LPA)) ||
1119 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_TUNNEL,
1120 strlen(SND_USE_CASE_MOD_PLAY_TUNNEL)) ||
1121 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_FM,
1122 strlen(SND_USE_CASE_MOD_PLAY_FM))) {
1123 return USECASE_TYPE_RX;
1124 } else if (!strncmp(useCase, SND_USE_CASE_VERB_HIFI_REC,
1125 strlen(SND_USE_CASE_VERB_HIFI_REC)) ||
1126 !strncmp(useCase, SND_USE_CASE_VERB_FM_REC,
1127 strlen(SND_USE_CASE_VERB_FM_REC)) ||
1128 !strncmp(useCase, SND_USE_CASE_VERB_FM_A2DP_REC,
1129 strlen(SND_USE_CASE_VERB_FM_A2DP_REC)) ||
1130 !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_MUSIC,
1131 strlen(SND_USE_CASE_MOD_CAPTURE_MUSIC)) ||
1132 !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_FM,
1133 strlen(SND_USE_CASE_MOD_CAPTURE_FM)) ||
1134 !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_A2DP_FM,
1135 strlen(SND_USE_CASE_MOD_CAPTURE_A2DP_FM))) {
1136 return USECASE_TYPE_TX;
1137 } else if (!strncmp(useCase, SND_USE_CASE_VERB_VOICECALL,
1138 strlen(SND_USE_CASE_VERB_VOICECALL)) ||
1139 !strncmp(useCase, SND_USE_CASE_VERB_IP_VOICECALL,
1140 strlen(SND_USE_CASE_VERB_IP_VOICECALL)) ||
1141 !strncmp(useCase, SND_USE_CASE_VERB_DL_REC,
1142 strlen(SND_USE_CASE_VERB_DL_REC)) ||
1143 !strncmp(useCase, SND_USE_CASE_VERB_UL_DL_REC,
1144 strlen(SND_USE_CASE_VERB_UL_DL_REC)) ||
1145 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_VOICE,
1146 strlen(SND_USE_CASE_MOD_PLAY_VOICE)) ||
1147 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_VOIP,
1148 strlen(SND_USE_CASE_MOD_PLAY_VOIP)) ||
1149 !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_VOICE_DL,
1150 strlen(SND_USE_CASE_MOD_CAPTURE_VOICE_DL)) ||
1151 !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_VOICE_UL_DL,
1152 strlen(SND_USE_CASE_MOD_CAPTURE_VOICE_UL_DL)) ||
1153 !strncmp(useCase, SND_USE_CASE_MOD_CAPTURE_VOICE,
1154 strlen(SND_USE_CASE_MOD_CAPTURE_VOICE)) ||
1155 !strncmp(useCase, SND_USE_CASE_VERB_VOLTE,
1156 strlen(SND_USE_CASE_VERB_VOLTE)) ||
1157 !strncmp(useCase, SND_USE_CASE_MOD_PLAY_VOLTE,
1158 strlen(SND_USE_CASE_MOD_PLAY_VOLTE))) {
1159 return (USECASE_TYPE_RX | USECASE_TYPE_TX);
1160 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001161 ALOGE("unknown use case %s\n", useCase);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001162 return 0;
1163 }
1164}
1165
1166static void disableDevice(alsa_handle_t *handle)
1167{
1168 unsigned usecase_type = 0;
1169 int i, mods_size;
1170 char *useCase;
1171 const char **mods_list;
1172
1173 snd_use_case_get(handle->ucMgr, "_verb", (const char **)&useCase);
1174 if (useCase != NULL) {
1175 if (!strncmp(useCase, handle->useCase, MAX_UC_LEN)) {
1176 snd_use_case_set(handle->ucMgr, "_verb", SND_USE_CASE_VERB_INACTIVE);
1177 } else {
1178 snd_use_case_set(handle->ucMgr, "_dismod", handle->useCase);
1179 }
1180 free(useCase);
1181 snd_use_case_get(handle->ucMgr, "_verb", (const char **)&useCase);
1182 if (strncmp(useCase, SND_USE_CASE_VERB_INACTIVE,
1183 strlen(SND_USE_CASE_VERB_INACTIVE)))
1184 usecase_type |= getUseCaseType(useCase);
1185 mods_size = snd_use_case_get_list(handle->ucMgr, "_enamods", &mods_list);
Iliyan Malchev4113f342012-06-11 14:39:47 -07001186 ALOGE("Number of modifiers %d\n", mods_size);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001187 if (mods_size) {
1188 for(i = 0; i < mods_size; i++) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001189 ALOGE("index %d modifier %s\n", i, mods_list[i]);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001190 usecase_type |= getUseCaseType(mods_list[i]);
1191 }
1192 }
Iliyan Malchev4113f342012-06-11 14:39:47 -07001193 ALOGE("usecase_type is %d\n", usecase_type);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001194 if (!(usecase_type & USECASE_TYPE_TX) && (strncmp(curTxUCMDevice, "None", 4)))
1195 snd_use_case_set(handle->ucMgr, "_disdev", curTxUCMDevice);
1196 if (!(usecase_type & USECASE_TYPE_RX) && (strncmp(curRxUCMDevice, "None", 4)))
1197 snd_use_case_set(handle->ucMgr, "_disdev", curRxUCMDevice);
1198 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001199 ALOGE("Invalid state, no valid use case found to disable");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001200 }
1201 free(useCase);
1202}
1203
1204char *getUCMDevice(uint32_t devices, int input, char *rxDevice)
1205{
1206 if (!input) {
1207 if (!(mDevSettingsFlag & TTY_OFF) &&
1208 (callMode == AudioSystem::MODE_IN_CALL) &&
1209 ((devices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) ||
1210 (devices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE))) {
1211#if 0
1212 ||
1213 (devices & AudioSystem::DEVICE_OUT_ANC_HEADSET) ||
1214 (devices & AudioSystem::DEVICE_OUT_ANC_HEADPHONE))) {
1215#endif
1216 if (mDevSettingsFlag & TTY_VCO) {
1217 return strdup(SND_USE_CASE_DEV_TTY_HEADSET_RX);
1218 } else if (mDevSettingsFlag & TTY_FULL) {
1219 return strdup(SND_USE_CASE_DEV_TTY_FULL_RX);
1220 } else if (mDevSettingsFlag & TTY_HCO) {
1221 return strdup(SND_USE_CASE_DEV_TTY_HANDSET_RX); /* HANDSET RX */
1222 }
1223 }else if ((devices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET) ||
1224 (devices & AudioSystem::DEVICE_OUT_DGTL_DOCK_HEADSET)) {
1225 return strdup(SND_USE_CASE_DEV_PROXY_RX); /* PROXY RX */
1226 } else if ((devices & AudioSystem::DEVICE_OUT_SPEAKER) &&
1227 ((devices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) ||
1228 (devices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE))) {
1229 if (mDevSettingsFlag & ANC_FLAG) {
1230 return strdup(SND_USE_CASE_DEV_SPEAKER_ANC_HEADSET); /* COMBO SPEAKER+ANC HEADSET RX */
1231 } else {
1232 return strdup(SND_USE_CASE_DEV_SPEAKER_HEADSET); /* COMBO SPEAKER+HEADSET RX */
1233 }
1234#if 0
1235 } else if ((devices & AudioSystem::DEVICE_OUT_SPEAKER) &&
1236 ((devices & AudioSystem::DEVICE_OUT_ANC_HEADSET) ||
1237 (devices & AudioSystem::DEVICE_OUT_ANC_HEADPHONE))) {
1238 return strdup(SND_USE_CASE_DEV_SPEAKER_ANC_HEADSET); /* COMBO SPEAKER+ANC HEADSET RX */
1239 } else if ((devices & AudioSystem::DEVICE_OUT_SPEAKER) &&
1240 (devices & AudioSystem::DEVICE_OUT_FM_TX)) {
1241 return strdup(SND_USE_CASE_DEV_SPEAKER_FM_TX); /* COMBO SPEAKER+FM_TX RX */
1242#endif
1243 } else if (devices & AudioSystem::DEVICE_OUT_EARPIECE) {
1244 return strdup(SND_USE_CASE_DEV_EARPIECE); /* HANDSET RX */
1245 } else if (devices & AudioSystem::DEVICE_OUT_SPEAKER) {
1246 return strdup(SND_USE_CASE_DEV_SPEAKER); /* SPEAKER RX */
1247 } else if ((devices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) ||
1248 (devices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE)) {
1249 if (mDevSettingsFlag & ANC_FLAG) {
1250 return strdup(SND_USE_CASE_DEV_ANC_HEADSET); /* ANC HEADSET RX */
1251 } else {
1252 return strdup(SND_USE_CASE_DEV_HEADPHONES); /* HEADSET RX */
1253 }
1254#if 0
1255 } else if ((devices & AudioSystem::DEVICE_OUT_ANC_HEADSET) ||
1256 (devices & AudioSystem::DEVICE_OUT_ANC_HEADPHONE)) {
1257 return strdup(SND_USE_CASE_DEV_ANC_HEADSET); /* ANC HEADSET RX */
1258#endif
1259 } else if ((devices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO) ||
1260 (devices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET) ||
1261 (devices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT)) {
1262 if (btsco_samplerate == BTSCO_RATE_16KHZ)
1263 return strdup(SND_USE_CASE_DEV_BTSCO_WB_RX); /* BTSCO RX*/
1264 else
1265 return strdup(SND_USE_CASE_DEV_BTSCO_NB_RX); /* BTSCO RX*/
1266 } else if ((devices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP) ||
1267 (devices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_HEADPHONES) ||
1268//commented JB
1269/* (devices & AudioSystem::DEVICE_OUT_DIRECTOUTPUT) ||*/
1270 (devices & AudioSystem::DEVICE_OUT_BLUETOOTH_A2DP_SPEAKER)) {
1271 /* Nothing to be done, use current active device */
1272 if (strncmp(curRxUCMDevice, "None", 4)) {
1273 return strdup(curRxUCMDevice);
1274 }
1275 } else if (devices & AudioSystem::DEVICE_OUT_AUX_DIGITAL) {
1276 return strdup(SND_USE_CASE_DEV_HDMI); /* HDMI RX */
1277#if 0
1278 } else if (devices & AudioSystem::DEVICE_OUT_PROXY) {
1279 return strdup(SND_USE_CASE_DEV_PROXY_RX); /* PROXY RX */
1280 } else if (devices & AudioSystem::DEVICE_OUT_FM_TX) {
1281 return strdup(SND_USE_CASE_DEV_FM_TX); /* FM Tx */
1282#endif
1283 } else if (devices & AudioSystem::DEVICE_OUT_DEFAULT) {
1284 return strdup(SND_USE_CASE_DEV_SPEAKER); /* SPEAKER RX */
1285 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001286 ALOGD("No valid output device: %u", devices);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001287 }
1288 } else {
1289 if (!(mDevSettingsFlag & TTY_OFF) &&
1290 (callMode == AudioSystem::MODE_IN_CALL) &&
1291 ((devices & AudioSystem::DEVICE_IN_WIRED_HEADSET))) {
1292#if 0
1293 ||(devices & AudioSystem::DEVICE_IN_ANC_HEADSET))) {
1294#endif
1295 if (mDevSettingsFlag & TTY_HCO) {
1296 return strdup(SND_USE_CASE_DEV_TTY_HEADSET_TX);
1297 } else if (mDevSettingsFlag & TTY_FULL) {
1298 return strdup(SND_USE_CASE_DEV_TTY_FULL_TX);
1299 } else if (mDevSettingsFlag & TTY_VCO) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001300#if 0
Iliyan Malchev4765c432012-06-11 14:36:16 -07001301 if (!strncmp(mic_type, "analog", 6)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001302 return strdup(SND_USE_CASE_DEV_TTY_HANDSET_ANAALOG_TX);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001303 } else {
1304 return strdup(SND_USE_CASE_DEV_TTY_HANDSET_TX);
1305 }
Iliyan Malchev4113f342012-06-11 14:39:47 -07001306#else
1307 return strdup(SND_USE_CASE_DEV_TTY_HANDSET_TX);
1308#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001309 }
1310 } else if (devices & AudioSystem::DEVICE_IN_BUILTIN_MIC) {
1311 if (!strncmp(mic_type, "analog", 6)) {
1312 return strdup(SND_USE_CASE_DEV_HANDSET); /* HANDSET TX */
1313 } else {
1314 if (mDevSettingsFlag & DMIC_FLAG) {
1315 if (((rxDevice != NULL) &&
1316 !strncmp(rxDevice, SND_USE_CASE_DEV_SPEAKER,
1317 (strlen(SND_USE_CASE_DEV_SPEAKER)+1))) ||
1318 !strncmp(curRxUCMDevice, SND_USE_CASE_DEV_SPEAKER,
1319 (strlen(SND_USE_CASE_DEV_SPEAKER)+1))) {
1320 if (fluence_mode == FLUENCE_MODE_ENDFIRE) {
1321 return strdup(SND_USE_CASE_DEV_SPEAKER_DUAL_MIC_ENDFIRE); /* DUALMIC EF TX */
1322 } else if (fluence_mode == FLUENCE_MODE_BROADSIDE) {
1323 return strdup(SND_USE_CASE_DEV_SPEAKER_DUAL_MIC_BROADSIDE); /* DUALMIC BS TX */
1324 }
1325 } else {
1326 if (fluence_mode == FLUENCE_MODE_ENDFIRE) {
1327 return strdup(SND_USE_CASE_DEV_DUAL_MIC_ENDFIRE); /* DUALMIC EF TX */
1328 } else if (fluence_mode == FLUENCE_MODE_BROADSIDE) {
1329 return strdup(SND_USE_CASE_DEV_DUAL_MIC_BROADSIDE); /* DUALMIC BS TX */
1330 }
1331 }
1332 } else if (mDevSettingsFlag & QMIC_FLAG){
1333 return strdup(SND_USE_CASE_DEV_QUAD_MIC);
1334 }
1335#ifdef SSR_ENABLED
1336 else if (mDevSettingsFlag & SSRQMIC_FLAG){
Iliyan Malchev4113f342012-06-11 14:39:47 -07001337 ALOGV("return SSRQMIC_FLAG: 0x%x devices:0x%x",mDevSettingsFlag,devices);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001338 // Mapping for quad mic input device.
1339 return strdup(SND_USE_CASE_DEV_SSR_QUAD_MIC); /* SSR Quad MIC */
1340 }
1341#endif
1342 else {
1343 return strdup(SND_USE_CASE_DEV_LINE); /* BUILTIN-MIC TX */
1344 }
1345 }
1346 } else if (devices & AudioSystem::DEVICE_IN_AUX_DIGITAL) {
1347 return strdup(SND_USE_CASE_DEV_HDMI_TX); /* HDMI TX */
1348#if 0
1349 } else if ((devices & AudioSystem::DEVICE_IN_WIRED_HEADSET) ||
1350 (devices & AudioSystem::DEVICE_IN_ANC_HEADSET)) {
1351 return strdup(SND_USE_CASE_DEV_HEADSET); /* HEADSET TX */
1352#endif
1353 } else if (devices & AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
1354 if (btsco_samplerate == BTSCO_RATE_16KHZ)
1355 return strdup(SND_USE_CASE_DEV_BTSCO_WB_TX); /* BTSCO TX*/
1356 else
1357 return strdup(SND_USE_CASE_DEV_BTSCO_NB_TX); /* BTSCO TX*/
1358#if 0
1359 } else if ((devices & AudioSystem::DEVICE_IN_ANLG_DOCK_HEADSET) ||
1360 (devices & AudioSystem::DEVICE_IN_PROXY)) {
1361 return strdup(SND_USE_CASE_DEV_PROXY_TX); /* PROXY TX */
1362#endif
1363 } else if ((devices & AudioSystem::DEVICE_IN_COMMUNICATION) ||
1364 (devices & AudioSystem::DEVICE_IN_VOICE_CALL)) {
1365 /* Nothing to be done, use current active device */
1366 if (strncmp(curTxUCMDevice, "None", 4)) {
1367 return strdup(curTxUCMDevice);
1368 }
1369#if 0
1370 } else if ((devices & AudioSystem::DEVICE_IN_FM_RX) ||
1371 (devices & AudioSystem::DEVICE_IN_FM_RX_A2DP)) {
1372 /* Nothing to be done, use current tx device or set dummy device */
1373 if (strncmp(curTxUCMDevice, "None", 4)) {
1374 return strdup(curTxUCMDevice);
1375 } else {
1376 return strdup(SND_USE_CASE_DEV_DUMMY_TX);
1377 }
1378#endif
1379 } else if ((devices & AudioSystem::DEVICE_IN_AMBIENT) ||
1380 (devices & AudioSystem::DEVICE_IN_BACK_MIC)) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001381 ALOGI("No proper mapping found with UCM device list, setting default");
Iliyan Malchev4765c432012-06-11 14:36:16 -07001382 if (!strncmp(mic_type, "analog", 6)) {
1383 return strdup(SND_USE_CASE_DEV_HANDSET); /* HANDSET TX */
1384 } else {
1385 return strdup(SND_USE_CASE_DEV_LINE); /* BUILTIN-MIC TX */
1386 }
1387 } else {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001388 ALOGD("No valid input device: %u", devices);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001389 }
1390 }
1391 return NULL;
1392}
1393
1394void s_set_voice_volume(int vol)
1395{
1396 int err = 0;
Iliyan Malchev4113f342012-06-11 14:39:47 -07001397 ALOGD("s_set_voice_volume: volume %d", vol);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001398 ALSAControl control("/dev/snd/controlC0");
1399 control.set("Voice Rx Volume", vol, 0);
1400
1401 if (platform_is_Fusion3()) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001402#if 0
Iliyan Malchev4765c432012-06-11 14:36:16 -07001403 err = csd_client_volume(vol);
1404 if (err < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001405 ALOGE("s_set_voice_volume: csd_client error %d", err);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001406 }
Iliyan Malchev4113f342012-06-11 14:39:47 -07001407#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001408 }
1409}
1410
1411void s_set_volte_volume(int vol)
1412{
Iliyan Malchev4113f342012-06-11 14:39:47 -07001413 ALOGD("s_set_volte_volume: volume %d", vol);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001414 ALSAControl control("/dev/snd/controlC0");
1415 control.set("VoLTE Rx Volume", vol, 0);
1416}
1417
1418
1419void s_set_voip_volume(int vol)
1420{
Iliyan Malchev4113f342012-06-11 14:39:47 -07001421 ALOGD("s_set_voip_volume: volume %d", vol);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001422 ALSAControl control("/dev/snd/controlC0");
1423 control.set("Voip Rx Volume", vol, 0);
1424}
1425void s_set_mic_mute(int state)
1426{
1427 int err = 0;
Iliyan Malchev4113f342012-06-11 14:39:47 -07001428 ALOGD("s_set_mic_mute: state %d", state);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001429 ALSAControl control("/dev/snd/controlC0");
1430 control.set("Voice Tx Mute", state, 0);
1431
1432 if (platform_is_Fusion3()) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001433#if 0
Iliyan Malchev4765c432012-06-11 14:36:16 -07001434 err = csd_client_mic_mute(state);
1435 if (err < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001436 ALOGE("s_set_mic_mute: csd_client error %d", err);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001437 }
Iliyan Malchev4113f342012-06-11 14:39:47 -07001438#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001439 }
1440}
1441void s_set_volte_mic_mute(int state)
1442{
Iliyan Malchev4113f342012-06-11 14:39:47 -07001443 ALOGD("s_set_volte_mic_mute: state %d", state);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001444 ALSAControl control("/dev/snd/controlC0");
1445 control.set("VoLTE Tx Mute", state, 0);
1446}
1447
1448void s_set_voip_mic_mute(int state)
1449{
Iliyan Malchev4113f342012-06-11 14:39:47 -07001450 ALOGD("s_set_voip_mic_mute: state %d", state);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001451 ALSAControl control("/dev/snd/controlC0");
1452 control.set("Voip Tx Mute", state, 0);
1453}
1454
1455void s_set_voip_config(int mode, int rate)
1456{
Iliyan Malchev4113f342012-06-11 14:39:47 -07001457 ALOGD("s_set_voip_config: mode %d,rate %d", mode, rate);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001458 ALSAControl control("/dev/snd/controlC0");
1459 char** setValues;
1460 setValues = (char**)malloc(2*sizeof(char*));
1461 if (setValues == NULL) {
1462 return;
1463 }
1464 setValues[0] = (char*)malloc(4*sizeof(char));
1465 if (setValues[0] == NULL) {
1466 free(setValues);
1467 return;
1468 }
1469
1470 setValues[1] = (char*)malloc(8*sizeof(char));
1471 if (setValues[1] == NULL) {
1472 free(setValues);
1473 free(setValues[0]);
1474 return;
1475 }
1476
1477 sprintf(setValues[0], "%d",mode);
1478 sprintf(setValues[1], "%d",rate);
1479
1480 control.setext("Voip Mode Rate Config", 2, setValues);
1481 free(setValues[1]);
1482 free(setValues[0]);
1483 free(setValues);
1484 return;
1485}
1486
1487void s_set_btsco_rate(int rate)
1488{
1489 btsco_samplerate = rate;
1490}
1491
1492void s_enable_wide_voice(bool flag)
1493{
1494 int err = 0;
1495
Iliyan Malchev4113f342012-06-11 14:39:47 -07001496 ALOGD("s_enable_wide_voice: flag %d", flag);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001497 ALSAControl control("/dev/snd/controlC0");
1498 if(flag == true) {
1499 control.set("Widevoice Enable", 1, 0);
1500 } else {
1501 control.set("Widevoice Enable", 0, 0);
1502 }
1503
1504 if (platform_is_Fusion3()) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001505#if 0
Iliyan Malchev4765c432012-06-11 14:36:16 -07001506 err == csd_client_wide_voice(flag);
1507 if (err < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001508 ALOGE("s_enable_wide_voice: csd_client error %d", err);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001509 }
Iliyan Malchev4113f342012-06-11 14:39:47 -07001510#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001511 }
1512}
1513
1514void s_set_voc_rec_mode(uint8_t mode)
1515{
Iliyan Malchev4113f342012-06-11 14:39:47 -07001516 ALOGD("s_set_voc_rec_mode: mode %d", mode);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001517 ALSAControl control("/dev/snd/controlC0");
1518 control.set("Incall Rec Mode", mode, 0);
1519}
1520
1521void s_enable_fens(bool flag)
1522{
1523 int err = 0;
1524
Iliyan Malchev4113f342012-06-11 14:39:47 -07001525 ALOGD("s_enable_fens: flag %d", flag);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001526 ALSAControl control("/dev/snd/controlC0");
1527 if(flag == true) {
1528 control.set("FENS Enable", 1, 0);
1529 } else {
1530 control.set("FENS Enable", 0, 0);
1531 }
1532
1533 if (platform_is_Fusion3()) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001534#if 0
Iliyan Malchev4765c432012-06-11 14:36:16 -07001535 err = csd_client_fens(flag);
1536 if (err < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001537 ALOGE("s_enable_fens: csd_client error %d", err);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001538 }
Iliyan Malchev4113f342012-06-11 14:39:47 -07001539#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001540 }
1541}
1542
1543void s_enable_slow_talk(bool flag)
1544{
1545 int err = 0;
1546
Iliyan Malchev4113f342012-06-11 14:39:47 -07001547 ALOGD("s_enable_slow_talk: flag %d", flag);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001548 ALSAControl control("/dev/snd/controlC0");
1549 if(flag == true) {
1550 control.set("Slowtalk Enable", 1, 0);
1551 } else {
1552 control.set("Slowtalk Enable", 0, 0);
1553 }
1554
1555 if (platform_is_Fusion3()) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001556#if 0
Iliyan Malchev4765c432012-06-11 14:36:16 -07001557 err = csd_client_slow_talk(flag);
1558 if (err < 0) {
Iliyan Malchev4113f342012-06-11 14:39:47 -07001559 ALOGE("s_enable_slow_talk: csd_client error %d", err);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001560 }
Iliyan Malchev4113f342012-06-11 14:39:47 -07001561#endif
Iliyan Malchev4765c432012-06-11 14:36:16 -07001562 }
1563}
1564
1565void s_set_flags(uint32_t flags)
1566{
Iliyan Malchev4113f342012-06-11 14:39:47 -07001567 ALOGV("s_set_flags: flags %d", flags);
Iliyan Malchev4765c432012-06-11 14:36:16 -07001568 mDevSettingsFlag = flags;
1569}
1570
1571static status_t s_set_compressed_vol(int value)
1572{
1573 status_t err = NO_ERROR;
1574
1575 ALSAControl control("/dev/snd/controlC0");
1576 control.set("COMPRESSED RX Volume",value,0);
1577
1578 return err;
1579}
1580
1581}