blob: 2b4d522debe14c9f4d6358bfc159ae4cbe7efa93 [file] [log] [blame]
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001/*
2** Copyright 2008, The Android Open-Source Project
3** Copyright (c) 2010-2013, The Linux Foundation. All rights reserved.
Giulio Cervera548b3192013-04-20 07:44:26 +02004** Copyright (c) 2011-2013, The CyanogenMod Project
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00005** Not a Contribution, Apache license notifications and license are retained
6** for attribution purposes only.
7**
8** Licensed under the Apache License, Version 2.0 (the "License");
9** you may not use this file except in compliance with the License.
10** You may obtain a copy of the License at
11**
12** http://www.apache.org/licenses/LICENSE-2.0
13**
14** Unless required by applicable law or agreed to in writing, software
15** distributed under the License is distributed on an "AS IS" BASIS,
16** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17** See the License for the specific language governing permissions and
18** limitations under the License.
19*/
20
21#include <math.h>
22
23#define LOG_TAG "AudioHardware7x30"
24//#define LOG_NDDEBUG 0
25#include <utils/Log.h>
26#include <utils/String8.h>
27#include <stdio.h>
28#include <unistd.h>
29#include <sys/ioctl.h>
30#include <sys/types.h>
31#include <sys/stat.h>
32#include <dlfcn.h>
33#include <fcntl.h>
Giulio Cervera548b3192013-04-20 07:44:26 +020034#include <cutils/properties.h>
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +000035#include <media/AudioSystem.h>
36
37#include "control.h"
38extern "C" {
39#include "initialize_audcal7x30.h"
Michael Bestas14030ec2013-05-14 20:00:20 +030040#ifdef HTC_AUDIO
Giulio Cervera548b3192013-04-20 07:44:26 +020041#include <linux/spi_aic3254.h>
42#include <linux/tpa2051d3.h>
Michael Bestas14030ec2013-05-14 20:00:20 +030043#endif
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +000044}
45// hardware specific functions
46
47#include "AudioHardware.h"
48//#include <media/AudioSystem.h>
49//#include <media/AudioRecord.h>
Arne Coucheron0c85f772013-04-23 12:18:53 +020050#ifdef WITH_QCOM_VOIP_OVER_MVS
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +000051#include <linux/msm_audio_mvs.h>
Arne Coucheron0c85f772013-04-23 12:18:53 +020052#endif
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +000053
54#define LOG_SND_RPC 0 // Set to 1 to log sound RPC's
55
56#define ECHO_SUPRESSION "ec_supported"
57
58#define DUALMIC_KEY "dualmic_enabled"
59#define TTY_MODE_KEY "tty_mode"
60#define BTHEADSET_VGS "bt_headset_vgs"
Michael Bestas14030ec2013-05-14 20:00:20 +030061#ifdef HTC_AUDIO
Giulio Cervera548b3192013-04-20 07:44:26 +020062#define DSP_EFFECT_KEY "dolby_srs_eq"
Michael Bestas14030ec2013-05-14 20:00:20 +030063#endif
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +000064#define AMRNB_DEVICE_IN "/dev/msm_amrnb_in"
65#define EVRC_DEVICE_IN "/dev/msm_evrc_in"
66#define QCELP_DEVICE_IN "/dev/msm_qcelp_in"
67#define AAC_DEVICE_IN "/dev/msm_aac_in"
Arne Coucheron0c85f772013-04-23 12:18:53 +020068#ifdef QCOM_FM_ENABLED
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +000069#define FM_DEVICE "/dev/msm_fm"
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +000070#define FM_A2DP_REC 1
71#define FM_FILE_REC 2
Arne Coucheron0c85f772013-04-23 12:18:53 +020072#endif
73
74#define MVS_DEVICE "/dev/msm_mvs"
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +000075
76#define AMRNB_FRAME_SIZE 32
77#define EVRC_FRAME_SIZE 23
78#define QCELP_FRAME_SIZE 35
79
80
81
82namespace android_audio_legacy {
83//using android_audio_legacy::AudioSystem;
84//using android_audio_legacy::AudioHardwareInterface;
85
86Mutex mDeviceSwitchLock;
Michael Bestas14030ec2013-05-14 20:00:20 +030087#ifdef HTC_AUDIO
Giulio Cervera548b3192013-04-20 07:44:26 +020088Mutex mAIC3254ConfigLock;
Michael Bestas14030ec2013-05-14 20:00:20 +030089#endif
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +000090static int audpre_index, tx_iir_index;
91static void * acoustic;
92const uint32_t AudioHardware::inputSamplingRates[] = {
93 8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000
94};
Giulio Cervera548b3192013-04-20 07:44:26 +020095static const uint32_t INVALID_DEVICE = 65535;
96static const uint32_t SND_DEVICE_CURRENT =-1;
97static const uint32_t SND_DEVICE_HANDSET = 0;
98static const uint32_t SND_DEVICE_SPEAKER = 1;
99static const uint32_t SND_DEVICE_HEADSET = 2;
100static const uint32_t SND_DEVICE_FM_HANDSET = 3;
101static const uint32_t SND_DEVICE_FM_SPEAKER = 4;
102static const uint32_t SND_DEVICE_FM_HEADSET = 5;
103static const uint32_t SND_DEVICE_BT = 6;
104static const uint32_t SND_DEVICE_HEADSET_AND_SPEAKER = 7;
105static const uint32_t SND_DEVICE_NO_MIC_HEADSET = 8;
106static const uint32_t SND_DEVICE_IN_S_SADC_OUT_HANDSET = 9;
107static const uint32_t SND_DEVICE_IN_S_SADC_OUT_SPEAKER_PHONE = 10;
108static const uint32_t SND_DEVICE_TTY_HEADSET = 11;
109static const uint32_t SND_DEVICE_TTY_HCO = 12;
110static const uint32_t SND_DEVICE_TTY_VCO = 13;
111static const uint32_t SND_DEVICE_TTY_FULL = 14;
112static const uint32_t SND_DEVICE_HDMI = 15;
113static const uint32_t SND_DEVICE_FM_TX = 16;
114static const uint32_t SND_DEVICE_FM_TX_AND_SPEAKER = 17;
115static const uint32_t SND_DEVICE_HEADPHONE_AND_SPEAKER = 18;
Michael Bestas14030ec2013-05-14 20:00:20 +0300116#ifdef HTC_AUDIO
Giulio Cervera548b3192013-04-20 07:44:26 +0200117static const uint32_t SND_DEVICE_CARKIT = 19;
118static const uint32_t SND_DEVICE_HANDSET_BACK_MIC = 20;
119static const uint32_t SND_DEVICE_SPEAKER_BACK_MIC = 21;
120static const uint32_t SND_DEVICE_NO_MIC_HEADSET_BACK_MIC = 28;
121static const uint32_t SND_DEVICE_HEADSET_AND_SPEAKER_BACK_MIC = 30;
122static const uint32_t SND_DEVICE_I2S_SPEAKER = 32;
123static const uint32_t SND_DEVICE_BT_EC_OFF = 45;
124static const uint32_t SND_DEVICE_HAC = 252;
125static const uint32_t SND_DEVICE_USB_HEADSET = 253;
Michael Bestas14030ec2013-05-14 20:00:20 +0300126#else
127static const uint32_t SND_DEVICE_CARKIT = -1;
128static const uint32_t SND_DEVICE_BT_EC_OFF = -1;
129#endif
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +0000130#ifdef SAMSUNG_AUDIO
Giulio Cervera548b3192013-04-20 07:44:26 +0200131static const uint32_t SND_DEVICE_VOIP_HANDSET = 50;
132static const uint32_t SND_DEVICE_VOIP_SPEAKER = 51;
133static const uint32_t SND_DEVICE_VOIP_HEADSET = 52;
134static const uint32_t SND_DEVICE_CALL_HANDSET = 60;
135static const uint32_t SND_DEVICE_CALL_SPEAKER = 61;
136static const uint32_t SND_DEVICE_CALL_HEADSET = 62;
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +0000137#endif
138
Giulio Cervera548b3192013-04-20 07:44:26 +0200139static const uint32_t DEVICE_HANDSET_RX = 0; /* handset_rx */
140static const uint32_t DEVICE_HANDSET_TX = 1; /* handset_tx */
141static const uint32_t DEVICE_SPEAKER_RX = 2; /* caf: speaker_stereo_rx
142 htc: speaker_mono_rx
143 sam: speaker_rx */
Michael Bestas14030ec2013-05-14 20:00:20 +0300144static const uint32_t DEVICE_SPEAKER_TX = 3; /* caf: speaker_mono_tx
Giulio Cervera548b3192013-04-20 07:44:26 +0200145 sam: speaker_tx */
Michael Bestas14030ec2013-05-14 20:00:20 +0300146static const uint32_t DEVICE_HEADSET_RX = 4; /* caf: headset_stereo_rx
Giulio Cervera548b3192013-04-20 07:44:26 +0200147 sam: headset_rx */
Michael Bestas14030ec2013-05-14 20:00:20 +0300148static const uint32_t DEVICE_HEADSET_TX = 5; /* caf: headset_mono_tx
Giulio Cervera548b3192013-04-20 07:44:26 +0200149 sam: headset_tx */
150static const uint32_t DEVICE_FMRADIO_HANDSET_RX = 6; /* fmradio_handset_rx */
151static const uint32_t DEVICE_FMRADIO_HEADSET_RX = 7; /* fmradio_headset_rx */
152static const uint32_t DEVICE_FMRADIO_SPEAKER_RX = 8; /* fmradio_speaker_rx */
153static const uint32_t DEVICE_DUALMIC_HANDSET_TX = 9; /* handset_dual_mic_endfire_tx */
154static const uint32_t DEVICE_DUALMIC_SPEAKER_TX = 10; /* speaker_dual_mic_endfire_tx */
155static const uint32_t DEVICE_TTY_HEADSET_MONO_RX = 11; /* tty_headset_mono_rx */
156static const uint32_t DEVICE_TTY_HEADSET_MONO_TX = 12; /* tty_headset_mono_tx */
157static const uint32_t DEVICE_SPEAKER_HEADSET_RX = 13; /* caf: headset_stereo_speaker_stereo_rx
158 htc: headset_speaker_stereo_rx
159 sam: speaker_headset_rx */
160static const uint32_t DEVICE_FMRADIO_STEREO_TX = 14;
161static const uint32_t DEVICE_HDMI_STERO_RX = 15; /* hdmi_stereo_rx */
162static const uint32_t DEVICE_FMRADIO_STEREO_RX = 16;
163static const uint32_t DEVICE_BT_SCO_RX = 17; /* bt_sco_rx */
164static const uint32_t DEVICE_BT_SCO_TX = 18; /* bt_sco_tx */
Michael Bestas14030ec2013-05-14 20:00:20 +0300165#if defined(SAMSUNG_AUDIO)
Giulio Cervera548b3192013-04-20 07:44:26 +0200166static const uint32_t DEVICE_HANDSET_VOIP_RX = 40; /* handset_voip_rx */
167static const uint32_t DEVICE_HANDSET_VOIP_TX = 41; /* handset_voip_tx */
168static const uint32_t DEVICE_SPEAKER_VOIP_RX = 42; /* speaker_voip_rx */
169static const uint32_t DEVICE_SPEAKER_VOIP_TX = 43; /* speaker_voip_tx */
170static const uint32_t DEVICE_HEADSET_VOIP_RX = 44; /* headset_voip_rx */
171static const uint32_t DEVICE_HEADSET_VOIP_TX = 45; /* headset_voip_tx */
172static const uint32_t DEVICE_HANDSET_CALL_RX = 60; /* handset_call_rx */
173static const uint32_t DEVICE_HANDSET_CALL_TX = 61; /* handset_call_tx */
174static const uint32_t DEVICE_SPEAKER_CALL_RX = 62; /* speaker_call_rx */
175static const uint32_t DEVICE_SPEAKER_CALL_TX = 63; /* speaker_call_tx */
176static const uint32_t DEVICE_HEADSET_CALL_RX = 64; /* headset_call_rx */
177static const uint32_t DEVICE_HEADSET_CALL_TX = 65; /* headset_call_tx */
178static const uint32_t DEVICE_COUNT = DEVICE_HEADSET_CALL_TX +1;
Michael Bestas14030ec2013-05-14 20:00:20 +0300179#elif defined(HTC_AUDIO)
180static const uint32_t DEVICE_USB_HEADSET_RX = 19; /* usb_headset_stereo_rx */
181static const uint32_t DEVICE_HAC_RX = 20; /* hac_mono_rx */
182static const uint32_t DEVICE_ALT_RX = 21; /* alt_mono_rx */
183static const uint32_t DEVICE_VR_HANDSET = 22; /* handset_vr_tx */
Giulio Cervera548b3192013-04-20 07:44:26 +0200184static const uint32_t DEVICE_COUNT = DEVICE_VR_HANDSET +1;
Michael Bestas14030ec2013-05-14 20:00:20 +0300185#else
186static uint32_t DEVICE_COUNT = DEVICE_BT_SCO_TX +1;
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +0000187#endif
188
Michael Bestas14030ec2013-05-14 20:00:20 +0300189#ifdef HTC_AUDIO
Giulio Cervera548b3192013-04-20 07:44:26 +0200190static bool support_aic3254 = true;
191static bool aic3254_enabled = true;
192int (*set_sound_effect)(const char* effect);
193static bool support_tpa2051 = true;
194static bool support_htc_backmic = true;
Giulio Cervera548b3192013-04-20 07:44:26 +0200195static bool fm_enabled = false;
196static int alt_enable = 0;
197static int hac_enable = 0;
198static uint32_t cur_aic_tx = UPLINK_OFF;
199static uint32_t cur_aic_rx = DOWNLINK_OFF;
200static int cur_tpa_mode = 0;
Michael Bestas14030ec2013-05-14 20:00:20 +0300201#endif
Giulio Cervera548b3192013-04-20 07:44:26 +0200202
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +0000203int dev_cnt = 0;
204const char ** name = NULL;
205int mixer_cnt = 0;
206static uint32_t cur_tx = INVALID_DEVICE;
207static uint32_t cur_rx = INVALID_DEVICE;
208bool vMicMute = false;
209typedef struct routing_table
210{
211 unsigned short dec_id;
212 int dev_id;
213 int dev_id_tx;
214 int stream_type;
215 bool active;
216 struct routing_table *next;
217} Routing_table;
218Routing_table* head;
219Mutex mRoutingTableLock;
220
221typedef struct device_table
222{
223 int dev_id;
224 int class_id;
225 int capability;
226}Device_table;
227Device_table* device_list;
228
229static unsigned char build_id[20];
230
231static void amr_transcode(unsigned char *src, unsigned char *dst);
232
233enum STREAM_TYPES {
234PCM_PLAY=1,
235PCM_REC,
Arne Coucheron0c85f772013-04-23 12:18:53 +0200236#ifdef QCOM_TUNNEL_LPA_ENABLED
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +0000237LPA_DECODE,
Arne Coucheron0c85f772013-04-23 12:18:53 +0200238#endif
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +0000239VOICE_CALL,
Arne Coucheron0c85f772013-04-23 12:18:53 +0200240#ifdef QCOM_FM_ENABLED
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +0000241FM_RADIO,
242FM_REC,
243FM_A2DP,
Arne Coucheron0c85f772013-04-23 12:18:53 +0200244#endif
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +0000245INVALID_STREAM
246};
247
248typedef struct ComboDeviceType
249{
250 uint32_t DeviceId;
251 STREAM_TYPES StreamType;
252}CurrentComboDeviceStruct;
253CurrentComboDeviceStruct CurrentComboDeviceData;
254Mutex mComboDeviceLock;
255
Arne Coucheron0c85f772013-04-23 12:18:53 +0200256#ifdef QCOM_FM_ENABLED
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +0000257enum FM_STATE {
258 FM_INVALID=1,
259 FM_OFF,
260 FM_ON
261};
262
263FM_STATE fmState = FM_INVALID;
Arne Coucheron0c85f772013-04-23 12:18:53 +0200264#endif
265
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +0000266static uint32_t fmDevice = INVALID_DEVICE;
267
268#define DEV_ID(X) device_list[X].dev_id
269void addToTable(int decoder_id,int device_id,int device_id_tx,int stream_type,bool active) {
270 Routing_table* temp_ptr;
271 Mutex::Autolock lock(mRoutingTableLock);
272 temp_ptr = (Routing_table* ) malloc(sizeof(Routing_table));
273 temp_ptr->next = NULL;
274 temp_ptr->dec_id = decoder_id;
275 temp_ptr->dev_id = device_id;
276 temp_ptr->dev_id_tx = device_id_tx;
277 temp_ptr->stream_type = stream_type;
278 temp_ptr->active = active;
279 //add new Node to head.
280 temp_ptr->next =head->next;
281 head->next = temp_ptr;
282}
283bool isStreamOn(int Stream_type) {
284 Routing_table* temp_ptr;
285 Mutex::Autolock lock(mRoutingTableLock);
286 temp_ptr = head->next;
287 while(temp_ptr!=NULL) {
288 if(temp_ptr->stream_type == Stream_type)
289 return true;
290 temp_ptr=temp_ptr->next;
291 }
292 return false;
293}
294bool isStreamOnAndActive(int Stream_type) {
295 Routing_table* temp_ptr;
296 Mutex::Autolock lock(mRoutingTableLock);
297 temp_ptr = head->next;
298 while(temp_ptr!=NULL) {
299 if(temp_ptr->stream_type == Stream_type) {
300 if(temp_ptr->active == true) {
301 return true;
302 }
303 else {
304 return false;
305 }
306 }
307 temp_ptr=temp_ptr->next;
308 }
309 return false;
310}
311bool isStreamOnAndInactive(int Stream_type) {
312 Routing_table* temp_ptr;
313 Mutex::Autolock lock(mRoutingTableLock);
314 temp_ptr = head->next;
315 while(temp_ptr!=NULL) {
316 if(temp_ptr->stream_type == Stream_type) {
317 if(temp_ptr->active == false) {
318 return true;
319 }
320 else {
321 return false;
322 }
323 }
324 temp_ptr=temp_ptr->next;
325 }
326 return false;
327}
328Routing_table* getNodeByStreamType(int Stream_type) {
329 Routing_table* temp_ptr;
330 Mutex::Autolock lock(mRoutingTableLock);
331 temp_ptr = head->next;
332 while(temp_ptr!=NULL) {
333 if(temp_ptr->stream_type == Stream_type) {
334 return temp_ptr;
335 }
336 temp_ptr=temp_ptr->next;
337 }
338 return NULL;
339}
340void modifyActiveStateOfStream(int Stream_type, bool Active) {
341 Routing_table* temp_ptr;
342 Mutex::Autolock lock(mRoutingTableLock);
343 temp_ptr = head->next;
344 while(temp_ptr!=NULL) {
345 if(temp_ptr->stream_type == Stream_type) {
346 temp_ptr->active = Active;
347 return;
348 }
349 temp_ptr=temp_ptr->next;
350 }
351}
352void modifyActiveDeviceOfStream(int Stream_type,int Device_id,int Device_id_tx) {
353 Routing_table* temp_ptr;
354 temp_ptr = head->next;
355 while(temp_ptr!=NULL) {
356 if(temp_ptr->stream_type == Stream_type) {
357 temp_ptr->dev_id = Device_id;
358 temp_ptr->dev_id_tx = Device_id_tx;
359 return;
360 }
361 temp_ptr=temp_ptr->next;
362 }
363}
364void printTable()
365{
366 Routing_table * temp_ptr;
367 Mutex::Autolock lock(mRoutingTableLock);
368 temp_ptr = head->next;
369 while(temp_ptr!=NULL) {
370 printf("%d %d %d %d %d\n",temp_ptr->dec_id,temp_ptr->dev_id,temp_ptr->dev_id_tx,temp_ptr->stream_type,temp_ptr->active);
371 temp_ptr = temp_ptr->next;
372 }
373}
374void deleteFromTable(int Stream_type) {
375 Routing_table *temp_ptr,*temp1;
376 Mutex::Autolock lock(mRoutingTableLock);
377 temp_ptr = head;
378 while(temp_ptr->next!=NULL) {
379 if(temp_ptr->next->stream_type == Stream_type) {
380 temp1 = temp_ptr->next;
381 temp_ptr->next = temp_ptr->next->next;
382 free(temp1);
383 return;
384 }
385 temp_ptr=temp_ptr->next;
386 }
387
388}
389
390bool isDeviceListEmpty() {
391 if(head->next == NULL)
392 return true;
393 else
394 return false;
395}
396
397int enableDevice(int device,short enable) {
Michael Bestasf281d5e2013-08-16 17:39:03 +0300398 ALOGV("value of device and enable is %d %d ALSA dev id:%d",device,enable,DEV_ID(device));
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +0000399 if( msm_en_device(DEV_ID(device), enable)) {
400 ALOGE("msm_en_device(%d, %d) failed errno = %d",DEV_ID(device), enable, errno);
401 return -1;
402 }
403 return 0;
404}
405
Michael Bestas14030ec2013-05-14 20:00:20 +0300406#ifdef HTC_AUDIO
Giulio Cervera548b3192013-04-20 07:44:26 +0200407void updateACDB(uint32_t new_rx_device, uint32_t new_tx_device,
408 uint32_t new_rx_acdb, uint32_t new_tx_acdb) {
409
410 ALOGD("updateACDB: (%d, %d, %d, %d) ", new_tx_device, new_rx_device, new_tx_acdb, new_rx_acdb);
411
412 int rc = -1;
413 int (*update_acdb_id)(uint32_t, uint32_t, uint32_t, uint32_t);
414
415 update_acdb_id = (int (*)(uint32_t, uint32_t, uint32_t, uint32_t))::dlsym(acoustic, "update_acdb_id");
416 if ((*update_acdb_id) == 0)
417 ALOGE("Could not open update_acdb_id()");
418 else {
419 rc = update_acdb_id(new_tx_device, new_rx_device, new_tx_acdb, new_rx_acdb);
420 if (rc < 0)
421 ALOGE("Could not set update_acdb_id: %d", rc);
422 }
423}
424
425static status_t updateDeviceInfo(int rx_device,int tx_device,
426 uint32_t rx_acdb_id, uint32_t tx_acdb_id) {
Michael Bestas14030ec2013-05-14 20:00:20 +0300427#else
428static status_t updateDeviceInfo(int rx_device,int tx_device) {
429#endif
Michael Bestasf281d5e2013-08-16 17:39:03 +0300430 ALOGV("updateDeviceInfo: E rx_device %d and tx_device %d", rx_device, tx_device);
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +0000431 bool isRxDeviceEnabled = false,isTxDeviceEnabled = false;
432 Routing_table *temp_ptr,*temp_head;
433 int tx_dev_prev = INVALID_DEVICE;
434 temp_head = head;
435 Mutex::Autolock lock(mDeviceSwitchLock);
436
Arne Coucheron0c85f772013-04-23 12:18:53 +0200437 if (!getNodeByStreamType(VOICE_CALL) && !getNodeByStreamType(PCM_PLAY)
438#ifdef QCOM_FM_ENABLED
439 && !getNodeByStreamType(FM_RADIO)
440#endif
441#ifdef QCOM_TUNNEL_LPA_ENABLED
442 && !getNodeByStreamType(LPA_DECODE)
443#endif
444 ) {
Michael Bestasf281d5e2013-08-16 17:39:03 +0300445 ALOGV("No active voicecall/playback, disabling cur_rx %d", cur_rx);
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +0000446 if(cur_rx != INVALID_DEVICE && enableDevice(cur_rx, 0)) {
447 ALOGE("Disabling device failed for cur_rx %d", cur_rx);
448 }
449 cur_rx = rx_device;
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +0000450 }
451
452 if(!getNodeByStreamType(VOICE_CALL) && !getNodeByStreamType(PCM_REC)) {
Michael Bestasf281d5e2013-08-16 17:39:03 +0300453 ALOGV("No active voicecall/recording, disabling cur_tx %d", cur_tx);
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +0000454 if(cur_tx != INVALID_DEVICE && enableDevice(cur_tx, 0)) {
455 ALOGE("Disabling device failed for cur_tx %d", cur_tx);
456 }
457 cur_tx = tx_device;
458 }
459 Mutex::Autolock lock_1(mRoutingTableLock);
460
461 while(temp_head->next != NULL) {
462 temp_ptr = temp_head->next;
463 switch(temp_ptr->stream_type) {
464 case PCM_PLAY:
Arne Coucheron0c85f772013-04-23 12:18:53 +0200465#ifdef QCOM_TUNNEL_LPA_ENABLED
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +0000466 case LPA_DECODE:
Arne Coucheron0c85f772013-04-23 12:18:53 +0200467#endif
468#ifdef QCOM_FM_ENABLED
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +0000469 case FM_RADIO:
Arne Coucheron0c85f772013-04-23 12:18:53 +0200470#endif
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +0000471 ALOGD("The node type is %d and cur device %d new device %d ", temp_ptr->stream_type, temp_ptr->dev_id, rx_device);
472 if(rx_device == INVALID_DEVICE)
473 return -1;
474 if(rx_device == temp_ptr->dev_id)
475 break;
476 ALOGV("rx_device = %d,temp_ptr->dev_id = %d",rx_device,temp_ptr->dev_id);
477 if(isRxDeviceEnabled == false) {
478 enableDevice(temp_ptr->dev_id,0);
479 enableDevice(rx_device,1);
480 isRxDeviceEnabled = true;
481 }
482 if(msm_route_stream(PCM_PLAY,temp_ptr->dec_id,DEV_ID(temp_ptr->dev_id),0)) {
483 ALOGE("msm_route_stream(PCM_PLAY,%d,%d,0) failed",temp_ptr->dec_id,DEV_ID(temp_ptr->dev_id));
484 }
485 if(msm_route_stream(PCM_PLAY,temp_ptr->dec_id,DEV_ID(rx_device),1)) {
486 ALOGE("msm_route_stream(PCM_PLAY,%d,%d,1) failed",temp_ptr->dec_id,DEV_ID(rx_device));
487 }
488 modifyActiveDeviceOfStream(temp_ptr->stream_type,rx_device,INVALID_DEVICE);
489 cur_tx = tx_device ;
490 cur_rx = rx_device ;
491 break;
492 case PCM_REC:
493
494 ALOGD("case PCM_REC");
495 if(tx_device == INVALID_DEVICE)
496 return -1;
497 if(tx_device == temp_ptr->dev_id)
498 break;
499
500 if(isTxDeviceEnabled == false) {
501 enableDevice(temp_ptr->dev_id,0);
502 enableDevice(tx_device,1);
503 isTxDeviceEnabled = true;
504 }
505 if(msm_route_stream(PCM_REC,temp_ptr->dec_id,DEV_ID(temp_ptr->dev_id),0)) {
Giulio Cervera548b3192013-04-20 07:44:26 +0200506 ALOGE("msm_route_stream(PCM_REC,%d,%d,0) failed",temp_ptr->dec_id,DEV_ID(temp_ptr->dev_id));
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +0000507 }
508 if(msm_route_stream(PCM_REC,temp_ptr->dec_id,DEV_ID(tx_device),1)) {
509 ALOGE("msm_route_stream(PCM_REC,%d,%d,1) failed",temp_ptr->dec_id,DEV_ID(tx_device));
510 }
511 modifyActiveDeviceOfStream(PCM_REC,tx_device,INVALID_DEVICE);
512 tx_dev_prev = cur_tx;
513 cur_tx = tx_device ;
514 cur_rx = rx_device ;
Arne Coucheron0c85f772013-04-23 12:18:53 +0200515#ifdef WITH_QCOM_VOIPMUTE
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +0000516 if((vMicMute == true) && (tx_dev_prev != cur_tx)) {
517 ALOGD("REC:device switch with mute enabled :tx_dev_prev %d cur_tx: %d",tx_dev_prev, cur_tx);
518 msm_device_mute(DEV_ID(cur_tx), true);
519 }
Arne Coucheron0c85f772013-04-23 12:18:53 +0200520#endif
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +0000521 break;
522 case VOICE_CALL:
523
524 ALOGD("case VOICE_CALL");
525 if(rx_device == INVALID_DEVICE || tx_device == INVALID_DEVICE)
526 return -1;
527 if(rx_device == temp_ptr->dev_id && tx_device == temp_ptr->dev_id_tx)
528 break;
529
Michael Bestas14030ec2013-05-14 20:00:20 +0300530#ifdef HTC_AUDIO
531 updateACDB(rx_device, tx_device, rx_acdb_id, tx_acdb_id);
532#endif
Giulio Cervera548b3192013-04-20 07:44:26 +0200533
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +0000534 msm_route_voice(DEV_ID(rx_device),DEV_ID(tx_device),1);
535
536 // Temporary work around for Speaker mode. The driver is not
537 // supporting Speaker Rx and Handset Tx combo
538 if(isRxDeviceEnabled == false) {
539 if (rx_device != temp_ptr->dev_id)
540 {
541 enableDevice(temp_ptr->dev_id,0);
542 }
543 isRxDeviceEnabled = true;
544 }
545 if(isTxDeviceEnabled == false) {
546 if (tx_device != temp_ptr->dev_id_tx)
547 {
548 enableDevice(temp_ptr->dev_id_tx,0);
549 }
550 isTxDeviceEnabled = true;
551 }
552
553 if (rx_device != temp_ptr->dev_id)
554 {
555 enableDevice(rx_device,1);
556 }
557
558 if (tx_device != temp_ptr->dev_id_tx)
559 {
560 enableDevice(tx_device,1);
561 }
562
563 cur_rx = rx_device;
564 cur_tx = tx_device;
565 modifyActiveDeviceOfStream(VOICE_CALL,cur_rx,cur_tx);
566 break;
567 default:
568 break;
569 }
570 temp_head = temp_head->next;
571 }
572
Michael Bestasf281d5e2013-08-16 17:39:03 +0300573 ALOGV("updateDeviceInfo: X cur_rx %d cur_tx %d", cur_rx, cur_tx);
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +0000574 return NO_ERROR;
575}
576
577void freeMemory() {
578 Routing_table *temp;
579 while(head != NULL) {
580 temp = head->next;
581 free(head);
582 head = temp;
583 }
584free(device_list);
585}
586
587//
588// ----------------------------------------------------------------------------
589
590AudioHardware::AudioHardware() :
Michael Bestas112d7da2013-08-16 17:39:03 +0300591 mInit(false), mMicMute(true), mFmFd(-1), mBluetoothNrec(true),
592 mBluetoothVGS(false), mBluetoothId(0), mVoiceVolume(1), mOutput(0),
593 mCurSndDevice(SND_DEVICE_CURRENT), mDualMicEnabled(false), mTtyMode(TTY_OFF)
Michael Bestas14030ec2013-05-14 20:00:20 +0300594#ifdef HTC_AUDIO
595 , mHACSetting(false), mBluetoothIdTx(0), mBluetoothIdRx(0),
596 mRecordState(false), mEffectEnabled(false)
597#endif
Arne Coucheron0c85f772013-04-23 12:18:53 +0200598#ifdef WITH_QCOM_VOIP_OVER_MVS
Michael Bestas14030ec2013-05-14 20:00:20 +0300599 , mVoipFd(-1), mVoipInActive(false), mVoipOutActive(false), mDirectOutput(0)
Arne Coucheron0c85f772013-04-23 12:18:53 +0200600#endif
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +0000601{
Michael Bestas14030ec2013-05-14 20:00:20 +0300602#ifdef HTC_AUDIO
Giulio Cervera548b3192013-04-20 07:44:26 +0200603 int (*snd_get_num)();
604 int (*snd_get_bt_endpoint)(msm_bt_endpoint *);
605 int (*set_acoustic_parameters)();
606 int (*set_tpa2051_parameters)();
607 int (*set_aic3254_parameters)();
608 int (*support_back_mic)();
609
610 struct msm_bt_endpoint *ept;
Michael Bestas14030ec2013-05-14 20:00:20 +0300611#endif
Giulio Cervera548b3192013-04-20 07:44:26 +0200612
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +0000613 int control;
614 int i = 0,index = 0;
615
616 head = (Routing_table* ) malloc(sizeof(Routing_table));
617 head->next = NULL;
618
Michael Bestas14030ec2013-05-14 20:00:20 +0300619#ifdef HTC_AUDIO
Giulio Cervera548b3192013-04-20 07:44:26 +0200620 acoustic =:: dlopen("/system/lib/libhtc_acoustic.so", RTLD_NOW);
621 if (acoustic == NULL ) {
622 ALOGD("Could not open libhtc_acoustic.so");
623 /* this is not really an error on non-htc devices... */
624 mNumBTEndpoints = 0;
Giulio Cervera548b3192013-04-20 07:44:26 +0200625 support_aic3254 = false;
626 support_tpa2051 = false;
627 support_htc_backmic = false;
628 }
Michael Bestas14030ec2013-05-14 20:00:20 +0300629#endif
Giulio Cervera548b3192013-04-20 07:44:26 +0200630
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +0000631 ALOGD("msm_mixer_open: Opening the device");
632 control = msm_mixer_open("/dev/snd/controlC0", 0);
633 if(control< 0)
634 ALOGE("ERROR opening the device");
635
636 if((fp = fopen("/sys/devices/system/soc/soc0/build_id","r")) == NULL) {
637 ALOGE("Cannot open build_id file.");
638 }
639 else {
640 (void)fgets((char *)build_id,sizeof(build_id),fp);
641 }
642
Arne Coucheron0c85f772013-04-23 12:18:53 +0200643#ifdef WITH_QCOM_RESETALL
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +0000644 if(msm_reset_all_device() < 0)
645 ALOGE("msm_reset_all_device() failed");
Arne Coucheron0c85f772013-04-23 12:18:53 +0200646#endif
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +0000647
648 mixer_cnt = msm_mixer_count();
649 ALOGD("msm_mixer_count:mixer_cnt =%d",mixer_cnt);
650
651 dev_cnt = msm_get_device_count();
652 ALOGV("got device_count %d",dev_cnt);
653 if (dev_cnt <= 0) {
654 ALOGE("NO devices registered\n");
655 return;
656 }
657 name = msm_get_device_list();
658 device_list = (Device_table* )malloc(sizeof(Device_table)*DEVICE_COUNT);
659 if(device_list == NULL) {
660 ALOGE("malloc failed for device list");
661 return;
662 }
Tiziano Carottid501a1a2013-04-21 05:06:46 +0200663 for(i = 0;i<DEVICE_COUNT;i++)
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +0000664 device_list[i].dev_id = INVALID_DEVICE;
665
666 for(i = 0; i < dev_cnt;i++) {
Giulio Cervera1844bcd2013-04-20 08:09:30 +0200667 ALOGI("******* name[%d] = [%s] *********", i, (char* )name[i]);
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +0000668 if(strcmp((char* )name[i],"handset_rx") == 0)
669 index = DEVICE_HANDSET_RX;
670 else if(strcmp((char* )name[i],"handset_tx") == 0)
671 index = DEVICE_HANDSET_TX;
672 else if((strcmp((char* )name[i],"speaker_stereo_rx") == 0) ||
freexperia01774142012-05-30 09:30:10 +0300673#ifndef WITH_STEREO_HW_SPEAKER
Giulio Cervera548b3192013-04-20 07:44:26 +0200674 (strcmp((char* )name[i],"speaker_mono_rx") == 0) ||
freexperia01774142012-05-30 09:30:10 +0300675#endif
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +0000676 (strcmp((char* )name[i],"speaker_rx") == 0))
677 index = DEVICE_SPEAKER_RX;
678 else if((strcmp((char* )name[i],"speaker_mono_tx") == 0) ||
679 (strcmp((char* )name[i],"speaker_tx") == 0))
680 index = DEVICE_SPEAKER_TX;
681 else if((strcmp((char* )name[i],"headset_stereo_rx") == 0) ||
682 (strcmp((char* )name[i],"headset_rx") == 0))
683 index = DEVICE_HEADSET_RX;
684 else if((strcmp((char* )name[i],"headset_mono_tx") == 0) ||
685 (strcmp((char* )name[i],"headset_tx") == 0))
686 index = DEVICE_HEADSET_TX;
687 else if(strcmp((char* )name[i],"fmradio_handset_rx") == 0)
688 index = DEVICE_FMRADIO_HANDSET_RX;
689 else if(strcmp((char* )name[i],"fmradio_headset_rx") == 0)
690 index = DEVICE_FMRADIO_HEADSET_RX;
691 else if(strcmp((char* )name[i],"fmradio_speaker_rx") == 0)
692 index = DEVICE_FMRADIO_SPEAKER_RX;
693 else if(strcmp((char* )name[i],"handset_dual_mic_endfire_tx") == 0)
694 index = DEVICE_DUALMIC_HANDSET_TX;
695 else if(strcmp((char* )name[i],"speaker_dual_mic_endfire_tx") == 0)
696 index = DEVICE_DUALMIC_SPEAKER_TX;
697 else if(strcmp((char* )name[i],"tty_headset_mono_rx") == 0)
698 index = DEVICE_TTY_HEADSET_MONO_RX;
699 else if(strcmp((char* )name[i],"tty_headset_mono_tx") == 0)
700 index = DEVICE_TTY_HEADSET_MONO_TX;
701 else if(strcmp((char* )name[i],"bt_sco_rx") == 0)
702 index = DEVICE_BT_SCO_RX;
703 else if(strcmp((char* )name[i],"bt_sco_tx") == 0)
704 index = DEVICE_BT_SCO_TX;
705 else if((strcmp((char*)name[i],"headset_stereo_speaker_stereo_rx") == 0) ||
Giulio Cervera548b3192013-04-20 07:44:26 +0200706 (strcmp((char*)name[i],"headset_speaker_stereo_rx") == 0) ||
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +0000707 (strcmp((char*)name[i],"speaker_headset_rx") == 0))
708 index = DEVICE_SPEAKER_HEADSET_RX;
709 else if(strcmp((char*)name[i],"fmradio_stereo_tx") == 0)
710 index = DEVICE_FMRADIO_STEREO_TX;
711 else if(strcmp((char*)name[i],"hdmi_stereo_rx") == 0)
712 index = DEVICE_HDMI_STERO_RX;
713 else if(strcmp((char*)name[i],"fmradio_stereo_rx") == 0)
714 index = DEVICE_FMRADIO_STEREO_RX;
715#ifdef SAMSUNG_AUDIO
716 else if(strcmp((char* )name[i], "handset_voip_rx") == 0)
717 index = DEVICE_HANDSET_VOIP_RX;
718 else if(strcmp((char* )name[i], "handset_voip_tx") == 0)
719 index = DEVICE_HANDSET_VOIP_TX;
720 else if(strcmp((char* )name[i], "speaker_voip_rx") == 0)
721 index = DEVICE_SPEAKER_VOIP_RX;
722 else if(strcmp((char* )name[i], "speaker_voip_tx") == 0)
723 index = DEVICE_SPEAKER_VOIP_TX;
724 else if(strcmp((char* )name[i], "headset_voip_rx") == 0)
725 index = DEVICE_HEADSET_VOIP_RX;
726 else if(strcmp((char* )name[i], "headset_voip_tx") == 0)
727 index = DEVICE_HEADSET_VOIP_TX;
728 else if(strcmp((char* )name[i], "handset_call_rx") == 0)
729 index = DEVICE_HANDSET_CALL_RX;
730 else if(strcmp((char* )name[i], "handset_call_tx") == 0)
731 index = DEVICE_HANDSET_CALL_TX;
732 else if(strcmp((char* )name[i], "speaker_call_rx") == 0)
733 index = DEVICE_SPEAKER_CALL_RX;
734 else if(strcmp((char* )name[i], "speaker_call_tx") == 0)
735 index = DEVICE_SPEAKER_CALL_TX;
736 else if(strcmp((char* )name[i], "headset_call_rx") == 0)
737 index = DEVICE_HEADSET_CALL_RX;
738 else if(strcmp((char* )name[i], "headset_call_tx") == 0)
739 index = DEVICE_HEADSET_CALL_TX;
740#endif
741 else
742 continue;
743 ALOGV("index = %d",index);
744
745 device_list[index].dev_id = msm_get_device((char* )name[i]);
746 if(device_list[index].dev_id >= 0) {
747 ALOGV("Found device: %s:index = %d,dev_id: %d",( char* )name[i], index,device_list[index].dev_id);
748 }
749 device_list[index].class_id = msm_get_device_class(device_list[index].dev_id);
750 device_list[index].capability = msm_get_device_capability(device_list[index].dev_id);
751 ALOGV("class ID = %d,capablity = %d for device %d",device_list[index].class_id,device_list[index].capability,device_list[index].dev_id);
752 }
753#ifdef WITH_QCOM_CALIBRATION
754 audcal_initialize();
755#endif
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +0000756
757 CurrentComboDeviceData.DeviceId = INVALID_DEVICE;
758 CurrentComboDeviceData.StreamType = INVALID_STREAM;
Giulio Cervera548b3192013-04-20 07:44:26 +0200759
Michael Bestas14030ec2013-05-14 20:00:20 +0300760#ifdef HTC_AUDIO
Giulio Cervera548b3192013-04-20 07:44:26 +0200761 // HTC specific functions
762 set_acoustic_parameters = (int (*)(void))::dlsym(acoustic, "set_acoustic_parameters");
763 if ((*set_acoustic_parameters) == 0 ) {
764 ALOGE("Could not open set_acoustic_parameters()");
765 return;
766 }
767
768 int rc = set_acoustic_parameters();
769 if (rc < 0) {
770 ALOGD("Could not set acoustic parameters to share memory: %d", rc);
771 }
772
773 char value[PROPERTY_VALUE_MAX];
774 /* Check the system property for enable or not the ALT function */
775 property_get("htc.audio.alt.enable", value, "0");
776 alt_enable = atoi(value);
777 ALOGV("Enable ALT function: %d", alt_enable);
778
779 /* Check the system property for enable or not the HAC function */
780 property_get("htc.audio.hac.enable", value, "0");
781 hac_enable = atoi(value);
782 ALOGV("Enable HAC function: %d", hac_enable);
783
784 set_tpa2051_parameters = (int (*)(void))::dlsym(acoustic, "set_tpa2051_parameters");
785 if ((*set_tpa2051_parameters) == 0) {
786 ALOGI("set_tpa2051_parameters() not present");
787 support_tpa2051 = false;
788 }
789
790 if (support_tpa2051) {
791 if (set_tpa2051_parameters() < 0) {
792 ALOGI("Speaker amplifies tpa2051 is not supported");
793 support_tpa2051 = false;
794 }
795 }
796
797 set_aic3254_parameters = (int (*)(void))::dlsym(acoustic, "set_aic3254_parameters");
798 if ((*set_aic3254_parameters) == 0 ) {
799 ALOGI("set_aic3254_parameters() not present");
800 support_aic3254 = false;
801 }
802
803 if (support_aic3254) {
804 if (set_aic3254_parameters() < 0) {
805 ALOGI("AIC3254 DSP is not supported");
806 support_aic3254 = false;
807 }
808 }
809
810 if (support_aic3254) {
811 set_sound_effect = (int (*)(const char*))::dlsym(acoustic, "set_sound_effect");
812 if ((*set_sound_effect) == 0 ) {
813 ALOGI("set_sound_effect() not present");
814 ALOGI("AIC3254 DSP is not supported");
815 support_aic3254 = false;
816 } else
817 strcpy(mEffect, "\0");
818 }
819
820 support_back_mic = (int (*)(void))::dlsym(acoustic, "support_back_mic");
821 if ((*support_back_mic) == 0 ) {
822 ALOGI("support_back_mic() not present");
823 support_htc_backmic = false;
824 }
825
826 if (support_htc_backmic) {
827 if (support_back_mic() != 1) {
828 ALOGI("HTC DualMic is not supported");
829 support_htc_backmic = false;
830 }
831 }
832
833 snd_get_num = (int (*)(void))::dlsym(acoustic, "snd_get_num");
834 if ((*snd_get_num) == 0 ) {
835 ALOGD("Could not open snd_get_num()");
836 }
837
838 mNumBTEndpoints = snd_get_num();
839 ALOGV("mNumBTEndpoints = %d", mNumBTEndpoints);
840 mBTEndpoints = new msm_bt_endpoint[mNumBTEndpoints];
841 ALOGV("constructed %d SND endpoints)", mNumBTEndpoints);
842 ept = mBTEndpoints;
843 snd_get_bt_endpoint = (int (*)(msm_bt_endpoint *))::dlsym(acoustic, "snd_get_bt_endpoint");
844 if ((*snd_get_bt_endpoint) == 0 ) {
845 mInit = true;
846 ALOGE("Could not open snd_get_bt_endpoint()");
847 return;
848 }
849 snd_get_bt_endpoint(mBTEndpoints);
850
851 for (int i = 0; i < mNumBTEndpoints; i++) {
852 ALOGV("BT name %s (tx,rx)=(%d,%d)", mBTEndpoints[i].name, mBTEndpoints[i].tx, mBTEndpoints[i].rx);
853 }
Michael Bestas14030ec2013-05-14 20:00:20 +0300854#endif
Giulio Cervera548b3192013-04-20 07:44:26 +0200855
856 mInit = true;
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +0000857}
858
859AudioHardware::~AudioHardware()
860{
861 for (size_t index = 0; index < mInputs.size(); index++) {
862 closeInputStream((AudioStreamIn*)mInputs[index]);
863 }
864 mInputs.clear();
865 closeOutputStream((AudioStreamOut*)mOutput);
866 if (acoustic) {
867 ::dlclose(acoustic);
868 acoustic = 0;
869 }
870 msm_mixer_close();
871#ifdef WITH_QCOM_CALIBRATION
872 audcal_deinitialize();
873#endif
874 freeMemory();
875 fclose(fp);
876 mInit = false;
877}
878
879status_t AudioHardware::initCheck()
880{
881 return mInit ? NO_ERROR : NO_INIT;
882}
883
884AudioStreamOut* AudioHardware::openOutputStream(
885 uint32_t devices, int *format, uint32_t *channels,
886 uint32_t *sampleRate, status_t *status)
887
888{
889 ALOGD("AudioHardware::openOutputStream devices %x format %d channels %d samplerate %d",
890 devices, *format, *channels, *sampleRate);
891
892 audio_output_flags_t flags = static_cast<audio_output_flags_t> (*status);
893
894
895 { // scope for the lock
896 Mutex::Autolock lock(mLock);
897
898 // only one output stream allowed
Arne Coucheron0c85f772013-04-23 12:18:53 +0200899#ifdef WITH_QCOM_VOIP_OVER_MVS
Arne Coucheron0de404b2013-04-23 11:42:42 +0200900 if (mOutput && !(flags & AUDIO_OUTPUT_FLAG_DIRECT) ) {
Arne Coucheron0c85f772013-04-23 12:18:53 +0200901#else
902 if (mOutput) {
903#endif
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +0000904 if (status) {
905 *status = INVALID_OPERATION;
906 }
907 ALOGE(" AudioHardware::openOutputStream Only one output stream allowed \n");
908 return 0;
909 }
Arne Coucheron0c85f772013-04-23 12:18:53 +0200910#ifdef WITH_QCOM_VOIP_OVER_MVS
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +0000911 status_t lStatus;
Arne Coucheron0de404b2013-04-23 11:42:42 +0200912 if(flags & AUDIO_OUTPUT_FLAG_DIRECT) {
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +0000913 if(mDirectOutput == 0) {
914 // open direct output stream
915 ALOGV(" AudioHardware::openOutputStream Direct output stream \n");
916 AudioStreamOutDirect* out = new AudioStreamOutDirect();
917 status_t lStatus = out->set(this, devices, format, channels, sampleRate);
918 if (status) {
919 *status = lStatus;
920 }
921 if (lStatus == NO_ERROR) {
922 mDirectOutput = out;
923 ALOGV(" \n set sucessful for AudioStreamOutDirect");
924 } else {
925 ALOGE(" \n set Failed for AudioStreamOutDirect");
926 delete out;
927 }
928 }
929 else
930 ALOGE(" \n AudioHardware::AudioStreamOutDirect is already open");
931 return mDirectOutput;
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +0000932 }
933 else
934 {
935 ALOGV(" AudioHardware::openOutputStream AudioStreamOutMSM72xx output stream \n");
936 // only one output stream allowed
937 if (mOutput) {
938 if (status) {
939 *status = INVALID_OPERATION;
940 }
941 ALOGE(" AudioHardware::openOutputStream Only one output stream allowed \n");
942 return 0;
943 }
944
945 // create new output stream
946 AudioStreamOutMSM72xx* out = new AudioStreamOutMSM72xx();
947 lStatus = out->set(this, devices, format, channels, sampleRate);
948 if (status) {
949 *status = lStatus;
950 }
951 if (lStatus == NO_ERROR) {
952 mOutput = out;
953 } else {
954 delete out;
955 }
956 return mOutput;
957 }
958 }
Arne Coucheron0c85f772013-04-23 12:18:53 +0200959#else
960 // create new output stream
961 AudioStreamOutMSM72xx* out = new AudioStreamOutMSM72xx();
962 status_t lStatus = out->set(this, devices, format, channels, sampleRate);
963 if (status) {
964 *status = lStatus;
965 }
966 if (lStatus == NO_ERROR) {
967 mOutput = out;
968 } else {
969 delete out;
970 }
971 }
972 return mOutput;
973#endif
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +0000974}
975
Arne Coucheron0de404b2013-04-23 11:42:42 +0200976#ifdef QCOM_TUNNEL_LPA_ENABLED
977AudioStreamOut* AudioHardware::openOutputSession(
978 uint32_t devices, int *format, status_t *status, int sessionId,
979 uint32_t samplingRate, uint32_t channels)
980{
981 AudioSessionOutMSM7xxx* out;
982 { // scope for the lock
983 Mutex::Autolock lock(mLock);
984
985 // create new output stream
986 out = new AudioSessionOutMSM7xxx();
987 status_t lStatus = out->set(this, devices, format, sessionId);
988 if (status) {
989 *status = lStatus;
990 }
991 if (lStatus != NO_ERROR) {
992 delete out;
993 out = NULL;
994 }
995 }
996 return out;
997}
998#endif /* QCOM_TUNNEL_LPA_ENABLED */
999
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001000void AudioHardware::closeOutputStream(AudioStreamOut* out) {
1001 Mutex::Autolock lock(mLock);
Arne Coucheron0c85f772013-04-23 12:18:53 +02001002#ifdef WITH_QCOM_VOIP_OVER_MVS
Arne Coucheron0de404b2013-04-23 11:42:42 +02001003 if ((mOutput == 0 && mDirectOutput == 0) || ((mOutput != out) && (mDirectOutput != out))){
Arne Coucheron0c85f772013-04-23 12:18:53 +02001004#else
1005 if (mOutput == 0 || mOutput != out) {
1006#endif
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001007 ALOGW("Attempt to close invalid output stream");
1008 }
Arne Coucheron0c85f772013-04-23 12:18:53 +02001009#ifdef WITH_QCOM_VOIP_OVER_MVS
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001010 else if (mOutput == out) {
Arne Coucheron0c85f772013-04-23 12:18:53 +02001011#else
1012 else {
1013#endif
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001014 delete mOutput;
1015 mOutput = 0;
1016 }
Arne Coucheron0c85f772013-04-23 12:18:53 +02001017#ifdef WITH_QCOM_VOIP_OVER_MVS
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001018 else if (mDirectOutput == out){
1019 ALOGV(" deleting mDirectOutput \n");
1020 delete mDirectOutput;
1021 mDirectOutput = 0;
1022 }
Arne Coucheron0c85f772013-04-23 12:18:53 +02001023#endif
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001024}
1025
1026AudioStreamIn* AudioHardware::openInputStream(
1027 uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status,
1028 AudioSystem::audio_in_acoustics acoustic_flags)
1029{
1030 // check for valid input source
1031 ALOGD("AudioHardware::openInputStream devices %x format %d channels %d samplerate %d",
1032 devices, *format, *channels, *sampleRate);
1033
1034 if (!AudioSystem::isInputDevice((AudioSystem::audio_devices)devices)) {
1035 return 0;
1036 }
1037
1038 mLock.lock();
1039
Arne Coucheron0c85f772013-04-23 12:18:53 +02001040#ifdef WITH_QCOM_VOIP_OVER_MVS
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001041 AudioStreamIn *in;
1042 if((devices == AudioSystem::DEVICE_IN_COMMUNICATION)&& (*sampleRate == 8000)) {
Arne Coucheron41eaae72013-04-17 05:17:23 +02001043 ALOGV("Create Audio stream Voip \n");
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001044 AudioStreamInVoip* inVoip = new AudioStreamInVoip();
1045 status_t lStatus = NO_ERROR;
1046 lStatus = inVoip->set(this, devices, format, channels, sampleRate, acoustic_flags);
1047 if (status) {
1048 *status = lStatus;
1049 }
1050 if (lStatus != NO_ERROR) {
1051 ALOGE(" Error creating voip input \n");
1052 mLock.unlock();
1053 delete inVoip;
1054 return 0;
1055 }
1056 mVoipInputs.add(inVoip);
Arne Coucheron0c85f772013-04-23 12:18:53 +02001057#else
1058 AudioStreamInMSM72xx* in = new AudioStreamInMSM72xx();
1059 status_t lStatus = in->set(this, devices, format, channels, sampleRate, acoustic_flags);
1060 if (status) {
1061 *status = lStatus;
1062 }
1063 if (lStatus != NO_ERROR) {
1064#endif
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001065 mLock.unlock();
Arne Coucheron0c85f772013-04-23 12:18:53 +02001066#ifndef WITH_QCOM_VOIP_OVER_MVS
1067 delete in;
1068 return 0;
1069#else
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001070 return inVoip;
1071 } else {
1072 AudioStreamInMSM72xx* in72xx = new AudioStreamInMSM72xx();
1073 status_t lStatus = in72xx->set(this, devices, format, channels, sampleRate, acoustic_flags);
1074 if (status) {
1075 *status = lStatus;
1076 }
1077 if (lStatus != NO_ERROR) {
1078 ALOGE("Error creating Audio stream AudioStreamInMSM72xx \n");
1079 mLock.unlock();
1080 delete in72xx;
1081 return 0;
1082 }
1083 mInputs.add(in72xx);
1084 mLock.unlock();
1085 return in72xx;
Arne Coucheron0c85f772013-04-23 12:18:53 +02001086#endif
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001087 }
Arne Coucheron0c85f772013-04-23 12:18:53 +02001088#ifndef WITH_QCOM_VOIP_OVER_MVS
1089 mInputs.add(in);
1090 mLock.unlock();
1091
1092 return in;
1093#endif
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001094}
1095
1096void AudioHardware::closeInputStream(AudioStreamIn* in) {
1097 Mutex::Autolock lock(mLock);
1098
Arne Coucheron0c85f772013-04-23 12:18:53 +02001099#ifdef WITH_QCOM_VOIP_OVER_MVS
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001100 ssize_t index = -1;
1101 if((index = mInputs.indexOf((AudioStreamInMSM72xx *)in)) >= 0) {
1102 ALOGV("closeInputStream AudioStreamInMSM72xx");
Arne Coucheron0c85f772013-04-23 12:18:53 +02001103#else
1104 ssize_t index = mInputs.indexOf((AudioStreamInMSM72xx *)in);
1105 if (index < 0) {
1106 ALOGW("Attempt to close invalid input stream");
1107 } else {
1108#endif
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001109 mLock.unlock();
1110 delete mInputs[index];
1111 mLock.lock();
1112 mInputs.removeAt(index);
Arne Coucheron0c85f772013-04-23 12:18:53 +02001113#ifdef WITH_QCOM_VOIP_OVER_MVS
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001114 } else if ((index = mVoipInputs.indexOf((AudioStreamInVoip *)in)) >= 0) {
1115 ALOGV("closeInputStream mVoipInputs");
1116 mLock.unlock();
1117 delete mVoipInputs[index];
1118 mLock.lock();
1119 mVoipInputs.removeAt(index);
1120 } else {
1121 ALOGE("Attempt to close invalid input stream");
Arne Coucheron0c85f772013-04-23 12:18:53 +02001122#endif
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001123 }
1124}
1125
1126status_t AudioHardware::setMode(int mode)
1127{
1128 status_t status = AudioHardwareBase::setMode(mode);
1129 if (status == NO_ERROR) {
1130 // make sure that doAudioRouteOrMute() is called by doRouting()
1131 // even if the new device selected is the same as current one.
1132 clearCurDevice();
1133 }
1134 return status;
1135}
1136
1137bool AudioHardware::checkOutputStandby()
1138{
1139 if (mOutput)
1140 if (!mOutput->checkStandby())
1141 return false;
1142
1143 return true;
1144}
1145
1146status_t AudioHardware::setMicMute(bool state)
1147{
1148 Mutex::Autolock lock(mLock);
1149 return setMicMute_nosync(state);
1150}
1151
1152// always call with mutex held
1153status_t AudioHardware::setMicMute_nosync(bool state)
1154{
1155 if (mMicMute != state) {
1156 mMicMute = state;
1157 ALOGD("setMicMute_nosync calling voice mute with the mMicMute %d", mMicMute);
Arne Coucheron0c85f772013-04-23 12:18:53 +02001158#ifdef WITH_QCOM_VOIPMUTE
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001159 if (isStreamOnAndActive(PCM_REC) && (mMode == AudioSystem::MODE_IN_COMMUNICATION)) {
1160 vMicMute = state;
1161 ALOGD("VOIP Active: vMicMute %d\n", vMicMute);
1162 msm_device_mute(DEV_ID(cur_tx), vMicMute);
1163 } else {
Arne Coucheron0c85f772013-04-23 12:18:53 +02001164#endif
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001165 ALOGD("setMicMute_nosync:voice_mute\n");
1166 msm_set_voice_tx_mute(mMicMute);
Arne Coucheron0c85f772013-04-23 12:18:53 +02001167#ifdef WITH_QCOM_VOIPMUTE
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001168 }
Arne Coucheron0c85f772013-04-23 12:18:53 +02001169#endif
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001170 }
1171 return NO_ERROR;
1172}
1173
1174status_t AudioHardware::getMicMute(bool* state)
1175{
1176 *state = mMicMute;
1177 return NO_ERROR;
1178}
1179
1180status_t AudioHardware::setParameters(const String8& keyValuePairs)
1181{
1182 AudioParameter param = AudioParameter(keyValuePairs);
1183 String8 value;
1184 String8 key;
1185 const char BT_NREC_KEY[] = "bt_headset_nrec";
1186 const char BT_NAME_KEY[] = "bt_headset_name";
1187 const char BT_NREC_VALUE_ON[] = "on";
Arne Coucheron0c85f772013-04-23 12:18:53 +02001188#ifdef QCOM_FM_ENABLED
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001189 const char FM_NAME_KEY[] = "FMRadioOn";
1190 const char FM_VALUE_HANDSET[] = "handset";
1191 const char FM_VALUE_SPEAKER[] = "speaker";
1192 const char FM_VALUE_HEADSET[] = "headset";
1193 const char FM_VALUE_FALSE[] = "false";
Arne Coucheron0c85f772013-04-23 12:18:53 +02001194#endif
Michael Bestas14030ec2013-05-14 20:00:20 +03001195#ifdef HTC_AUDIO
Giulio Cervera548b3192013-04-20 07:44:26 +02001196 const char ACTIVE_AP[] = "active_ap";
1197 const char EFFECT_ENABLED[] = "sound_effect_enable";
Michael Bestas14030ec2013-05-14 20:00:20 +03001198#endif
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001199
1200 ALOGV("setParameters() %s", keyValuePairs.string());
1201
1202 if (keyValuePairs.length() == 0) return BAD_VALUE;
1203
1204 key = String8(BT_NREC_KEY);
1205 if (param.get(key, value) == NO_ERROR) {
1206 if (value == BT_NREC_VALUE_ON) {
1207 mBluetoothNrec = true;
1208 } else {
1209 mBluetoothNrec = false;
1210 ALOGI("Turning noise reduction and echo cancellation off for BT "
1211 "headset");
1212 }
1213 }
Giulio Cervera548b3192013-04-20 07:44:26 +02001214
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001215 key = String8(BTHEADSET_VGS);
1216 if (param.get(key, value) == NO_ERROR) {
1217 if (value == BT_NREC_VALUE_ON) {
1218 mBluetoothVGS = true;
1219 } else {
1220 mBluetoothVGS = false;
1221 }
1222 }
Giulio Cervera548b3192013-04-20 07:44:26 +02001223
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001224 key = String8(BT_NAME_KEY);
1225 if (param.get(key, value) == NO_ERROR) {
Michael Bestas14030ec2013-05-14 20:00:20 +03001226#ifdef HTC_AUDIO
Giulio Cervera548b3192013-04-20 07:44:26 +02001227 mBluetoothIdTx = 0;
1228 mBluetoothIdRx = 0;
1229 for (int i = 0; i < mNumBTEndpoints; i++) {
1230 if (!strcasecmp(value.string(), mBTEndpoints[i].name)) {
1231 mBluetoothIdTx = mBTEndpoints[i].tx;
1232 mBluetoothIdRx = mBTEndpoints[i].rx;
1233 ALOGD("Using custom acoustic parameters for %s", value.string());
1234 break;
1235 }
1236 }
1237 if (mBluetoothIdTx == 0) {
1238 ALOGD("Using default acoustic parameters "
1239 "(%s not in acoustic database)", value.string());
1240 }
Michael Bestas14030ec2013-05-14 20:00:20 +03001241#endif
Giulio Cervera548b3192013-04-20 07:44:26 +02001242 doRouting(NULL);
1243 }
1244
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001245 key = String8(DUALMIC_KEY);
1246 if (param.get(key, value) == NO_ERROR) {
1247 if (value == "true") {
1248 mDualMicEnabled = true;
1249 ALOGI("DualMike feature Enabled");
1250 } else {
1251 mDualMicEnabled = false;
1252 ALOGI("DualMike feature Disabled");
1253 }
1254 doRouting(NULL);
1255 }
1256
1257 key = String8(TTY_MODE_KEY);
1258 if (param.get(key, value) == NO_ERROR) {
Vineela Tummalapalli9a86b942013-02-13 15:00:03 +05301259 if (value == "full" || value == "tty_full") {
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001260 mTtyMode = TTY_FULL;
Vineela Tummalapalli9a86b942013-02-13 15:00:03 +05301261 } else if (value == "hco" || value == "tty_hco") {
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001262 mTtyMode = TTY_HCO;
Vineela Tummalapalli9a86b942013-02-13 15:00:03 +05301263 } else if (value == "vco" || value == "tty_vco") {
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001264 mTtyMode = TTY_VCO;
1265 } else {
1266 mTtyMode = TTY_OFF;
1267 }
1268 if(mMode != AudioSystem::MODE_IN_CALL){
1269 return NO_ERROR;
1270 }
1271 ALOGI("Changed TTY Mode=%s", value.string());
1272 if((mMode == AudioSystem::MODE_IN_CALL) &&
1273 (cur_rx == DEVICE_HEADSET_RX) &&
1274 (cur_tx == DEVICE_HEADSET_TX))
1275 doRouting(NULL);
1276 }
Giulio Cervera548b3192013-04-20 07:44:26 +02001277
Michael Bestas14030ec2013-05-14 20:00:20 +03001278#ifdef HTC_AUDIO
Giulio Cervera548b3192013-04-20 07:44:26 +02001279 key = String8(ACTIVE_AP);
1280 if (param.get(key, value) == NO_ERROR) {
1281 const char* active_ap = value.string();
1282 ALOGD("Active AP = %s", active_ap);
1283 strcpy(mActiveAP, active_ap);
1284
1285 const char* dsp_effect = "\0";
1286 key = String8(DSP_EFFECT_KEY);
1287 if (param.get(key, value) == NO_ERROR) {
1288 ALOGD("DSP Effect = %s", value.string());
1289 dsp_effect = value.string();
1290 strcpy(mEffect, dsp_effect);
1291 }
1292
1293 key = String8(EFFECT_ENABLED);
1294 if (param.get(key, value) == NO_ERROR) {
1295 const char* sound_effect_enable = value.string();
1296 ALOGD("Sound Effect Enabled = %s", sound_effect_enable);
1297 if (value == "on") {
1298 mEffectEnabled = true;
1299 if (support_aic3254)
1300 aic3254_config(get_snd_dev());
1301 } else {
1302 strcpy(mEffect, "\0");
1303 mEffectEnabled = false;
1304 }
1305 }
1306 }
Michael Bestas14030ec2013-05-14 20:00:20 +03001307#endif
Giulio Cervera548b3192013-04-20 07:44:26 +02001308
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001309 return NO_ERROR;
1310}
1311
1312String8 AudioHardware::getParameters(const String8& keys)
1313{
1314 AudioParameter param = AudioParameter(keys);
1315 String8 value;
1316
1317 String8 key = String8(DUALMIC_KEY);
1318 if (param.get(key, value) == NO_ERROR) {
1319 value = String8(mDualMicEnabled ? "true" : "false");
1320 param.add(key, value);
1321 }
1322 key = String8(BTHEADSET_VGS);
1323 if (param.get(key, value) == NO_ERROR) {
1324 if(mBluetoothVGS)
1325 param.addInt(String8("isVGS"), true);
1326 }
Arne Coucheron0c85f772013-04-23 12:18:53 +02001327#ifdef WITH_QCOM_SPEECH
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001328 key = String8("tunneled-input-formats");
1329 if ( param.get(key,value) == NO_ERROR ) {
1330 param.addInt(String8("AMR"), true );
1331 if (build_id[17] != '1') {
1332 param.addInt(String8("EVRC"), true );
1333 param.addInt(String8("QCELP"), true );
1334 }
1335 }
Arne Coucheron0c85f772013-04-23 12:18:53 +02001336#endif
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001337
Arne Coucheron0c85f772013-04-23 12:18:53 +02001338#ifdef QCOM_FM_ENABLED
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001339 key = String8("Fm-radio");
1340 if ( param.get(key,value) == NO_ERROR ) {
1341 if ( getNodeByStreamType(FM_RADIO) ) {
1342 param.addInt(String8("isFMON"), true );
1343 }
1344 }
Arne Coucheron0c85f772013-04-23 12:18:53 +02001345#endif
Giulio Cervera548b3192013-04-20 07:44:26 +02001346
Michael Bestas14030ec2013-05-14 20:00:20 +03001347#ifdef HTC_AUDIO
Giulio Cervera548b3192013-04-20 07:44:26 +02001348 key = String8(DSP_EFFECT_KEY);
1349 if (param.get(key, value) == NO_ERROR) {
1350 value = String8(mCurDspProfile);
1351 param.add(key, value);
1352 }
Michael Bestas14030ec2013-05-14 20:00:20 +03001353#endif
Giulio Cervera548b3192013-04-20 07:44:26 +02001354
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001355 ALOGV("AudioHardware::getParameters() %s", param.toString().string());
1356 return param.toString();
1357}
1358
1359
1360static unsigned calculate_audpre_table_index(unsigned index)
1361{
1362 switch (index) {
1363 case 48000: return SAMP_RATE_INDX_48000;
1364 case 44100: return SAMP_RATE_INDX_44100;
1365 case 32000: return SAMP_RATE_INDX_32000;
1366 case 24000: return SAMP_RATE_INDX_24000;
1367 case 22050: return SAMP_RATE_INDX_22050;
1368 case 16000: return SAMP_RATE_INDX_16000;
1369 case 12000: return SAMP_RATE_INDX_12000;
1370 case 11025: return SAMP_RATE_INDX_11025;
1371 case 8000: return SAMP_RATE_INDX_8000;
1372 default: return -1;
1373 }
1374}
1375size_t AudioHardware::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
1376{
1377 if ((format != AudioSystem::PCM_16_BIT) &&
Arne Coucheron0c85f772013-04-23 12:18:53 +02001378#ifdef WITH_QCOM_SPEECH
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001379 (format != AudioSystem::AMR_NB) &&
1380 (format != AudioSystem::EVRC) &&
1381 (format != AudioSystem::QCELP) &&
Arne Coucheron0c85f772013-04-23 12:18:53 +02001382#endif
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001383 (format != AudioSystem::AAC)){
1384 ALOGW("getInputBufferSize bad format: %d", format);
1385 return 0;
1386 }
1387 if (channelCount < 1 || channelCount > 2) {
1388 ALOGW("getInputBufferSize bad channel count: %d", channelCount);
1389 return 0;
1390 }
1391
Arne Coucheron0c85f772013-04-23 12:18:53 +02001392 if (format == AudioSystem::AAC)
1393 return 2048;
1394#ifdef WITH_QCOM_SPEECH
1395 else if (format == AudioSystem::AMR_NB)
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001396 return 320*channelCount;
Arne Coucheron0c85f772013-04-23 12:18:53 +02001397 else if (format == AudioSystem::EVRC)
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001398 return 230*channelCount;
1399 else if (format == AudioSystem::QCELP)
1400 return 350*channelCount;
Arne Coucheron0c85f772013-04-23 12:18:53 +02001401#endif
1402#ifdef WITH_QCOM_VOIP_OVER_MVS
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001403 else if (sampleRate == AUDIO_HW_VOIP_SAMPLERATE_8K)
1404 return 320*channelCount;
1405 else if (sampleRate == AUDIO_HW_VOIP_SAMPLERATE_16K)
1406 return 640*channelCount;
Arne Coucheron0c85f772013-04-23 12:18:53 +02001407#endif
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001408 else
1409 {
1410 if (build_id[17] == '1') {
1411 /*
1412 Return pcm record buffer size based on the sampling rate:
1413 If sampling rate >= 44.1 Khz, use 512 samples/channel pcm recording and
1414 If sampling rate < 44.1 Khz, use 256 samples/channel pcm recording
1415 */
1416 if(sampleRate>=44100)
1417 return 1024*channelCount;
1418 else
1419 return 512*channelCount;
1420 }
1421 else {
1422 return 2048*channelCount;
1423 }
1424 }
1425}
1426static status_t set_volume_rpc(uint32_t device,
1427 uint32_t method,
1428 uint32_t volume)
1429{
1430 ALOGV("set_volume_rpc(%d, %d, %d)\n", device, method, volume);
1431
1432 if (device == -1UL) return NO_ERROR;
1433 return NO_ERROR;
1434}
1435
1436status_t AudioHardware::setVoiceVolume(float v)
1437{
1438 if (v < 0.0) {
1439 ALOGW("setVoiceVolume(%f) under 0.0, assuming 0.0\n", v);
1440 v = 0.0;
1441 } else if (v > 1.0) {
1442 ALOGW("setVoiceVolume(%f) over 1.0, assuming 1.0\n", v);
1443 v = 1.0;
1444 }
1445
Giulio Cerveraf0ec98d2013-04-21 05:01:48 +02001446 mVoiceVolume = v;
1447
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001448 int vol = lrint(v * 100.0);
1449 ALOGD("setVoiceVolume(%f)\n", v);
1450 ALOGI("Setting in-call volume to %d (available range is 0 to 100)\n", vol);
1451
1452 if(msm_set_voice_rx_vol(vol)) {
1453 ALOGE("msm_set_voice_rx_vol(%d) failed errno = %d",vol,errno);
1454 return -1;
1455 }
1456 ALOGV("msm_set_voice_rx_vol(%d) succeeded",vol);
Giulio Cervera548b3192013-04-20 07:44:26 +02001457
Michael Bestas14030ec2013-05-14 20:00:20 +03001458#ifdef HTC_AUDIO
Giulio Cervera548b3192013-04-20 07:44:26 +02001459 if (mMode == AudioSystem::MODE_IN_CALL &&
1460 mCurSndDevice != SND_DEVICE_BT &&
1461 mCurSndDevice != SND_DEVICE_CARKIT &&
Michael Bestas14030ec2013-05-14 20:00:20 +03001462 mCurSndDevice != SND_DEVICE_BT_EC_OFF)
Giulio Cervera548b3192013-04-20 07:44:26 +02001463 {
1464 uint32_t new_tx_acdb = getACDB(MOD_TX, mCurSndDevice);
1465 uint32_t new_rx_acdb = getACDB(MOD_RX, mCurSndDevice);
1466
1467 int (*update_voice_acdb)(uint32_t, uint32_t);
1468
1469 update_voice_acdb = (int (*)(uint32_t, uint32_t))::dlsym(acoustic, "update_voice_acdb");
1470 if ((*update_voice_acdb) == 0 ) {
1471 ALOGE("Could not open update_voice_acdb()");
1472 }
1473
1474 int rc = update_voice_acdb(new_tx_acdb, new_rx_acdb);
1475 if (rc < 0)
1476 ALOGE("Could not set update_voice_acdb: %d", rc);
1477 else
1478 ALOGI("update_voice_acdb(%d, %d) succeeded", new_tx_acdb, new_rx_acdb);
1479 }
Michael Bestas14030ec2013-05-14 20:00:20 +03001480#endif
Giulio Cervera548b3192013-04-20 07:44:26 +02001481
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001482 return NO_ERROR;
1483}
1484#ifdef QCOM_FM_ENABLED
1485status_t AudioHardware::setFmVolume(float v)
1486{
1487 int vol = android::AudioSystem::logToLinear( v );
1488 if ( vol > 100 ) {
1489 vol = 100;
1490 }
1491 else if ( vol < 0 ) {
1492 vol = 0;
1493 }
1494 ALOGV("setFmVolume(%f)\n", v);
1495 Routing_table* temp = NULL;
1496 temp = getNodeByStreamType(FM_RADIO);
1497 if(temp == NULL){
1498 ALOGV("No Active FM stream is running");
1499 return NO_ERROR;
1500 }
1501 if(msm_set_volume(temp->dec_id, vol)) {
1502 ALOGE("msm_set_volume(%d) failed for FM errno = %d",vol,errno);
1503 return -1;
1504 }
1505 ALOGV("msm_set_volume(%d) for FM succeeded",vol);
1506 return NO_ERROR;
1507}
1508#endif
1509
1510status_t AudioHardware::setMasterVolume(float v)
1511{
1512 Mutex::Autolock lock(mLock);
1513 int vol = ceil(v * 7.0);
1514 ALOGI("Set master volume to %d.\n", vol);
1515
1516 set_volume_rpc(SND_DEVICE_HANDSET, SND_METHOD_VOICE, vol);
1517 set_volume_rpc(SND_DEVICE_SPEAKER, SND_METHOD_VOICE, vol);
1518 set_volume_rpc(SND_DEVICE_BT, SND_METHOD_VOICE, vol);
1519 set_volume_rpc(SND_DEVICE_HEADSET, SND_METHOD_VOICE, vol);
1520 //TBD - does HDMI require this handling
1521
1522 // We return an error code here to let the audioflinger do in-software
1523 // volume on top of the maximum volume that we set through the SND API.
1524 // return error - software mixer will handle it
1525 return -1;
1526}
1527
Michael Bestas14030ec2013-05-14 20:00:20 +03001528#ifdef HTC_AUDIO
Giulio Cervera548b3192013-04-20 07:44:26 +02001529status_t get_batt_temp(int *batt_temp) {
1530 ALOGD("Enable ALT for speaker");
1531
1532 int i, fd, len;
1533 char get_batt_temp[6] = { 0 };
1534 const char *fn[] = {
1535 "/sys/devices/platform/rs30100001:00000000.0/power_supply/battery/batt_temp",
1536 "/sys/devices/platform/rs30100001:00000000/power_supply/battery/batt_temp" };
1537
1538 for (i = 0; i < 2; i++) {
1539 if ((fd = open(fn[i], O_RDONLY)) >= 0)
1540 break;
1541 }
1542 if (fd <= 0) {
1543 ALOGE("Couldn't open sysfs file batt_temp");
1544 return UNKNOWN_ERROR;
1545 }
1546
1547 if ((len = read(fd, get_batt_temp, sizeof(get_batt_temp))) <= 1) {
1548 ALOGE("read battery temp fail: %s", strerror(errno));
1549 close(fd);
1550 return BAD_VALUE;
1551 }
1552
1553 *batt_temp = strtol(get_batt_temp, NULL, 10);
1554 ALOGD("ALT batt_temp = %d", *batt_temp);
1555
1556 close(fd);
1557 return NO_ERROR;
1558}
1559
1560status_t do_tpa2051_control(int mode)
1561{
1562 int fd, rc;
1563 int tpa_mode = 0;
1564 int batt_temp = 0;
1565
1566 if (mode) {
1567 if (cur_rx == DEVICE_HEADSET_RX)
1568 tpa_mode = TPA2051_MODE_VOICECALL_HEADSET;
1569 else if (cur_rx == DEVICE_SPEAKER_RX)
1570 tpa_mode = TPA2051_MODE_VOICECALL_SPKR;
1571 } else {
1572 switch (cur_rx) {
1573 case DEVICE_FMRADIO_HEADSET_RX:
1574 tpa_mode = TPA2051_MODE_FM_HEADSET;
1575 break;
1576 case DEVICE_FMRADIO_SPEAKER_RX:
1577 tpa_mode = TPA2051_MODE_FM_SPKR;
1578 break;
1579 case DEVICE_SPEAKER_HEADSET_RX:
1580 tpa_mode = TPA2051_MODE_RING;
1581 break;
1582 case DEVICE_HEADSET_RX:
1583 tpa_mode = TPA2051_MODE_PLAYBACK_HEADSET;
1584 break;
1585 case DEVICE_SPEAKER_RX:
1586 tpa_mode = TPA2051_MODE_PLAYBACK_SPKR;
1587 break;
1588 default:
1589 break;
1590 }
1591 }
1592
1593 fd = open("/dev/tpa2051d3", O_RDWR);
1594 if (fd < 0) {
1595 ALOGE("can't open /dev/tpa2051d3 %d", fd);
1596 return -1;
1597 }
1598
1599 if (tpa_mode != cur_tpa_mode) {
1600 cur_tpa_mode = tpa_mode;
1601 rc = ioctl(fd, TPA2051_SET_MODE, &tpa_mode);
1602 if (rc < 0)
1603 ALOGE("ioctl TPA2051_SET_MODE failed: %s", strerror(errno));
1604 else
1605 ALOGD("update TPA2051_SET_MODE to mode %d success", tpa_mode);
1606 }
1607
1608 if (alt_enable && cur_rx == DEVICE_SPEAKER_RX) {
1609 if (get_batt_temp(&batt_temp) == NO_ERROR) {
1610 if (batt_temp < 50) {
1611 tpa_mode = 629276672;
1612 rc = ioctl(fd, TPA2051_SET_CONFIG, &tpa_mode);
1613 if (rc < 0)
1614 ALOGE("ioctl TPA2051_SET_CONFIG failed: %s", strerror(errno));
1615 else
1616 ALOGD("update TPA2051_SET_CONFIG to mode %d success", tpa_mode);
1617 }
1618 }
1619 }
1620
1621 close(fd);
1622 return 0;
1623}
1624
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001625static status_t do_route_audio_rpc(uint32_t device,
Giulio Cervera548b3192013-04-20 07:44:26 +02001626 bool ear_mute, bool mic_mute,
1627 uint32_t rx_acdb_id, uint32_t tx_acdb_id)
Michael Bestas14030ec2013-05-14 20:00:20 +03001628#else
1629static status_t do_route_audio_rpc(uint32_t device,
1630 bool ear_mute, bool mic_mute)
1631#endif
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001632{
1633 if(device == -1)
1634 return 0;
1635
1636 int new_rx_device = INVALID_DEVICE,new_tx_device = INVALID_DEVICE,fm_device = INVALID_DEVICE;
1637 Routing_table* temp = NULL;
1638 ALOGV("do_route_audio_rpc(%d, %d, %d)", device, ear_mute, mic_mute);
1639
1640 if(device == SND_DEVICE_HANDSET) {
1641 new_rx_device = DEVICE_HANDSET_RX;
1642 new_tx_device = DEVICE_HANDSET_TX;
1643 ALOGV("In HANDSET");
1644 }
1645 else if(device == SND_DEVICE_SPEAKER) {
1646 new_rx_device = DEVICE_SPEAKER_RX;
1647 new_tx_device = DEVICE_SPEAKER_TX;
1648 ALOGV("In SPEAKER");
1649 }
1650 else if(device == SND_DEVICE_HEADSET) {
1651 new_rx_device = DEVICE_HEADSET_RX;
1652 new_tx_device = DEVICE_HEADSET_TX;
1653 ALOGV("In HEADSET");
1654 }
1655 else if(device == SND_DEVICE_NO_MIC_HEADSET) {
1656 new_rx_device = DEVICE_HEADSET_RX;
1657 new_tx_device = DEVICE_HANDSET_TX;
1658 ALOGV("In NO MIC HEADSET");
1659 }
Arne Coucheron0c85f772013-04-23 12:18:53 +02001660#ifdef QCOM_FM_ENABLED
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001661 else if (device == SND_DEVICE_FM_HANDSET) {
1662 fm_device = DEVICE_FMRADIO_HANDSET_RX;
1663 ALOGV("In FM HANDSET");
1664 }
1665 else if(device == SND_DEVICE_FM_SPEAKER) {
1666 fm_device = DEVICE_FMRADIO_SPEAKER_RX;
1667 ALOGV("In FM SPEAKER");
1668 }
1669 else if(device == SND_DEVICE_FM_HEADSET) {
1670 fm_device = DEVICE_FMRADIO_HEADSET_RX;
1671 ALOGV("In FM HEADSET");
1672 }
Arne Coucheron0c85f772013-04-23 12:18:53 +02001673#endif
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001674 else if(device == SND_DEVICE_IN_S_SADC_OUT_HANDSET) {
1675 new_rx_device = DEVICE_HANDSET_RX;
1676 new_tx_device = DEVICE_DUALMIC_HANDSET_TX;
1677 ALOGV("In DUALMIC_HANDSET");
1678 }
1679 else if(device == SND_DEVICE_IN_S_SADC_OUT_SPEAKER_PHONE) {
1680 new_rx_device = DEVICE_SPEAKER_RX;
1681 new_tx_device = DEVICE_DUALMIC_SPEAKER_TX;
1682 ALOGV("In DUALMIC_SPEAKER");
1683 }
1684 else if(device == SND_DEVICE_TTY_FULL) {
1685 new_rx_device = DEVICE_TTY_HEADSET_MONO_RX;
1686 new_tx_device = DEVICE_TTY_HEADSET_MONO_TX;
1687 ALOGV("In TTY_FULL");
1688 }
1689 else if(device == SND_DEVICE_TTY_VCO) {
1690 new_rx_device = DEVICE_TTY_HEADSET_MONO_RX;
1691 new_tx_device = DEVICE_HANDSET_TX;
1692 ALOGV("In TTY_VCO");
1693 }
1694 else if(device == SND_DEVICE_TTY_HCO) {
1695 new_rx_device = DEVICE_HANDSET_RX;
1696 new_tx_device = DEVICE_TTY_HEADSET_MONO_TX;
1697 ALOGV("In TTY_HCO");
1698 }
Michael Bestas14030ec2013-05-14 20:00:20 +03001699#ifdef HTC_AUDIO
Giulio Cervera548b3192013-04-20 07:44:26 +02001700 else if((device == SND_DEVICE_BT) ||
1701 (device == SND_DEVICE_BT_EC_OFF)) {
Michael Bestas14030ec2013-05-14 20:00:20 +03001702#else
1703 else if(device == SND_DEVICE_BT) {
1704#endif
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001705 new_rx_device = DEVICE_BT_SCO_RX;
1706 new_tx_device = DEVICE_BT_SCO_TX;
1707 ALOGV("In BT_HCO");
1708 }
1709 else if(device == SND_DEVICE_HEADSET_AND_SPEAKER) {
1710 new_rx_device = DEVICE_SPEAKER_HEADSET_RX;
1711 new_tx_device = DEVICE_HEADSET_TX;
1712 ALOGV("In DEVICE_SPEAKER_HEADSET_RX and DEVICE_HEADSET_TX");
1713 }
1714 else if(device == SND_DEVICE_HEADPHONE_AND_SPEAKER) {
1715 new_rx_device = DEVICE_SPEAKER_HEADSET_RX;
1716 new_tx_device = DEVICE_HANDSET_TX;
1717 ALOGV("In DEVICE_SPEAKER_HEADSET_RX and DEVICE_HANDSET_TX");
1718 }
1719 else if (device == SND_DEVICE_HDMI) {
1720 new_rx_device = DEVICE_HDMI_STERO_RX;
1721 new_tx_device = cur_tx;
1722 ALOGV("In DEVICE_HDMI_STERO_RX and cur_tx");
Arne Coucheron0c85f772013-04-23 12:18:53 +02001723 }
1724#ifdef QCOM_FM_ENABLED
1725 else if (device == SND_DEVICE_FM_TX) {
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001726 new_rx_device = DEVICE_FMRADIO_STEREO_RX;
1727 new_tx_device = cur_tx;
1728 ALOGV("In DEVICE_FMRADIO_STEREO_RX and cur_tx");
1729 }
Arne Coucheron0c85f772013-04-23 12:18:53 +02001730#endif
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001731#ifdef SAMSUNG_AUDIO
1732 else if (device == SND_DEVICE_VOIP_HANDSET) {
1733 new_rx_device = DEVICE_HANDSET_VOIP_RX;
1734 new_tx_device = DEVICE_HANDSET_VOIP_TX;
1735 ALOGV("In VOIP HANDSET");
1736 }
1737 else if (device == SND_DEVICE_VOIP_SPEAKER) {
1738 new_rx_device = DEVICE_SPEAKER_VOIP_RX;
1739 new_tx_device = DEVICE_SPEAKER_VOIP_TX;
1740 ALOGV("In VOIP SPEAKER");
1741 }
1742 else if (device == SND_DEVICE_VOIP_HEADSET) {
1743 new_rx_device = DEVICE_HEADSET_VOIP_RX;
1744 new_tx_device = DEVICE_HEADSET_VOIP_TX;
1745 ALOGV("In VOIP HEADSET");
1746 }
1747 else if (device == SND_DEVICE_CALL_HANDSET) {
1748 new_rx_device = DEVICE_HANDSET_CALL_RX;
1749 new_tx_device = DEVICE_HANDSET_CALL_TX;
1750 ALOGV("In CALL HANDSET");
1751 }
1752 else if (device == SND_DEVICE_CALL_SPEAKER) {
1753 new_rx_device = DEVICE_SPEAKER_CALL_RX;
1754 new_tx_device = DEVICE_SPEAKER_CALL_TX;
1755 ALOGV("In CALL SPEAKER");
1756 }
1757 else if (device == SND_DEVICE_CALL_HEADSET) {
1758 new_rx_device = DEVICE_HEADSET_CALL_RX;
1759 new_tx_device = DEVICE_HEADSET_CALL_TX;
1760 ALOGV("In CALL HEADSET");
1761 }
1762#endif
1763
1764 if(new_rx_device != INVALID_DEVICE)
1765 ALOGD("new_rx = %d", DEV_ID(new_rx_device));
1766 if(new_tx_device != INVALID_DEVICE)
1767 ALOGD("new_tx = %d", DEV_ID(new_tx_device));
1768
1769 if (ear_mute == false && !isStreamOn(VOICE_CALL)) {
1770 ALOGV("Going to enable RX/TX device for voice stream");
1771 // Routing Voice
1772 if ( (new_rx_device != INVALID_DEVICE) && (new_tx_device != INVALID_DEVICE))
1773 {
1774 ALOGD("Starting voice on Rx %d and Tx %d device", DEV_ID(new_rx_device), DEV_ID(new_tx_device));
Giulio Cervera548b3192013-04-20 07:44:26 +02001775
Michael Bestas14030ec2013-05-14 20:00:20 +03001776#ifdef HTC_AUDIO
1777 updateACDB(new_rx_device, new_tx_device, rx_acdb_id, tx_acdb_id);
1778#endif
Giulio Cervera548b3192013-04-20 07:44:26 +02001779
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001780 msm_route_voice(DEV_ID(new_rx_device),DEV_ID(new_tx_device), 1);
1781 }
1782 else
1783 {
1784 return -1;
1785 }
1786
1787 if(cur_rx == INVALID_DEVICE || new_rx_device == INVALID_DEVICE)
1788 return -1;
1789
1790 if(cur_tx == INVALID_DEVICE || new_tx_device == INVALID_DEVICE)
1791 return -1;
1792
1793 //Enable RX device
1794 if(new_rx_device != cur_rx) {
1795 enableDevice(cur_rx,0);
1796 }
1797 enableDevice(new_rx_device,1);
1798
1799 //Enable TX device
1800 if(new_tx_device != cur_tx) {
1801 enableDevice(cur_tx,0);
1802 }
1803 enableDevice(new_tx_device,1);
1804
1805 // start Voice call
1806 ALOGD("Starting voice call and UnMuting the call");
1807 msm_start_voice();
1808 msm_set_voice_tx_mute(0);
1809 cur_rx = new_rx_device;
1810 cur_tx = new_tx_device;
1811 addToTable(0,cur_rx,cur_tx,VOICE_CALL,true);
Michael Bestas14030ec2013-05-14 20:00:20 +03001812#ifdef HTC_AUDIO
Giulio Cervera548b3192013-04-20 07:44:26 +02001813 updateDeviceInfo(new_rx_device,new_tx_device, rx_acdb_id, tx_acdb_id);
Michael Bestas14030ec2013-05-14 20:00:20 +03001814#else
1815 updateDeviceInfo(new_rx_device,new_tx_device);
1816#endif
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001817 }
1818 else if (ear_mute == true && isStreamOnAndActive(VOICE_CALL)) {
1819 ALOGV("Going to disable RX/TX device during end of voice call");
1820 temp = getNodeByStreamType(VOICE_CALL);
1821 if(temp == NULL)
1822 return 0;
1823
1824 // Ending voice call
1825 ALOGD("Ending Voice call");
1826 msm_end_voice();
1827 deleteFromTable(VOICE_CALL);
Michael Bestas14030ec2013-05-14 20:00:20 +03001828#ifdef HTC_AUDIO
Giulio Cervera548b3192013-04-20 07:44:26 +02001829 updateDeviceInfo(new_rx_device,new_tx_device, 0, 0);
Michael Bestas14030ec2013-05-14 20:00:20 +03001830#else
1831 updateDeviceInfo(new_rx_device,new_tx_device);
1832#endif
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001833 if(new_rx_device != INVALID_DEVICE && new_tx_device != INVALID_DEVICE) {
1834 cur_rx = new_rx_device;
1835 cur_tx = new_tx_device;
1836 }
1837 }
1838 else {
Michael Bestas14030ec2013-05-14 20:00:20 +03001839#ifdef HTC_AUDIO
Giulio Cervera548b3192013-04-20 07:44:26 +02001840 updateDeviceInfo(new_rx_device,new_tx_device, rx_acdb_id, tx_acdb_id);
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001841 }
Giulio Cervera548b3192013-04-20 07:44:26 +02001842
1843 if (support_tpa2051)
1844 do_tpa2051_control(ear_mute ^1);
Michael Bestas14030ec2013-05-14 20:00:20 +03001845#else
1846 updateDeviceInfo(new_rx_device,new_tx_device);
1847 }
1848#endif
Giulio Cervera548b3192013-04-20 07:44:26 +02001849
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001850 return NO_ERROR;
1851}
1852
Michael Bestas14030ec2013-05-14 20:00:20 +03001853#ifdef HTC_AUDIO
Giulio Cerveraf0ec98d2013-04-21 05:01:48 +02001854status_t AudioHardware::doAudioRouteOrMuteHTC(uint32_t device)
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001855{
Giulio Cervera548b3192013-04-20 07:44:26 +02001856 uint32_t rx_acdb_id = 0;
1857 uint32_t tx_acdb_id = 0;
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001858
Giulio Cervera548b3192013-04-20 07:44:26 +02001859 if (device == SND_DEVICE_BT) {
1860 if (!mBluetoothNrec)
1861 device = SND_DEVICE_BT_EC_OFF;
1862 }
1863
1864 if (support_aic3254) {
1865 aic3254_config(device);
1866 do_aic3254_control(device);
1867 }
1868
1869 if (device == SND_DEVICE_BT) {
1870 if (mBluetoothIdTx != 0) {
1871 rx_acdb_id = mBluetoothIdRx;
1872 tx_acdb_id = mBluetoothIdTx;
1873 } else {
1874 /* use default BT entry defined in AudioBTID.csv */
1875 rx_acdb_id = mBTEndpoints[0].rx;
1876 tx_acdb_id = mBTEndpoints[0].tx;
1877 ALOGD("Update ACDB ID to default BT setting");
1878 }
1879 } else if (device == SND_DEVICE_CARKIT ||
1880 device == SND_DEVICE_BT_EC_OFF) {
1881 if (mBluetoothIdTx != 0) {
1882 rx_acdb_id = mBluetoothIdRx;
1883 tx_acdb_id = mBluetoothIdTx;
1884 } else {
1885 /* use default carkit entry defined in AudioBTID.csv */
1886 rx_acdb_id = mBTEndpoints[1].rx;
1887 tx_acdb_id = mBTEndpoints[1].tx;
1888 ALOGD("Update ACDB ID to default carkit setting");
1889 }
Giulio Cerveraf0ec98d2013-04-21 05:01:48 +02001890 } else if (isInCall() && hac_enable && mHACSetting &&
Giulio Cervera548b3192013-04-20 07:44:26 +02001891 device == SND_DEVICE_HANDSET) {
1892 ALOGD("Update acdb id to hac profile.");
1893 rx_acdb_id = ACDB_ID_HAC_HANDSET_SPKR;
Arne Coucheron0c85f772013-04-23 12:18:53 +02001894 tx_acdb_id = ACDB_ID_HAC_HANDSET_MIC;
Giulio Cervera548b3192013-04-20 07:44:26 +02001895 } else {
Giulio Cerveraf0ec98d2013-04-21 05:01:48 +02001896 if (isInCall()) {
Giulio Cervera548b3192013-04-20 07:44:26 +02001897 rx_acdb_id = getACDB(MOD_RX, device);
1898 tx_acdb_id = getACDB(MOD_TX, device);
1899 } else {
1900 if (!checkOutputStandby())
1901 rx_acdb_id = getACDB(MOD_PLAY, device);
1902
1903 if (mRecordState)
1904 tx_acdb_id = getACDB(MOD_REC, device);
1905 }
1906 }
1907
Arne Coucheron0c85f772013-04-23 12:18:53 +02001908 ALOGV("doAudioRouteOrMuteHTC: rx acdb %d, tx acdb %d", rx_acdb_id, tx_acdb_id);
Giulio Cerveraf0ec98d2013-04-21 05:01:48 +02001909 ALOGV("doAudioRouteOrMuteHTC() device %x, mMode %d, mMicMute %d", device, mMode, mMicMute);
Arne Coucheron0c85f772013-04-23 12:18:53 +02001910#ifdef WITH_QCOM_VOIP_OVER_MVS
Daniel Hillenbrandd81f36f2013-04-06 18:56:57 +00001911 int earMute = (mMode != AudioSystem::MODE_IN_CALL) && (mMode != AudioSystem::MODE_IN_COMMUNICATION);
Giulio Cervera548b3192013-04-20 07:44:26 +02001912 return do_route_audio_rpc(device,earMute, mMicMute, rx_acdb_id, tx_acdb_id);
Arne Coucheron0c85f772013-04-23 12:18:53 +02001913#else
1914 return do_route_audio_rpc(device, !isInCall(), mMicMute, rx_acdb_id, tx_acdb_id);
1915#endif
Giulio Cervera548b3192013-04-20 07:44:26 +02001916}
Michael Bestas14030ec2013-05-14 20:00:20 +03001917#endif
Giulio Cervera548b3192013-04-20 07:44:26 +02001918
Giulio Cerveraf0ec98d2013-04-21 05:01:48 +02001919// always call with mutex held
1920status_t AudioHardware::doAudioRouteOrMute(uint32_t device)
1921{
1922// BT acoustics is not supported. This might be used by OEMs. Hence commenting
1923// the code and not removing it.
1924#if 0
1925 if (device == (uint32_t)SND_DEVICE_BT || device == (uint32_t)SND_DEVICE_CARKIT) {
1926 if (mBluetoothId) {
1927 device = mBluetoothId;
1928 } else if (!mBluetoothNrec) {
1929 device = SND_DEVICE_BT_EC_OFF;
1930 }
1931 }
1932#endif
1933
1934 status_t ret = NO_ERROR;
1935
Michael Bestas14030ec2013-05-14 20:00:20 +03001936#ifdef HTC_AUDIO
1937 ret = doAudioRouteOrMuteHTC(device);
Arne Coucheron0c85f772013-04-23 12:18:53 +02001938#else
Michael Bestas14030ec2013-05-14 20:00:20 +03001939 ALOGV("doAudioRouteOrMute() device %d, mMode %d, mMicMute %d", device, mMode, mMicMute);
1940#ifdef WITH_QCOM_VOIP_OVER_MVS
1941 int earMute = (mMode != AudioSystem::MODE_IN_CALL) && (mMode != AudioSystem::MODE_IN_COMMUNICATION);
1942 ret = do_route_audio_rpc(device, earMute, mMicMute);
1943#else
1944 ret = do_route_audio_rpc(device, !isInCall(), mMicMute);
Arne Coucheron0c85f772013-04-23 12:18:53 +02001945#endif
Michael Bestas14030ec2013-05-14 20:00:20 +03001946#endif
Giulio Cerveraf0ec98d2013-04-21 05:01:48 +02001947
1948 if (isStreamOnAndActive(VOICE_CALL) && mMicMute == false)
1949 msm_set_voice_tx_mute(0);
1950
1951 if (isInCall())
1952 setVoiceVolume(mVoiceVolume);
1953
1954 return ret;
1955}
1956
Michael Bestas14030ec2013-05-14 20:00:20 +03001957
1958#ifdef HTC_AUDIO
Giulio Cervera548b3192013-04-20 07:44:26 +02001959status_t AudioHardware::get_mMode(void) {
1960 return mMode;
1961}
1962
1963status_t AudioHardware::set_mRecordState(bool onoff) {
1964 mRecordState = onoff;
1965 return 0;
1966}
1967
1968status_t AudioHardware::get_mRecordState(void) {
1969 return mRecordState;
1970}
1971
1972status_t AudioHardware::get_snd_dev(void) {
1973 return mCurSndDevice;
1974}
1975
1976uint32_t AudioHardware::getACDB(int mode, uint32_t device) {
1977
Giulio Cervera548b3192013-04-20 07:44:26 +02001978 uint32_t acdb_id = 0;
1979 int batt_temp = 0;
Giulio Cerveraf0ec98d2013-04-21 05:01:48 +02001980 int vol = lrint(mVoiceVolume * 100.0);
Giulio Cervera548b3192013-04-20 07:44:26 +02001981
1982 if (mMode == AudioSystem::MODE_IN_CALL &&
1983 device <= SND_DEVICE_NO_MIC_HEADSET) {
1984 if (mode == MOD_RX) {
1985 switch (device) {
1986 case SND_DEVICE_HANDSET:
Giulio Cerveraf0ec98d2013-04-21 05:01:48 +02001987 acdb_id = vol / 20 + 201;
Giulio Cervera548b3192013-04-20 07:44:26 +02001988 break;
1989 case SND_DEVICE_HEADSET:
1990 case SND_DEVICE_NO_MIC_HEADSET:
Giulio Cerveraf0ec98d2013-04-21 05:01:48 +02001991 acdb_id = vol / 20 + 401;
Giulio Cervera548b3192013-04-20 07:44:26 +02001992 break;
1993 case SND_DEVICE_SPEAKER:
Giulio Cerveraf0ec98d2013-04-21 05:01:48 +02001994 acdb_id = vol / 20 + 601;
Giulio Cervera548b3192013-04-20 07:44:26 +02001995 break;
1996 default:
1997 break;
1998 }
1999 } else if (mode == MOD_TX) {
2000 switch (device) {
2001 case SND_DEVICE_HANDSET:
Giulio Cerveraf0ec98d2013-04-21 05:01:48 +02002002 acdb_id = vol / 20 + 101;
Giulio Cervera548b3192013-04-20 07:44:26 +02002003 break;
2004 case SND_DEVICE_HEADSET:
2005 case SND_DEVICE_NO_MIC_HEADSET:
Giulio Cerveraf0ec98d2013-04-21 05:01:48 +02002006 acdb_id = vol / 20 + 301;
Giulio Cervera548b3192013-04-20 07:44:26 +02002007 break;
2008 case SND_DEVICE_SPEAKER:
Giulio Cerveraf0ec98d2013-04-21 05:01:48 +02002009 acdb_id = vol / 20 + 501;
Giulio Cervera548b3192013-04-20 07:44:26 +02002010 break;
2011 default:
2012 break;
2013 }
2014 }
2015 } else {
2016 if (mode == MOD_PLAY) {
2017 switch (device) {
2018 case SND_DEVICE_HEADSET:
2019 case SND_DEVICE_NO_MIC_HEADSET:
2020 case SND_DEVICE_NO_MIC_HEADSET_BACK_MIC:
2021 case SND_DEVICE_FM_HEADSET:
2022 acdb_id = ACDB_ID_HEADSET_PLAYBACK;
2023 break;
2024 case SND_DEVICE_SPEAKER:
2025 case SND_DEVICE_FM_SPEAKER:
2026 case SND_DEVICE_SPEAKER_BACK_MIC:
2027 acdb_id = ACDB_ID_SPKR_PLAYBACK;
2028 if (alt_enable) {
2029 if (get_batt_temp(&batt_temp) == NO_ERROR) {
2030 if (batt_temp < 50)
2031 acdb_id = ACDB_ID_ALT_SPKR_PLAYBACK;
2032 }
2033 }
2034 break;
2035 case SND_DEVICE_HEADSET_AND_SPEAKER:
2036 case SND_DEVICE_HEADSET_AND_SPEAKER_BACK_MIC:
2037 case SND_DEVICE_HEADPHONE_AND_SPEAKER:
2038 acdb_id = ACDB_ID_HEADSET_RINGTONE_PLAYBACK;
2039 break;
2040 default:
2041 break;
2042 }
2043 } else if (mode == MOD_REC) {
2044 switch (device) {
2045 case SND_DEVICE_HEADSET:
2046 case SND_DEVICE_FM_HEADSET:
2047 case SND_DEVICE_FM_SPEAKER:
2048 case SND_DEVICE_HEADSET_AND_SPEAKER:
2049 acdb_id = ACDB_ID_EXT_MIC_REC;
2050 break;
2051 case SND_DEVICE_HANDSET:
2052 case SND_DEVICE_NO_MIC_HEADSET:
2053 case SND_DEVICE_SPEAKER:
2054 acdb_id = ACDB_ID_INT_MIC_REC;
2055 break;
2056 case SND_DEVICE_SPEAKER_BACK_MIC:
2057 case SND_DEVICE_NO_MIC_HEADSET_BACK_MIC:
2058 case SND_DEVICE_HANDSET_BACK_MIC:
2059 case SND_DEVICE_HEADSET_AND_SPEAKER_BACK_MIC:
2060 acdb_id = ACDB_ID_CAMCORDER;
2061 break;
2062 default:
2063 break;
2064 }
2065 }
2066 }
2067 ALOGV("getACDB, return ID %d", acdb_id);
2068 return acdb_id;
2069}
2070
2071status_t AudioHardware::do_aic3254_control(uint32_t device) {
2072 ALOGD("do_aic3254_control device: %d mode: %d record: %d", device, mMode, mRecordState);
2073
2074 uint32_t new_aic_txmode = UPLINK_OFF;
2075 uint32_t new_aic_rxmode = DOWNLINK_OFF;
2076
2077 Mutex::Autolock lock(mAIC3254ConfigLock);
2078
2079 if (mMode == AudioSystem::MODE_IN_CALL) {
2080 switch (device ) {
2081 case SND_DEVICE_HEADSET:
2082 new_aic_rxmode = CALL_DOWNLINK_EMIC_HEADSET;
2083 new_aic_txmode = CALL_UPLINK_EMIC_HEADSET;
2084 break;
2085 case SND_DEVICE_SPEAKER:
2086 case SND_DEVICE_SPEAKER_BACK_MIC:
2087 new_aic_rxmode = CALL_DOWNLINK_IMIC_SPEAKER;
2088 new_aic_txmode = CALL_UPLINK_IMIC_SPEAKER;
2089 break;
2090 case SND_DEVICE_HEADSET_AND_SPEAKER:
2091 case SND_DEVICE_HEADSET_AND_SPEAKER_BACK_MIC:
2092 new_aic_rxmode = RING_HEADSET_SPEAKER;
2093 break;
2094 case SND_DEVICE_NO_MIC_HEADSET:
2095 case SND_DEVICE_NO_MIC_HEADSET_BACK_MIC:
2096 new_aic_rxmode = CALL_DOWNLINK_IMIC_HEADSET;
2097 new_aic_txmode = CALL_UPLINK_IMIC_HEADSET;
2098 break;
2099 case SND_DEVICE_HANDSET:
2100 case SND_DEVICE_HANDSET_BACK_MIC:
2101 new_aic_rxmode = CALL_DOWNLINK_IMIC_RECEIVER;
2102 new_aic_txmode = CALL_UPLINK_IMIC_RECEIVER;
2103 break;
2104 default:
2105 break;
2106 }
2107 } else {
2108 if (checkOutputStandby()) {
2109 if (device == SND_DEVICE_FM_HEADSET) {
2110 new_aic_rxmode = FM_OUT_HEADSET;
2111 new_aic_txmode = FM_IN_HEADSET;
2112 } else if (device == SND_DEVICE_FM_SPEAKER) {
2113 new_aic_rxmode = FM_OUT_SPEAKER;
2114 new_aic_txmode = FM_IN_SPEAKER;
2115 }
2116 } else {
2117 switch (device) {
2118 case SND_DEVICE_HEADSET_AND_SPEAKER:
2119 case SND_DEVICE_HEADSET_AND_SPEAKER_BACK_MIC:
2120 case SND_DEVICE_HEADPHONE_AND_SPEAKER:
2121 new_aic_rxmode = RING_HEADSET_SPEAKER;
2122 break;
2123 case SND_DEVICE_SPEAKER:
2124 case SND_DEVICE_SPEAKER_BACK_MIC:
2125 new_aic_rxmode = PLAYBACK_SPEAKER;
2126 break;
2127 case SND_DEVICE_HANDSET:
2128 case SND_DEVICE_HANDSET_BACK_MIC:
2129 new_aic_rxmode = PLAYBACK_RECEIVER;
2130 break;
2131 case SND_DEVICE_HEADSET:
2132 case SND_DEVICE_NO_MIC_HEADSET:
2133 case SND_DEVICE_NO_MIC_HEADSET_BACK_MIC:
2134 new_aic_rxmode = PLAYBACK_HEADSET;
2135 break;
2136 default:
2137 break;
2138 }
2139 }
2140
2141 if (mRecordState) {
2142 switch (device) {
2143 case SND_DEVICE_HEADSET:
2144 new_aic_txmode = VOICERECORD_EMIC;
2145 break;
2146 case SND_DEVICE_HANDSET_BACK_MIC:
2147 case SND_DEVICE_SPEAKER_BACK_MIC:
2148 case SND_DEVICE_NO_MIC_HEADSET_BACK_MIC:
2149 case SND_DEVICE_HEADSET_AND_SPEAKER_BACK_MIC:
2150 new_aic_txmode = VIDEORECORD_IMIC;
2151 break;
2152 case SND_DEVICE_HANDSET:
2153 case SND_DEVICE_SPEAKER:
2154 case SND_DEVICE_NO_MIC_HEADSET:
2155 case SND_DEVICE_HEADSET_AND_SPEAKER:
2156 new_aic_txmode = VOICERECORD_IMIC;
2157 break;
2158 default:
2159 break;
2160 }
2161 }
2162 }
2163 ALOGD("aic3254_ioctl: new_aic_rxmode %d cur_aic_rx %d", new_aic_rxmode, cur_aic_rx);
2164 if (new_aic_rxmode != cur_aic_rx)
2165 if (aic3254_ioctl(AIC3254_CONFIG_RX, new_aic_rxmode) >= 0)
2166 cur_aic_rx = new_aic_rxmode;
2167
2168 ALOGD("aic3254_ioctl: new_aic_txmode %d cur_aic_tx %d", new_aic_txmode, cur_aic_tx);
2169 if (new_aic_txmode != cur_aic_tx)
2170 if (aic3254_ioctl(AIC3254_CONFIG_TX, new_aic_txmode) >= 0)
2171 cur_aic_tx = new_aic_txmode;
2172
2173 if (cur_aic_tx