AudioHardware.cpp revision 17b4d724c2d8f3b70ae94ab523f584940d1c175a
12aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland/*
22aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland** Copyright 2008, Google Inc.
32aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland**
42aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland** Licensed under the Apache License, Version 2.0 (the "License");
52aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland** you may not use this file except in compliance with the License.
62aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland** You may obtain a copy of the License at
72aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland**
82aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland**     http://www.apache.org/licenses/LICENSE-2.0
92aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland**
102aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland** Unless required by applicable law or agreed to in writing, software
112aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland** distributed under the License is distributed on an "AS IS" BASIS,
122aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland** See the License for the specific language governing permissions and
142aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland** limitations under the License.
152aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland*/
162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#include <math.h>
182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland//#define LOG_NDEBUG 0
202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#define LOG_TAG "AudioHardwareQSD"
212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#include <utils/Log.h>
222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#include <utils/String8.h>
235d89308f2e1252eff2743bf823bf558dbb0de2faDave Sparks#include <hardware_legacy/power.h>
242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#include <stdio.h>
262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#include <unistd.h>
272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#include <sys/ioctl.h>
282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#include <sys/types.h>
292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#include <sys/stat.h>
302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#include <dlfcn.h>
312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#include <fcntl.h>
322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
33739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi#include <cutils/properties.h> // for property_get for the voice recognition mode switch
34739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi
352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland// hardware specific functions
362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#include "AudioHardware.h"
382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#include <media/AudioRecord.h>
392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandextern "C" {
412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#include "msm_audio.h"
429ab0b5b1f3244f261fcda2ead8fcdd5fe5d714b6Iliyan Malchev#include <linux/a1026.h>
43f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev#include <linux/tpa2018d1.h>
442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#define LOG_SND_RPC 0  // Set to 1 to log sound RPC's
472aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#define TX_PATH (1)
482aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_CURRENT = 256;
502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_HANDSET = 0;
512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_SPEAKER = 1;
522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_BT = 3;
532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_CARKIT = 4;
542aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_BT_EC_OFF = 45;
552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_HEADSET = 2;
562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_HEADSET_AND_SPEAKER = 10;
572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_FM_HEADSET = 9;
582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_FM_SPEAKER = 11;
592aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_NO_MIC_HEADSET = 8;
602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_TTY_FULL = 5;
6117b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurentstatic const uint32_t SND_DEVICE_TTY_VCO = 6;
6217b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurentstatic const uint32_t SND_DEVICE_TTY_HCO = 7;
63da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurentstatic const uint32_t SND_DEVICE_HANDSET_BACK_MIC = 20;
64da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurentstatic const uint32_t SND_DEVICE_SPEAKER_BACK_MIC = 21;
65da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurentstatic const uint32_t SND_DEVICE_NO_MIC_HEADSET_BACK_MIC = 28;
6658cf88a5a91d82ae2fb3e23365eaa4524a9cd089Jean-Michel Trivistatic const uint32_t SND_DEVICE_HEADSET_AND_SPEAKER_BACK_MIC = 30;
672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandnamespace android {
682aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic int support_a1026 = 1;
69f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchevstatic bool support_tpa2018d1 = true;
702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic int fd_a1026 = -1;
712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic int old_pathid = -1;
722aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic int new_pathid = -1;
730f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurentstatic int curr_out_device = -1;
740f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurentstatic int curr_mic_device = -1;
752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic int voice_started = 0;
762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic int fd_fm_device = -1;
7710254cc35f5cb7ebe2c7ef452815486cb8e92a33Jean-Michel Trivistatic int stream_volume = -300;
78739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi// use VR mode on inputs: 1 == VR mode enabled when selected, 0 = VR mode disabled when selected
7908516fe50b023532d5a3010050970de28e14621bIliyan Malchevstatic int vr_mode_enabled;
80739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivistatic bool vr_mode_change = false;
81739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivistatic int vr_uses_ns = 0;
82f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchevstatic int alt_enable = 0;
83f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchevstatic int hac_enable = 0;
849ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi// enable or disable 2-mic noise suppression in call on receiver mode
85739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivistatic int enable1026 = 1;
869ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi//FIXME add new settings in A1026 driver for an incall no ns mode, based on the current vr no ns
879ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi#define A1026_PATH_INCALL_NO_NS_RECEIVER A1026_PATH_VR_NO_NS_RECEIVER
8810254cc35f5cb7ebe2c7ef452815486cb8e92a33Jean-Michel Trivi
892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandint errCount = 0;
900f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurentstatic void * acoustic;
912aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandconst uint32_t AudioHardware::inputSamplingRates[] = {
922aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000
932aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland};
945d89308f2e1252eff2743bf823bf558dbb0de2faDave Sparks
955d89308f2e1252eff2743bf823bf558dbb0de2faDave Sparks// ID string for audio wakelock
965d89308f2e1252eff2743bf823bf558dbb0de2faDave Sparksstatic const char kOutputWakelockStr[] = "AudioHardwareQSD";
975d89308f2e1252eff2743bf823bf558dbb0de2faDave Sparks
982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland// ----------------------------------------------------------------------------
992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
1002aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandAudioHardware::AudioHardware() :
1010f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    mA1026Init(false), mInit(false), mMicMute(true),
102f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    mBluetoothNrec(true),
103f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    mHACSetting(false),
104f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    mBluetoothIdTx(0), mBluetoothIdRx(0),
105f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    mOutput(0),
1063964d4ed448b00791bc1b574913be24f44b45f0fEric Laurent    mNoiseSuppressionState(A1026_NS_STATE_AUTO),
10717b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent    mVoiceVolume(VOICE_VOLUME_MAX), mTTYMode(TTY_MODE_OFF)
1082aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
1090f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    int (*snd_get_num)();
1100f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    int (*snd_get_bt_endpoint)(msm_bt_endpoint *);
1110f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    int (*set_acoustic_parameters)();
112f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    int (*set_tpa2018d1_parameters)();
1130f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent
1140f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    struct msm_bt_endpoint *ept;
1150f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent
1162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    doA1026_init();
1170f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent
1180f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    acoustic =:: dlopen("/system/lib/libhtc_acoustic.so", RTLD_NOW);
1190f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    if (acoustic == NULL ) {
1200f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        LOGE("Could not open libhtc_acoustic.so");
1210f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        /* this is not really an error on non-htc devices... */
1220f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        mNumBTEndpoints = 0;
1230f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        mInit = true;
1240f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        return;
1250f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    }
1260f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    set_acoustic_parameters = (int (*)(void))::dlsym(acoustic, "set_acoustic_parameters");
1270f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    if ((*set_acoustic_parameters) == 0 ) {
1280f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        LOGE("Could not open set_acoustic_parameters()");
1290f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        return;
1300f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    }
1310f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent
132f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    set_tpa2018d1_parameters = (int (*)(void))::dlsym(acoustic, "set_tpa2018d1_parameters");
133f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    if ((*set_tpa2018d1_parameters) == 0) {
134f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        LOGI("set_tpa2018d1_parameters() not present");
135f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        support_tpa2018d1 = false;
136f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    }
137f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev
1380f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    int rc = set_acoustic_parameters();
1390f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    if (rc < 0) {
1400f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        LOGE("Could not set acoustic parameters to share memory: %d", rc);
1410f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    }
1420f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent
143f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    if (support_tpa2018d1) {
144f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev       rc = set_tpa2018d1_parameters();
145f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev       if (rc < 0) {
146f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev           support_tpa2018d1 = false;
147f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev           LOGE("speaker amplifier tpa2018 is not supported\n");
148f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev       }
149f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    }
150f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev
1510f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    snd_get_num = (int (*)(void))::dlsym(acoustic, "snd_get_num");
1520f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    if ((*snd_get_num) == 0 ) {
1530f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        LOGE("Could not open snd_get_num()");
1540f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    }
1550f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent
1560f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    mNumBTEndpoints = snd_get_num();
1570f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    LOGD("mNumBTEndpoints = %d", mNumBTEndpoints);
1580f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    mBTEndpoints = new msm_bt_endpoint[mNumBTEndpoints];
1590f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    mInit = true;
1600f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    LOGV("constructed %d SND endpoints)", mNumBTEndpoints);
1610f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    ept = mBTEndpoints;
1620f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    snd_get_bt_endpoint = (int (*)(msm_bt_endpoint *))::dlsym(acoustic, "snd_get_bt_endpoint");
1630f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    if ((*snd_get_bt_endpoint) == 0 ) {
1640f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        LOGE("Could not open snd_get_bt_endpoint()");
1650f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        return;
1660f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    }
1670f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    snd_get_bt_endpoint(mBTEndpoints);
1680f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent
1690f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    for (int i = 0; i < mNumBTEndpoints; i++) {
1700f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        LOGE("BT name %s (tx,rx)=(%d,%d)", mBTEndpoints[i].name, mBTEndpoints[i].tx, mBTEndpoints[i].rx);
1710f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    }
1720f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent
173d1dc8c30a969ec3539fc21b940789b2f23197756Eric Laurent    // reset voice mode in case media_server crashed and restarted while in call
174d1dc8c30a969ec3539fc21b940789b2f23197756Eric Laurent    int fd = open("/dev/msm_audio_ctl", O_RDWR);
175d1dc8c30a969ec3539fc21b940789b2f23197756Eric Laurent    if (fd >= 0) {
176d1dc8c30a969ec3539fc21b940789b2f23197756Eric Laurent        ioctl(fd, AUDIO_STOP_VOICE, NULL);
177d1dc8c30a969ec3539fc21b940789b2f23197756Eric Laurent        close(fd);
178d1dc8c30a969ec3539fc21b940789b2f23197756Eric Laurent    }
179d1dc8c30a969ec3539fc21b940789b2f23197756Eric Laurent
180739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    vr_mode_change = false;
18108516fe50b023532d5a3010050970de28e14621bIliyan Malchev    vr_mode_enabled = 0;
182739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    enable1026 = 1;
183739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    char value[PROPERTY_VALUE_MAX];
184739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    // Check the system property to enable or not the special recording modes
185739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    property_get("media.a1026.enableA1026", value, "1");
186739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    enable1026 = atoi(value);
187739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    LOGV("Enable mode selection for A1026 is %d", enable1026);
188739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    // Check the system property for which VR mode to use
189739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    property_get("media.a1026.nsForVoiceRec", value, "0");
190739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    vr_uses_ns = atoi(value);
191739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    LOGV("Using Noise Suppression for Voice Rec is %d", vr_uses_ns);
192739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi
193f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    // Check the system property for enable or not the ALT function
194f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    property_get("htc.audio.alt.enable", value, "0");
195f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    alt_enable = atoi(value);
196f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    LOGV("Enable ALT function: %d", alt_enable);
197f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev
198f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    // Check the system property for enable or not the HAC function
199f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    property_get("htc.audio.hac.enable", value, "0");
200f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    hac_enable = atoi(value);
201f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    LOGV("Enable HAC function: %d", hac_enable);
202f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev
2032aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mInit = true;
2042aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
2052aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2062aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandAudioHardware::~AudioHardware()
2072aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
2082aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    for (size_t index = 0; index < mInputs.size(); index++) {
2092aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        closeInputStream((AudioStreamIn*)mInputs[index]);
2102aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
2112aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mInputs.clear();
2122aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    closeOutputStream((AudioStreamOut*)mOutput);
2132aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mInit = false;
2142aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
2152aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::initCheck()
2172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
2182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return mInit ? NO_ERROR : NO_INIT;
2192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
2202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2212aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandAudioStreamOut* AudioHardware::openOutputStream(
2222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status)
2232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
2242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    { // scope for the lock
2252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        Mutex::Autolock lock(mLock);
2262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        // only one output stream allowed
2282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (mOutput) {
2292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            if (status) {
2302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                *status = INVALID_OPERATION;
2312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            }
2322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            return 0;
2332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
2342aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        // create new output stream
2362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        AudioStreamOutMSM72xx* out = new AudioStreamOutMSM72xx();
2372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        status_t lStatus = out->set(this, devices, format, channels, sampleRate);
2382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (status) {
2392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            *status = lStatus;
2402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
2412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (lStatus == NO_ERROR) {
2422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            mOutput = out;
2432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        } else {
2442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            delete out;
2452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
2462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
2472aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return mOutput;
2482aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
2492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandvoid AudioHardware::closeOutputStream(AudioStreamOut* out) {
2512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    Mutex::Autolock lock(mLock);
2522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mOutput == 0 || mOutput != out) {
2532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGW("Attempt to close invalid output stream");
2542aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
2552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    else {
2562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        delete mOutput;
2572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mOutput = 0;
2582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
2592aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
2602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2612aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandAudioStreamIn* AudioHardware::openInputStream(
2622aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status,
2632aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        AudioSystem::audio_in_acoustics acoustic_flags)
2642aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
2652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // check for valid input source
2662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (!AudioSystem::isInputDevice((AudioSystem::audio_devices)devices)) {
2672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return 0;
2682aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
2692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mLock.lock();
2712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2722aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    AudioStreamInMSM72xx* in = new AudioStreamInMSM72xx();
2732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    status_t lStatus = in->set(this, devices, format, channels, sampleRate, acoustic_flags);
2742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (status) {
2752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        *status = lStatus;
2762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
2772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (lStatus != NO_ERROR) {
2782aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mLock.unlock();
2792aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        delete in;
2802aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return 0;
2812aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
2822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mInputs.add(in);
2842aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mLock.unlock();
2852aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2862aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return in;
2872aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
2882aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandvoid AudioHardware::closeInputStream(AudioStreamIn* in) {
2902aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    Mutex::Autolock lock(mLock);
2912aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2922aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    ssize_t index = mInputs.indexOf((AudioStreamInMSM72xx *)in);
2932aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (index < 0) {
2942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGW("Attempt to close invalid input stream");
2952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else {
2962aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mLock.unlock();
2972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        delete mInputs[index];
2982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mLock.lock();
2992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mInputs.removeAt(index);
3002aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
3012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
3022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
3032aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::setMode(int mode)
3042aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
305739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    // VR mode is never used in a call and must be cleared when entering the IN_CALL mode
306739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    if (mode == AudioSystem::MODE_IN_CALL) {
30708516fe50b023532d5a3010050970de28e14621bIliyan Malchev        vr_mode_enabled = 0;
308739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    }
309739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi
310f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    if (support_tpa2018d1)
311f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        do_tpa2018_control(mode);
312f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev
3132aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    status_t status = AudioHardwareBase::setMode(mode);
3142aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (status == NO_ERROR) {
3152aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        // make sure that doAudioRouteOrMute() is called by doRouting()
3162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        // even if the new device selected is the same as current one.
3172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mCurSndDevice = -1;
3182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
3192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return status;
3202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
3212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
3222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandbool AudioHardware::checkOutputStandby()
3232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
3242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mOutput)
3252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (!mOutput->checkStandby())
3262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            return false;
3272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
3282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return true;
3292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
3303cb8864598e72c04859f410bb03f242cf3965dbeHK Chenstatic status_t set_mic_mute(bool _mute)
3312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
3323cb8864598e72c04859f410bb03f242cf3965dbeHK Chen    uint32_t mute = _mute;
3333cb8864598e72c04859f410bb03f242cf3965dbeHK Chen    int fd = -1;
3342aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    fd = open("/dev/msm_audio_ctl", O_RDWR);
3352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (fd < 0) {
3362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGE("Cannot open msm_audio_ctl device\n");
3372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return -1;
3382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
3392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGD("Setting mic mute to %d\n", mute);
3403cb8864598e72c04859f410bb03f242cf3965dbeHK Chen    if (ioctl(fd, AUDIO_SET_MUTE, &mute)) {
3412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGE("Cannot set mic mute on current device\n");
3422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        close(fd);
3432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return -1;
3442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
3452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    close(fd);
3462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
3472aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
3482aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
3492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::setMicMute(bool state)
3502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
3512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    Mutex::Autolock lock(mLock);
3522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return setMicMute_nosync(state);
3532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
3542aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
3552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland// always call with mutex held
3562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::setMicMute_nosync(bool state)
3572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
3582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mMicMute != state) {
3592aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mMicMute = state;
3602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return set_mic_mute(mMicMute); //always set current TX device
3612aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
3622aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
3632aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
3642aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
3652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::getMicMute(bool* state)
3662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
3672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    *state = mMicMute;
3682aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
3692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
3702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
3712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::setParameters(const String8& keyValuePairs)
3722aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
3732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    AudioParameter param = AudioParameter(keyValuePairs);
3742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    String8 value;
3752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    String8 key;
3762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    const char BT_NREC_KEY[] = "bt_headset_nrec";
3772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    const char BT_NAME_KEY[] = "bt_headset_name";
378f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    const char HAC_KEY[] = "HACSetting";
3792aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    const char BT_NREC_VALUE_ON[] = "on";
380f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    const char HAC_VALUE_ON[] = "ON";
3812aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
3822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
3832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("setParameters() %s", keyValuePairs.string());
3842aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
3852aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (keyValuePairs.length() == 0) return BAD_VALUE;
3862aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
387f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    if(hac_enable) {
388f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        key = String8(HAC_KEY);
389f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        if (param.get(key, value) == NO_ERROR) {
390f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            if (value == HAC_VALUE_ON) {
391f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev                mHACSetting = true;
392f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev                LOGD("Enable HAC");
393f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            } else {
394f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev                mHACSetting = false;
395f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev                LOGD("Disable HAC");
396f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            }
397f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        }
398f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    }
399f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev
4002aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    key = String8(BT_NREC_KEY);
4012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (param.get(key, value) == NO_ERROR) {
4022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (value == BT_NREC_VALUE_ON) {
4032aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            mBluetoothNrec = true;
4042aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        } else {
4052aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            mBluetoothNrec = false;
4062aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            LOGI("Turning noise reduction and echo cancellation off for BT "
4072aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                 "headset");
4082aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
4092aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
4102aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    key = String8(BT_NAME_KEY);
4112aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (param.get(key, value) == NO_ERROR) {
4120f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        mBluetoothIdTx = 0;
4130f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        mBluetoothIdRx = 0;
4140f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        for (int i = 0; i < mNumBTEndpoints; i++) {
4150f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            if (!strcasecmp(value.string(), mBTEndpoints[i].name)) {
4160f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                mBluetoothIdTx = mBTEndpoints[i].tx;
4170f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                mBluetoothIdRx = mBTEndpoints[i].rx;
4182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                LOGI("Using custom acoustic parameters for %s", value.string());
4192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                break;
4202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            }
4212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
4220f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        if (mBluetoothIdTx == 0) {
4232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            LOGI("Using default acoustic parameters "
4242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                 "(%s not in acoustic database)", value.string());
4252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
4260f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        doRouting(NULL);
4272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
428da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    key = String8("noise_suppression");
429da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    if (param.get(key, value) == NO_ERROR) {
430da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent        if (support_a1026 == 1) {
431da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            int noiseSuppressionState;
432da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            if (value == "off") {
433da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                noiseSuppressionState = A1026_NS_STATE_OFF;
434da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            } else if (value == "auto") {
435da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                noiseSuppressionState = A1026_NS_STATE_AUTO;
436da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            } else if (value == "far_talk") {
437da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                noiseSuppressionState = A1026_NS_STATE_FT;
438da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            } else if (value == "close_talk") {
439da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                noiseSuppressionState = A1026_NS_STATE_CT;
440da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            } else {
441da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                return BAD_VALUE;
442da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            }
443da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent
444da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            if (noiseSuppressionState != mNoiseSuppressionState) {
445da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                if (!mA1026Init) {
446da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                    LOGW("Audience A1026 not initialized.\n");
447da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                    return INVALID_OPERATION;
448da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                }
449da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent
450da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                if (fd_a1026 < 0) {
451da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                    fd_a1026 = open("/dev/audience_a1026", O_RDWR);
452da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                    if (fd_a1026 < 0) {
453da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                        LOGE("Cannot open audience_a1026 device (%d)\n", fd_a1026);
454da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                        return -1;
455da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                    }
456da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                }
457da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                LOGV("Setting noise suppression %s", value.string());
458da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                mA1026Lock.lock();
459da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                int rc = ioctl(fd_a1026, A1026_SET_NS_STATE, &noiseSuppressionState);
460da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                if (!rc) {
461da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                    mNoiseSuppressionState = noiseSuppressionState;
462da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                } else {
463da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                    LOGE("Failed to set noise suppression %s", value.string());
464da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                }
465da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                mA1026Lock.unlock();
466da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            }
467da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent        } else {
468da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            return INVALID_OPERATION;
469da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent        }
470da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent     }
471da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent
47217b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent    key = String8("tty_mode");
47317b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent    if (param.get(key, value) == NO_ERROR) {
47417b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent        int ttyMode;
47517b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent        if (value == "tty_off") {
47617b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent            ttyMode = TTY_MODE_OFF;
47717b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent        } else if (value == "tty_full") {
47817b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent            ttyMode = TTY_MODE_FULL;
47917b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent        } else if (value == "tty_vco") {
48017b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent            ttyMode = TTY_MODE_VCO;
48117b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent        } else if (value == "tty_hco") {
48217b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent            ttyMode = TTY_MODE_HCO;
48317b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent        } else {
48417b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent            return BAD_VALUE;
48517b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent        }
48617b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent
48717b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent        if (ttyMode != mTTYMode) {
48817b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent            LOGV("new tty mode %d", ttyMode);
48917b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent            mTTYMode = ttyMode;
49017b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent            doRouting(NULL);
49117b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent        }
49217b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent     }
49317b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent
4942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
4952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
4962aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
4972aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandString8 AudioHardware::getParameters(const String8& keys)
4982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
499da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    AudioParameter request = AudioParameter(keys);
500da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    AudioParameter reply = AudioParameter();
501da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    String8 value;
502da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    String8 key;
503da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent
504da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    LOGV("getParameters() %s", keys.string());
505da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent
506da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    key = "noise_suppression";
507da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    if (request.get(key, value) == NO_ERROR) {
508da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent        switch(mNoiseSuppressionState) {
509da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent        case A1026_NS_STATE_OFF:
510da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            value = "off";
511da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            break;
512da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent        case A1026_NS_STATE_AUTO:
513da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            value = "auto";
514da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            break;
515da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent        case A1026_NS_STATE_FT:
516da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            value = "far_talk";
517da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            break;
518da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent        case A1026_NS_STATE_CT:
519da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            value = "close_talk";
520da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            break;
521da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent        }
522da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent        reply.add(key, value);
523da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    }
524da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent
525da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    return reply.toString();
5262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
5272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
5282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
5292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic unsigned calculate_audpre_table_index(unsigned index)
5302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
5312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    switch (index) {
5322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        case 48000:    return SAMP_RATE_INDX_48000;
5332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        case 44100:    return SAMP_RATE_INDX_44100;
5342aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        case 32000:    return SAMP_RATE_INDX_32000;
5352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        case 24000:    return SAMP_RATE_INDX_24000;
5362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        case 22050:    return SAMP_RATE_INDX_22050;
5372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        case 16000:    return SAMP_RATE_INDX_16000;
5382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        case 12000:    return SAMP_RATE_INDX_12000;
5392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        case 11025:    return SAMP_RATE_INDX_11025;
5402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        case 8000:    return SAMP_RATE_INDX_8000;
5412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        default:     return -1;
5422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
5432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
5442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandsize_t AudioHardware::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
5452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
5462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (format != AudioSystem::PCM_16_BIT) {
5472aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGW("getInputBufferSize bad format: %d", format);
5482aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return 0;
5492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
5502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (channelCount < 1 || channelCount > 2) {
5512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGW("getInputBufferSize bad channel count: %d", channelCount);
5522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return 0;
5532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
5542aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
555a4fe0167c6cad83d88b3bc56efa1ffad85b345b5Eric Laurent    return AUDIO_KERNEL_PCM_IN_BUFFERSIZE*channelCount;
5562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
5572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
5582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic status_t set_volume_rpc(uint32_t volume)
5592aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
5602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    int fd = -1;
5612aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    fd = open("/dev/msm_audio_ctl", O_RDWR);
5622aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (fd < 0) {
5632aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGE("Cannot open msm_audio_ctl device\n");
5642aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return -1;
5652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
5662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    volume *= 20; //percentage
5672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGD("Setting in-call volume to %d\n", volume);
5682aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (ioctl(fd, AUDIO_SET_VOLUME, &volume)) {
5692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGW("Cannot set volume on current device\n");
5702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
5712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    close(fd);
5722aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
5732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
5742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
5752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::setVoiceVolume(float v)
5762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
5772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (v < 0.0) {
5782aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGW("setVoiceVolume(%f) under 0.0, assuming 0.0\n", v);
5792aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        v = 0.0;
5802aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else if (v > 1.0) {
5812aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGW("setVoiceVolume(%f) over 1.0, assuming 1.0\n", v);
5822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        v = 1.0;
5832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
5842aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
585f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    if (mHACSetting && hac_enable)
586f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        v = 1.0;
587f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev
5883964d4ed448b00791bc1b574913be24f44b45f0fEric Laurent    int vol = lrint(v * VOICE_VOLUME_MAX);
5892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGD("setVoiceVolume(%f)\n", v);
5903964d4ed448b00791bc1b574913be24f44b45f0fEric Laurent    LOGI("Setting in-call volume to %d (available range is 0 to %d)\n", vol, VOICE_VOLUME_MAX);
5912aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
5922aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    Mutex::Autolock lock(mLock);
5932aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    set_volume_rpc(vol); //always set current device
5943964d4ed448b00791bc1b574913be24f44b45f0fEric Laurent    mVoiceVolume = vol;
5952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
5962aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
5972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
5982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::setMasterVolume(float v)
5992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
6003964d4ed448b00791bc1b574913be24f44b45f0fEric Laurent    LOGI("Set master volume to %f.\n", v);
6012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // We return an error code here to let the audioflinger do in-software
6022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // volume on top of the maximum volume that we set through the SND API.
6032aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // return error - software mixer will handle it
6042aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return -1;
6052aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
6062aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
6077fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivistatic status_t do_route_audio_dev_ctrl(uint32_t device, bool inCall, uint32_t rx_acdb_id, uint32_t tx_acdb_id)
6082aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
6097fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    uint32_t out_device = 0, mic_device = 0;
6107fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    uint32_t path[2];
6112aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    int fd = 0;
6122aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
6132aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (device == SND_DEVICE_CURRENT)
6142aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        goto Incall;
6152aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
6162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // hack -- kernel needs to put these in include file
6172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGD("Switching audio device to ");
6182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (device == SND_DEVICE_HANDSET) {
6192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           out_device = HANDSET_SPKR;
6202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           mic_device = HANDSET_MIC;
6212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           LOGD("Handset");
6222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else if ((device  == SND_DEVICE_BT) || (device == SND_DEVICE_BT_EC_OFF)) {
6232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           out_device = BT_SCO_SPKR;
6242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           mic_device = BT_SCO_MIC;
6252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           LOGD("BT Headset");
626da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    } else if (device == SND_DEVICE_SPEAKER ||
627da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent               device == SND_DEVICE_SPEAKER_BACK_MIC) {
6282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           out_device = SPKR_PHONE_MONO;
6292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           mic_device = SPKR_PHONE_MIC;
6302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           LOGD("Speakerphone");
6312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else if (device == SND_DEVICE_HEADSET) {
6322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           out_device = HEADSET_SPKR_STEREO;
6332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           mic_device = HEADSET_MIC;
6342aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           LOGD("Stereo Headset");
6352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else if (device == SND_DEVICE_HEADSET_AND_SPEAKER) {
6362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           out_device = SPKR_PHONE_HEADSET_STEREO;
6372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           mic_device = HEADSET_MIC;
6382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           LOGD("Stereo Headset + Speaker");
63958cf88a5a91d82ae2fb3e23365eaa4524a9cd089Jean-Michel Trivi    } else if (device == SND_DEVICE_HEADSET_AND_SPEAKER_BACK_MIC) {
64058cf88a5a91d82ae2fb3e23365eaa4524a9cd089Jean-Michel Trivi           out_device = SPKR_PHONE_HEADSET_STEREO;
64158cf88a5a91d82ae2fb3e23365eaa4524a9cd089Jean-Michel Trivi           mic_device = SPKR_PHONE_MIC;
64258cf88a5a91d82ae2fb3e23365eaa4524a9cd089Jean-Michel Trivi           LOGD("Stereo Headset + Speaker and back mic");
6432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else if (device == SND_DEVICE_NO_MIC_HEADSET) {
6442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           out_device = HEADSET_SPKR_STEREO;
6452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           mic_device = HANDSET_MIC;
6462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           LOGD("No microphone Wired Headset");
647da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    } else if (device == SND_DEVICE_NO_MIC_HEADSET_BACK_MIC) {
648da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent           out_device = HEADSET_SPKR_STEREO;
649da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent           mic_device = SPKR_PHONE_MIC;
650da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent           LOGD("No microphone Wired Headset and back mic");
651da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    } else if (device == SND_DEVICE_HANDSET_BACK_MIC) {
652da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent           out_device = HANDSET_SPKR;
653da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent           mic_device = SPKR_PHONE_MIC;
654da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent           LOGD("Handset and back mic");
6552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else if (device == SND_DEVICE_FM_HEADSET) {
6562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           out_device = FM_HEADSET;
6572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           mic_device = HEADSET_MIC;
6582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           LOGD("Stereo FM headset");
6592aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else if (device == SND_DEVICE_FM_SPEAKER) {
6602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           out_device = FM_SPKR;
6612aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           mic_device = HEADSET_MIC;
6622aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           LOGD("Stereo FM speaker");
663c42d5b9bd789034e4e10679b24a7bd38e68f4556Eric Laurent    } else if (device == SND_DEVICE_CARKIT) {
664c42d5b9bd789034e4e10679b24a7bd38e68f4556Eric Laurent           out_device = BT_SCO_SPKR;
665c42d5b9bd789034e4e10679b24a7bd38e68f4556Eric Laurent           mic_device = BT_SCO_MIC;
666c42d5b9bd789034e4e10679b24a7bd38e68f4556Eric Laurent           LOGD("Carkit");
66717b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent    } else if (device == SND_DEVICE_TTY_FULL) {
66817b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent        out_device = TTY_HEADSET_SPKR;
66917b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent        mic_device = TTY_HEADSET_MIC;
67017b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent        LOGD("TTY FULL headset");
67117b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent    } else if (device == SND_DEVICE_TTY_VCO) {
67217b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent        out_device = TTY_HEADSET_SPKR;
67317b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent        mic_device = HANDSET_MIC;
67417b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent        LOGD("TTY VCO headset");
67517b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent    } else if (device == SND_DEVICE_TTY_HCO) {
67617b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent        out_device = SPKR_PHONE_MONO;
67717b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent        mic_device = TTY_HEADSET_MIC;
67817b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent        LOGD("TTY HCO headset");
6792aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else {
68017b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent        LOGE("unknown device %d", device);
68117b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent        return -1;
6822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
6832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
6842aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#if 0 //Add for FM support
6852aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (out_device == FM_HEADSET ||
6862aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        out_device == FM_SPKR) {
6872aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (fd_fm_device < 0) {
6882aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            fd_fm_device = open("/dev/msm_htc_fm", O_RDWR);
6892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            if (fd_fm_device < 0) {
6902aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                LOGE("Cannot open msm_htc_fm device");
6912aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                return -1;
6922aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            }
6932aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            LOGD("Opened msm_htc_fm for FM radio");
6942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
6952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else if (fd_fm_device >= 0) {
6962aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        close(fd_fm_device);
6972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        fd_fm_device = -1;
6982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGD("Closed msm_htc_fm after FM radio");
6992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
7002aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#endif
7012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
7022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    fd = open("/dev/msm_audio_ctl", O_RDWR);
7032aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (fd < 0)        {
7042aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland       LOGE("Cannot open msm_audio_ctl");
7052aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland       return -1;
7062aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
7077fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    path[0] = out_device;
7087fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    path[1] = rx_acdb_id;
7097fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    if (ioctl(fd, AUDIO_SWITCH_DEVICE, &path)) {
7102aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland       LOGE("Cannot switch audio device");
7112aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland       close(fd);
7122aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland       return -1;
7132aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
7147fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    path[0] = mic_device;
7157fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    path[1] = tx_acdb_id;
7167fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    if (ioctl(fd, AUDIO_SWITCH_DEVICE, &path)) {
7172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland       LOGE("Cannot switch mic device");
7182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland       close(fd);
7192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland       return -1;
7202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
7210f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    curr_out_device = out_device;
7220f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    curr_mic_device = mic_device;
7232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
7242aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandIncall:
7252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (inCall == true && !voice_started) {
726f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        if (fd < 0) {
7272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            fd = open("/dev/msm_audio_ctl", O_RDWR);
7282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
7292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            if (fd < 0) {
7302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                LOGE("Cannot open msm_audio_ctl");
7312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                return -1;
7322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            }
7332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
734f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        if (rx_acdb_id == ACDB_ID_HAC_HANDSET_SPKR &&
735f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            tx_acdb_id == ACDB_ID_HAC_HANDSET_MIC) {
736f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            path[0] = rx_acdb_id;
737f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            path[1] = tx_acdb_id;
738f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            if (ioctl(fd, AUDIO_START_VOICE, &path)) {
739f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev                LOGE("Cannot start voice");
740f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev                close(fd);
741f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev                return -1;
742f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            }
743f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        } else {
744f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            if (ioctl(fd, AUDIO_START_VOICE, NULL)) {
745f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev                LOGE("Cannot start voice");
746f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev                close(fd);
747f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev                return -1;
748f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            }
7492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
7502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGD("Voice Started!!");
7512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        voice_started = 1;
7522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
7532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    else if (inCall == false && voice_started) {
7542aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (fd < 0) {
7552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            fd = open("/dev/msm_audio_ctl", O_RDWR);
7562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
7572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            if (fd < 0) {
7582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                LOGE("Cannot open msm_audio_ctl");
7592aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                return -1;
7602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            }
7612aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
7622aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (ioctl(fd, AUDIO_STOP_VOICE, NULL)) {
7632aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland               LOGE("Cannot stop voice");
7642aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland               close(fd);
7652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland               return -1;
7662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
7672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGD("Voice Stopped!!");
7682aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        voice_started = 0;
7692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
7702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
7712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    close(fd);
7722aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
7732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
7742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
7752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
7762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland// always call with mutex held
7772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::doAudioRouteOrMute(uint32_t device)
7782aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
7797fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    uint32_t rx_acdb_id = 0;
7807fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    uint32_t tx_acdb_id = 0;
7817fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi
782f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi    if (support_a1026 == 1)
783f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi            doAudience_A1026_Control(mMode, mRecordState, device);
784f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi
7852aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (device == (uint32_t)SND_DEVICE_BT || device == (uint32_t)SND_DEVICE_CARKIT) {
7860f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        if (!mBluetoothNrec) {
7872aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            device = SND_DEVICE_BT_EC_OFF;
7882aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
7892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
7907fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi
791f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    if (mMode == AudioSystem::MODE_IN_CALL
792f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            && (device == (int) SND_DEVICE_BT
793f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            || device == (int) SND_DEVICE_BT_EC_OFF)) {
794f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        if (mBluetoothIdTx != 0) {
7957fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi        rx_acdb_id = mBluetoothIdRx;
7967fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi        tx_acdb_id = mBluetoothIdTx;
7977fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    } else {
798f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            /* use default BT entry defined in AudioBTID.csv */
799f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            rx_acdb_id = mBTEndpoints[0].rx;
800f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            tx_acdb_id = mBTEndpoints[0].tx;
801f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            LOGD("Update ACDB ID to default BT setting\n");
802f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        }
803f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    } else if (mMode == AudioSystem::MODE_IN_CALL
804f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            && device == (int) SND_DEVICE_CARKIT) {
805f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        if (mBluetoothIdTx != 0) {
806f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            rx_acdb_id = mBluetoothIdRx;
807f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            tx_acdb_id = mBluetoothIdTx;
808f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        } else {
809f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            /* use default carkit entry defined in AudioBTID.csv */
810f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            rx_acdb_id = mBTEndpoints[1].rx;
811f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            tx_acdb_id = mBTEndpoints[1].tx;
812f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            LOGD("Update ACDB ID to default carkit setting");
813f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        }
814f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    } else if (mMode == AudioSystem::MODE_IN_CALL && hac_enable && mHACSetting) {
815f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        LOGE("Update acdb id to hac profile.");
816f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        rx_acdb_id = ACDB_ID_HAC_HANDSET_SPKR;
817f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        tx_acdb_id = ACDB_ID_HAC_HANDSET_MIC;
818f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    } else {
819f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        if (!checkOutputStandby() || mMode != AudioSystem::MODE_IN_CALL)
8207fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi            rx_acdb_id = getACDB(MOD_PLAY, device);
8217fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi        if (mRecordState)
8227fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi            tx_acdb_id = getACDB(MOD_REC, device);
8237fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    }
8247fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    LOGV("doAudioRouteOrMute: rx acdb %d, tx acdb %d\n", rx_acdb_id, tx_acdb_id);
8257fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi
8267fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    return do_route_audio_dev_ctrl(device, mMode == AudioSystem::MODE_IN_CALL, rx_acdb_id, tx_acdb_id);
8272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
8282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
8292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::get_mMode(void)
8302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
8312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return mMode;
8322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
8332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
8342aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::get_mRoutes(void)
8352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
8362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return mRoutes[mMode];
8372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
8382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
8392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::set_mRecordState(bool onoff)
8402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
8412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mRecordState = onoff;
8422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return 0;
8432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
8442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
845f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchevstatus_t AudioHardware::get_batt_temp(int *batt_temp)
846f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev{
847f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    int fd, len;
848f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    const char *fn =
849f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        "/sys/devices/platform/rs30100001:00000000/power_supply/battery/batt_temp";
850f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    char get_batt_temp[6] = { 0 };
851f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev
852f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    if ((fd = open(fn, O_RDONLY)) < 0) {
853f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        LOGE("%s: cannot open %s: %s\n", __FUNCTION__, fn, strerror(errno));
854f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        return UNKNOWN_ERROR;
855f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    }
856f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev
857f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    if ((len = read(fd, get_batt_temp, sizeof(get_batt_temp))) <= 1) {
858f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        LOGE("read battery temp fail: %s\n", strerror(errno));
859f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        close(fd);
860f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        return BAD_VALUE;
861f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    }
862f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev
863f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    *batt_temp = strtol(get_batt_temp, NULL, 10);
864f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    close(fd);
865f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    return NO_ERROR;
866f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev}
867f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev
8682aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::doA1026_init(void)
8692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
8702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    struct a1026img fwimg;
8712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    char char_tmp = 0;
87208516fe50b023532d5a3010050970de28e14621bIliyan Malchev    unsigned char local_vpimg_buf[A1026_MAX_FW_SIZE], *ptr = local_vpimg_buf;
87308516fe50b023532d5a3010050970de28e14621bIliyan Malchev    int rc = 0, fw_fd = -1;
87408516fe50b023532d5a3010050970de28e14621bIliyan Malchev    ssize_t nr;
87508516fe50b023532d5a3010050970de28e14621bIliyan Malchev    size_t remaining;
87608516fe50b023532d5a3010050970de28e14621bIliyan Malchev    struct stat fw_stat;
8772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
87808516fe50b023532d5a3010050970de28e14621bIliyan Malchev    static const char *const fn = "/system/etc/vpimg";
87908516fe50b023532d5a3010050970de28e14621bIliyan Malchev    static const char *const path = "/dev/audience_a1026";
88008516fe50b023532d5a3010050970de28e14621bIliyan Malchev
88108516fe50b023532d5a3010050970de28e14621bIliyan Malchev    if (fd_a1026 < 0)
88208516fe50b023532d5a3010050970de28e14621bIliyan Malchev        fd_a1026 = open(path, O_RDWR | O_NONBLOCK, 0);
8832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
8842aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (fd_a1026 < 0) {
88508516fe50b023532d5a3010050970de28e14621bIliyan Malchev        LOGE("Cannot open %s %d\n", path, fd_a1026);
88608516fe50b023532d5a3010050970de28e14621bIliyan Malchev        support_a1026 = 0;
88708516fe50b023532d5a3010050970de28e14621bIliyan Malchev        goto open_drv_err;
8882aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
8892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
89008516fe50b023532d5a3010050970de28e14621bIliyan Malchev    fw_fd = open(fn, O_RDONLY);
89108516fe50b023532d5a3010050970de28e14621bIliyan Malchev    if (fw_fd < 0) {
8922aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGE("Fail to open %s\n", fn);
8932aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        goto ld_img_error;
8947fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    } else LOGI("open %s success\n", fn);
8952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
89608516fe50b023532d5a3010050970de28e14621bIliyan Malchev    rc = fstat(fw_fd, &fw_stat);
89708516fe50b023532d5a3010050970de28e14621bIliyan Malchev    if (rc < 0) {
89808516fe50b023532d5a3010050970de28e14621bIliyan Malchev        LOGE("Cannot stat file %s: %s\n", fn, strerror(errno));
89908516fe50b023532d5a3010050970de28e14621bIliyan Malchev        goto ld_img_error;
90008516fe50b023532d5a3010050970de28e14621bIliyan Malchev    }
90108516fe50b023532d5a3010050970de28e14621bIliyan Malchev
90208516fe50b023532d5a3010050970de28e14621bIliyan Malchev    remaining = (int)fw_stat.st_size;
9032aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
90408516fe50b023532d5a3010050970de28e14621bIliyan Malchev    LOGI("Firmware %s size %d\n", fn, remaining);
90508516fe50b023532d5a3010050970de28e14621bIliyan Malchev
90608516fe50b023532d5a3010050970de28e14621bIliyan Malchev    if (remaining > sizeof(local_vpimg_buf)) {
90708516fe50b023532d5a3010050970de28e14621bIliyan Malchev        LOGE("File %s size %d exceeds internal limit %d\n",
90808516fe50b023532d5a3010050970de28e14621bIliyan Malchev             fn, remaining, sizeof(local_vpimg_buf));
90908516fe50b023532d5a3010050970de28e14621bIliyan Malchev        goto ld_img_error;
9102aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
9112aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
91208516fe50b023532d5a3010050970de28e14621bIliyan Malchev    while (remaining) {
91308516fe50b023532d5a3010050970de28e14621bIliyan Malchev        nr = read(fw_fd, ptr, remaining);
91408516fe50b023532d5a3010050970de28e14621bIliyan Malchev        if (nr < 0) {
91508516fe50b023532d5a3010050970de28e14621bIliyan Malchev            LOGE("Error reading firmware: %s\n", strerror(errno));
91608516fe50b023532d5a3010050970de28e14621bIliyan Malchev            goto ld_img_error;
91708516fe50b023532d5a3010050970de28e14621bIliyan Malchev        }
91808516fe50b023532d5a3010050970de28e14621bIliyan Malchev        else if (!nr) {
91908516fe50b023532d5a3010050970de28e14621bIliyan Malchev            if (remaining)
92008516fe50b023532d5a3010050970de28e14621bIliyan Malchev                LOGW("EOF reading firmware %s while %d bytes remain\n",
92108516fe50b023532d5a3010050970de28e14621bIliyan Malchev                     fn, remaining);
92208516fe50b023532d5a3010050970de28e14621bIliyan Malchev            break;
92308516fe50b023532d5a3010050970de28e14621bIliyan Malchev        }
92408516fe50b023532d5a3010050970de28e14621bIliyan Malchev        remaining -= nr;
92508516fe50b023532d5a3010050970de28e14621bIliyan Malchev        ptr += nr;
92608516fe50b023532d5a3010050970de28e14621bIliyan Malchev    }
92708516fe50b023532d5a3010050970de28e14621bIliyan Malchev
92808516fe50b023532d5a3010050970de28e14621bIliyan Malchev    close (fw_fd);
92908516fe50b023532d5a3010050970de28e14621bIliyan Malchev    fw_fd = -1;
93008516fe50b023532d5a3010050970de28e14621bIliyan Malchev
9312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    fwimg.buf = local_vpimg_buf;
93208516fe50b023532d5a3010050970de28e14621bIliyan Malchev    fwimg.img_size = (int)(fw_stat.st_size - remaining);
93308516fe50b023532d5a3010050970de28e14621bIliyan Malchev    LOGI("Total %d bytes put to user space buffer.\n", fwimg.img_size);
9342aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
9352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    rc = ioctl(fd_a1026, A1026_BOOTUP_INIT, &fwimg);
9362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (!rc) {
9372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGI("audience_a1026 init OK\n");
9382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mA1026Init = 1;
9392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else
9402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGE("audience_a1026 init failed\n");
9412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
9422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandld_img_error:
94308516fe50b023532d5a3010050970de28e14621bIliyan Malchev    if (fw_fd >= 0)
94408516fe50b023532d5a3010050970de28e14621bIliyan Malchev        close(fw_fd);
9452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    close(fd_a1026);
9462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandopen_drv_err:
9472aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    fd_a1026 = -1;
9482aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return rc;
9492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
9502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
9512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::get_snd_dev(void)
9522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
9532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    Mutex::Autolock lock(mLock);
9547161d052ce69228825bd5deca3bfa4a213a99f06HK Chen    return mCurSndDevice;
9552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
9562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
9577fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Triviuint32_t AudioHardware::getACDB(int mode, int device)
9580f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent{
9597fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    uint32_t acdb_id = 0;
960f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    int batt_temp = 0;
9610f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    if (mMode == AudioSystem::MODE_IN_CALL) {
9620f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        LOGD("skip update ACDB due to in-call");
9630f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        return 0;
9640f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    }
9650f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent
9667fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    if (mode == MOD_PLAY) {
9677fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi        switch (device) {
9680f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            case SND_DEVICE_HEADSET:
9690f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            case SND_DEVICE_NO_MIC_HEADSET:
970da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            case SND_DEVICE_NO_MIC_HEADSET_BACK_MIC:
9710f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            case SND_DEVICE_FM_HEADSET:
9720f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                acdb_id = ACDB_ID_HEADSET_PLAYBACK;
9730f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                break;
9740f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            case SND_DEVICE_SPEAKER:
9750f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            case SND_DEVICE_FM_SPEAKER:
976da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            case SND_DEVICE_SPEAKER_BACK_MIC:
9770f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                acdb_id = ACDB_ID_SPKR_PLAYBACK;
978f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev                if(alt_enable) {
979f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev                    LOGD("Enable ALT for speaker\n");
980f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev                    if (get_batt_temp(&batt_temp)) {
981f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev                        if (batt_temp < 50)
982f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev                            acdb_id = ACDB_ID_ALT_SPKR_PLAYBACK;
983f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev                        LOGD("ALT batt temp = %d\n", batt_temp);
984f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev                    }
985f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev                }
9860f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                break;
9870f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            case SND_DEVICE_HEADSET_AND_SPEAKER:
98858cf88a5a91d82ae2fb3e23365eaa4524a9cd089Jean-Michel Trivi            case SND_DEVICE_HEADSET_AND_SPEAKER_BACK_MIC:
9890f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                acdb_id = ACDB_ID_HEADSET_RINGTONE_PLAYBACK;
9900f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                break;
9910f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            default:
9920f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                break;
9930f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        }
9947fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    } else if (mode == MOD_REC) {
9957fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi        switch (device) {
9960f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            case SND_DEVICE_HEADSET:
9970f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            case SND_DEVICE_FM_HEADSET:
9980f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            case SND_DEVICE_FM_SPEAKER:
99958cf88a5a91d82ae2fb3e23365eaa4524a9cd089Jean-Michel Trivi            case SND_DEVICE_HEADSET_AND_SPEAKER:
10000f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                acdb_id = ACDB_ID_EXT_MIC_REC;
10010f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                break;
10020f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            case SND_DEVICE_HANDSET:
10030f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            case SND_DEVICE_NO_MIC_HEADSET:
10040f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            case SND_DEVICE_SPEAKER:
100508516fe50b023532d5a3010050970de28e14621bIliyan Malchev                if (vr_mode_enabled == 0) {
100663af0f3cbd387e97bcaca82d1e22787c224d6430Jean-Michel Trivi                    acdb_id = ACDB_ID_INT_MIC_REC;
100763af0f3cbd387e97bcaca82d1e22787c224d6430Jean-Michel Trivi                } else {
100863af0f3cbd387e97bcaca82d1e22787c224d6430Jean-Michel Trivi                    acdb_id = ACDB_ID_INT_MIC_VR;
100963af0f3cbd387e97bcaca82d1e22787c224d6430Jean-Michel Trivi                }
101063af0f3cbd387e97bcaca82d1e22787c224d6430Jean-Michel Trivi                break;
1011da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            case SND_DEVICE_SPEAKER_BACK_MIC:
1012da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            case SND_DEVICE_NO_MIC_HEADSET_BACK_MIC:
1013da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            case SND_DEVICE_HANDSET_BACK_MIC:
101458cf88a5a91d82ae2fb3e23365eaa4524a9cd089Jean-Michel Trivi            case SND_DEVICE_HEADSET_AND_SPEAKER_BACK_MIC:
101563af0f3cbd387e97bcaca82d1e22787c224d6430Jean-Michel Trivi                acdb_id = ACDB_ID_CAMCORDER;
10160f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                break;
10170f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            default:
10180f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                break;
10190f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        }
10200f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    }
10217fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    LOGV("getACDB, return ID %d\n", acdb_id);
10227fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    return acdb_id;
10230f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent}
10240f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent
1025f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchevstatus_t AudioHardware::do_tpa2018_control(int mode)
1026f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev{
1027f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    if (curr_out_device == HANDSET_SPKR ||
1028f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        curr_out_device == SPKR_PHONE_MONO ||
1029f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        curr_out_device == HEADSET_SPKR_STEREO ||
1030f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        curr_out_device == SPKR_PHONE_HEADSET_STEREO ||
1031f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        curr_out_device == FM_SPKR) {
1032f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev
1033f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev	int fd, rc;
1034f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        int retry = 3;
1035f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev
1036f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        switch (mode) {
1037f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        case AudioSystem::MODE_NORMAL:
1038f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            mode = TPA2018_MODE_PLAYBACK;
1039f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            break;
1040f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        case AudioSystem::MODE_RINGTONE:
1041f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            mode = TPA2018_MODE_RINGTONE;
1042f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            break;
1043f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        case AudioSystem::MODE_IN_CALL:
1044f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            mode = TPA2018_MODE_VOICE_CALL;
1045f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            break;
1046f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        default:
1047f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            return 0;
1048f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        }
1049f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev
1050f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        fd = open("/dev/tpa2018d1", O_RDWR);
1051f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        if (fd < 0) {
1052f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            LOGE("can't open /dev/tpa2018d1 %d", fd);
1053f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            return -1;
1054f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        }
1055f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev
1056f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        do {
1057f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            rc = ioctl(fd, TPA2018_SET_MODE, &mode);
1058f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            if (!rc)
1059f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev                break;
1060f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        } while (--retry);
1061f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev
1062f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        if (rc < 0) {
1063f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            LOGE("ioctl TPA2018_SET_MODE failed: %s", strerror(errno));
1064f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        } else
1065f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            LOGD("Update TPA2018_SET_MODE to mode %d success", mode);
1066f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev
1067f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        close(fd);
1068f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    }
1069f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    return 0;
1070f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev}
10717fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi
10722aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::doAudience_A1026_Control(int Mode, bool Record, uint32_t Routes)
10732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
10742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    int rc = 0;
10750f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    int retry = 4;
10762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
10772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (!mA1026Init) {
10782aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	LOGW("Audience A1026 not initialized.\n");
10792aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	return NO_INIT;
10802aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
10812aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
10822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (fd_a1026 < 0) {
10832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        fd_a1026 = open("/dev/audience_a1026", O_RDWR);
10842aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (fd_a1026 < 0) {
10852aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            LOGE("Cannot open audience_a1026 device (%d)\n", fd_a1026);
10862aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            return -1;
10872aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	}
10882aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
10892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
10902aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mA1026Lock.lock();
10912aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
10922aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if ((Mode < AudioSystem::MODE_CURRENT) || (Mode >= AudioSystem::NUM_MODES)) {
10932aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGW("Illegal value: doAudience_A1026_Control(%d, %u, %u)", Mode, Record, Routes);
10942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mA1026Lock.unlock();
10952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return BAD_VALUE;
10962aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
10972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
10982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (Mode == AudioSystem::MODE_IN_CALL) {
10992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (Record == 1) {
11002aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	    switch (Routes) {
11012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        case SND_DEVICE_HANDSET:
11022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        case SND_DEVICE_NO_MIC_HEADSET:
1103da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent	            //TODO: what do we do for camcorder when in call?
1104da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent	        case SND_DEVICE_NO_MIC_HEADSET_BACK_MIC:
1105da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent	        case SND_DEVICE_HANDSET_BACK_MIC:
110617b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent	        case SND_DEVICE_TTY_VCO:
11079ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	            if (enable1026) {
11084bcd5b16c66bc5c2bffe232f15f5cb83aea18318Jean-Michel Trivi                    new_pathid = A1026_PATH_INCALL_RECEIVER;
110963af0f3cbd387e97bcaca82d1e22787c224d6430Jean-Michel Trivi                    LOGV("A1026 control: new path is A1026_PATH_INCALL_RECEIVER");
11109ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	            } else {
11119ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	                new_pathid = A1026_PATH_INCALL_NO_NS_RECEIVER;
11129ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	                LOGV("A1026 control: new path is A1026_PATH_INCALL_NO_NS_RECEIVER");
11139ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	            }
11149ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	            break;
11159ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	        case SND_DEVICE_HEADSET:
11169ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	        case SND_DEVICE_HEADSET_AND_SPEAKER:
11179ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	        case SND_DEVICE_FM_HEADSET:
11189ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	        case SND_DEVICE_FM_SPEAKER:
11199ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	        case SND_DEVICE_HEADSET_AND_SPEAKER_BACK_MIC:
112017b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent	        case SND_DEVICE_TTY_HCO:
112117b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent	        case SND_DEVICE_TTY_FULL:
11224bcd5b16c66bc5c2bffe232f15f5cb83aea18318Jean-Michel Trivi	            new_pathid = A1026_PATH_INCALL_HEADSET;
112363af0f3cbd387e97bcaca82d1e22787c224d6430Jean-Michel Trivi	            LOGV("A1026 control: new path is A1026_PATH_INCALL_HEADSET");
11242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            break;
11252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        case SND_DEVICE_SPEAKER:
1126da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent	            //TODO: what do we do for camcorder when in call?
1127da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent	        case SND_DEVICE_SPEAKER_BACK_MIC:
11284bcd5b16c66bc5c2bffe232f15f5cb83aea18318Jean-Michel Trivi	            new_pathid = A1026_PATH_INCALL_SPEAKER;
112963af0f3cbd387e97bcaca82d1e22787c224d6430Jean-Michel Trivi	            LOGV("A1026 control: new path is A1026_PATH_INCALL_SPEAKER");
11302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            break;
11312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        case SND_DEVICE_BT:
11322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        case SND_DEVICE_BT_EC_OFF:
1133c42d5b9bd789034e4e10679b24a7bd38e68f4556Eric Laurent	        case SND_DEVICE_CARKIT:
11344bcd5b16c66bc5c2bffe232f15f5cb83aea18318Jean-Michel Trivi	            new_pathid = A1026_PATH_INCALL_BT;
113563af0f3cbd387e97bcaca82d1e22787c224d6430Jean-Michel Trivi	            LOGV("A1026 control: new path is A1026_PATH_INCALL_BT");
11362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            break;
11372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        default:
11382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            break;
11392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            }
11402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland       } else {
11412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           switch (Routes) {
11422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        case SND_DEVICE_HANDSET:
11432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        case SND_DEVICE_NO_MIC_HEADSET:
114417b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent	        case SND_DEVICE_TTY_VCO:
11459ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	            if (enable1026) {
11469ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	                new_pathid = A1026_PATH_INCALL_RECEIVER; /* NS CT mode, Dual MIC */
114763af0f3cbd387e97bcaca82d1e22787c224d6430Jean-Michel Trivi                    LOGV("A1026 control: new path is A1026_PATH_INCALL_RECEIVER");
11489ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	            } else {
11499ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	                new_pathid = A1026_PATH_INCALL_NO_NS_RECEIVER;
11509ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	                LOGV("A1026 control: new path is A1026_PATH_INCALL_NO_NS_RECEIVER");
11519ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	            }
11529ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	            break;
11539ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	        case SND_DEVICE_HEADSET:
11549ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	        case SND_DEVICE_HEADSET_AND_SPEAKER:
11559ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	        case SND_DEVICE_FM_HEADSET:
11569ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	        case SND_DEVICE_FM_SPEAKER:
115717b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent	        case SND_DEVICE_TTY_HCO:
115817b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent	        case SND_DEVICE_TTY_FULL:
11592aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            new_pathid = A1026_PATH_INCALL_HEADSET; /* NS disable, Headset MIC */
116063af0f3cbd387e97bcaca82d1e22787c224d6430Jean-Michel Trivi	            LOGV("A1026 control: new path is A1026_PATH_INCALL_HEADSET");
11612aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            break;
11622aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        case SND_DEVICE_SPEAKER:
11632aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            new_pathid = A1026_PATH_INCALL_SPEAKER; /* NS FT mode, Main MIC */
116463af0f3cbd387e97bcaca82d1e22787c224d6430Jean-Michel Trivi	            LOGV("A1026 control: new path is A1026_PATH_INCALL_SPEAKER");
11652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            break;
11662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        case SND_DEVICE_BT:
11672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        case SND_DEVICE_BT_EC_OFF:
1168c42d5b9bd789034e4e10679b24a7bd38e68f4556Eric Laurent	        case SND_DEVICE_CARKIT:
11692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            new_pathid = A1026_PATH_INCALL_BT; /* QCOM NS, BT MIC */
117063af0f3cbd387e97bcaca82d1e22787c224d6430Jean-Michel Trivi	            LOGV("A1026 control: new path is A1026_PATH_INCALL_BT");
11712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            break;
11722aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        default:
11732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            break;
11742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            }
11752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland       }
11762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else if (Record == 1) {
11772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        switch (Routes) {
1178ba36d4fa33072ef14183365fffd289762c26905eJean-Michel Trivi        case SND_DEVICE_SPEAKER:
1179ba36d4fa33072ef14183365fffd289762c26905eJean-Michel Trivi            // default output is speaker, recording from phone mic, user RECEIVER configuration
1180739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        case SND_DEVICE_HANDSET:
1181739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        case SND_DEVICE_NO_MIC_HEADSET:
118208516fe50b023532d5a3010050970de28e14621bIliyan Malchev	        if (vr_mode_enabled) {
1183739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	            if (vr_uses_ns) {
11844bcd5b16c66bc5c2bffe232f15f5cb83aea18318Jean-Michel Trivi	                new_pathid = A1026_PATH_VR_NS_RECEIVER;
1185739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	                LOGV("A1026 control: new path is A1026_PATH_VR_NS_RECEIVER");
1186739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	            } else {
11874bcd5b16c66bc5c2bffe232f15f5cb83aea18318Jean-Michel Trivi	                new_pathid = A1026_PATH_VR_NO_NS_RECEIVER;
1188739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	                LOGV("A1026 control: new path is A1026_PATH_VR_NO_NS_RECEIVER");
1189739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	            }
1190739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	        } else {
11919ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	            new_pathid = A1026_PATH_RECORD_RECEIVER; /* INT-MIC Recording: NS disable, Main MIC */
1192739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi                LOGV("A1026 control: new path is A1026_PATH_RECORD_RECEIVER");
1193739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	        }
11942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        break;
1195739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        case SND_DEVICE_HEADSET:
1196739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        case SND_DEVICE_HEADSET_AND_SPEAKER:
1197739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        case SND_DEVICE_FM_HEADSET:
1198739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        case SND_DEVICE_FM_SPEAKER:
119908516fe50b023532d5a3010050970de28e14621bIliyan Malchev	        if (vr_mode_enabled) {
1200739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	            if (vr_uses_ns) {
12014bcd5b16c66bc5c2bffe232f15f5cb83aea18318Jean-Michel Trivi	                new_pathid = A1026_PATH_VR_NS_HEADSET;
1202739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	                LOGV("A1026 control: new path is A1026_PATH_VR_NS_HEADSET");
1203739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	            } else {
12044bcd5b16c66bc5c2bffe232f15f5cb83aea18318Jean-Michel Trivi	                new_pathid = A1026_PATH_VR_NO_NS_HEADSET;
1205739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	                LOGV("A1026 control: new path is A1026_PATH_VR_NO_NS_HEADSET");
1206739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	            }
1207739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	        } else {
1208739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	            new_pathid = A1026_PATH_RECORD_HEADSET; /* EXT-MIC Recording: NS disable, Headset MIC */
1209739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	            LOGV("A1026 control: new path is A1026_PATH_RECORD_HEADSET");
1210739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	        }
1211739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	        break;
1212739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        case SND_DEVICE_SPEAKER_BACK_MIC:
1213739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        case SND_DEVICE_NO_MIC_HEADSET_BACK_MIC:
1214739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        case SND_DEVICE_HANDSET_BACK_MIC:
121558cf88a5a91d82ae2fb3e23365eaa4524a9cd089Jean-Michel Trivi        case SND_DEVICE_HEADSET_AND_SPEAKER_BACK_MIC:
1216da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent	        new_pathid = A1026_PATH_CAMCORDER; /* CAM-Coder: NS FT mode, Back MIC */
1217f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi	        LOGV("A1026 control: new path is A1026_PATH_CAMCORDER");
12182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        break;
1219739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        case SND_DEVICE_BT:
1220739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        case SND_DEVICE_BT_EC_OFF:
1221c42d5b9bd789034e4e10679b24a7bd38e68f4556Eric Laurent        case SND_DEVICE_CARKIT:
122208516fe50b023532d5a3010050970de28e14621bIliyan Malchev	        if (vr_mode_enabled) {
1223739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	            if (vr_uses_ns) {
12244bcd5b16c66bc5c2bffe232f15f5cb83aea18318Jean-Michel Trivi	                new_pathid = A1026_PATH_VR_NS_BT;
1225739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	                LOGV("A1026 control: new path is A1026_PATH_VR_NS_BT");
1226739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	            } else {
12274bcd5b16c66bc5c2bffe232f15f5cb83aea18318Jean-Michel Trivi	                new_pathid = A1026_PATH_VR_NO_NS_BT;
1228739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	                LOGV("A1026 control: new path is A1026_PATH_VR_NO_NS_BT");
1229739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	            }
1230739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	        } else {
1231739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	            new_pathid = A1026_PATH_RECORD_BT; /* BT MIC */
1232739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	            LOGV("A1026 control: new path is A1026_PATH_RECORD_BT");
1233739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	        }
12342aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        break;
1235739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        default:
12362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        break;
12372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
12382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
12392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    else {
12402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        new_pathid = A1026_PATH_SUSPEND;
12412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
12422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
12432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (old_pathid != new_pathid) {
12442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        //LOGI("A1026: do ioctl(A1026_SET_CONFIG) to %d\n", new_pathid);
12450f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        do {
12460f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            rc = ioctl(fd_a1026, A1026_SET_CONFIG, &new_pathid);
12470f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            if (!rc) {
12480f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                old_pathid = new_pathid;
12490f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                break;
12500f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            }
12510f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        } while (--retry);
12520f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent
12530f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        if (rc < 0) {
12540f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            LOGE("A1026 do hard reset to recover from error!\n");
12550f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            rc = doA1026_init(); /* A1026 needs to do hard reset! */
12560f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            if (!rc) {
12572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	rc = ioctl(fd_a1026, A1026_SET_CONFIG, &new_pathid);
12582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	if (!rc)
12592aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland		old_pathid = new_pathid;
12602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	else
12610f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                    LOGE("A1026 Fatal Error!\n");
12620f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            } else
12630f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                LOGE("A1026 Fatal Error: Re-init A1026 Failed\n");
12640f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        }
12652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
12662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
12672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mA1026Lock.unlock();
12682aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    close(fd_a1026);
12692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    fd_a1026 = -1;
12702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
12712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return rc;
12722aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
12732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
12742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
12752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::doRouting(AudioStreamInMSM72xx *input)
12762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
1277f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi    Mutex::Autolock lock(mLock);
1278f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi    uint32_t outputDevices = mOutput->devices();
12792aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    status_t ret = NO_ERROR;
1280f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi    int sndDevice = -1;
12812aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
128217b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent    if (mMode == AudioSystem::MODE_IN_CALL && mTTYMode != TTY_MODE_OFF) {
128317b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent        if ((outputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) ||
128417b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent            (outputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE)) {
128517b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent            switch (mTTYMode) {
128617b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent            case TTY_MODE_FULL:
128717b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent                sndDevice = SND_DEVICE_TTY_FULL;
128817b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent                break;
128917b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent            case TTY_MODE_VCO:
129017b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent                sndDevice = SND_DEVICE_TTY_VCO;
129117b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent                break;
129217b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent            case TTY_MODE_HCO:
129317b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent                sndDevice = SND_DEVICE_TTY_HCO;
129417b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent                break;
129517b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent            }
129617b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent        }
129717b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent    }
129817b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent
129917b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent    if (sndDevice == -1 && input != NULL) {
1300f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        uint32_t inputDevice = input->devices();
1301f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        LOGI("do input routing device %x\n", inputDevice);
1302f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        if (inputDevice != 0) {
1303f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi            if (inputDevice & AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
1304f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                LOGI("Routing audio to Bluetooth PCM\n");
1305f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                sndDevice = SND_DEVICE_BT;
1306c42d5b9bd789034e4e10679b24a7bd38e68f4556Eric Laurent            } else if (inputDevice & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT) {
1307f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev                LOGI("Routing audio to Bluetooth car kit\n");
1308f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev                sndDevice = SND_DEVICE_CARKIT;
1309f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi            } else if (inputDevice & AudioSystem::DEVICE_IN_WIRED_HEADSET) {
1310f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                if ((outputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) &&
1311956f7ba5ee0f087c91b5fefd2718dae30f8c1e29Eric Laurent                        (outputDevices & AudioSystem::DEVICE_OUT_SPEAKER)) {
1312f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                            LOGI("Routing audio to Wired Headset and Speaker\n");
1313f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                            sndDevice = SND_DEVICE_HEADSET_AND_SPEAKER;
1314956f7ba5ee0f087c91b5fefd2718dae30f8c1e29Eric Laurent                } else {
1315f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                    LOGI("Routing audio to Wired Headset\n");
1316f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                    sndDevice = SND_DEVICE_HEADSET;
1317f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                }
1318f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi            } else if (inputDevice & AudioSystem::DEVICE_IN_BACK_MIC) {
131958cf88a5a91d82ae2fb3e23365eaa4524a9cd089Jean-Michel Trivi                if (outputDevices & (AudioSystem:: DEVICE_OUT_WIRED_HEADSET) &&
132058cf88a5a91d82ae2fb3e23365eaa4524a9cd089Jean-Michel Trivi                       (outputDevices & AudioSystem:: DEVICE_OUT_SPEAKER)) {
132158cf88a5a91d82ae2fb3e23365eaa4524a9cd089Jean-Michel Trivi                    LOGI("Routing audio to Wired Headset and Speaker with back mic\n");
132258cf88a5a91d82ae2fb3e23365eaa4524a9cd089Jean-Michel Trivi                    sndDevice = SND_DEVICE_HEADSET_AND_SPEAKER_BACK_MIC;
132358cf88a5a91d82ae2fb3e23365eaa4524a9cd089Jean-Michel Trivi                } else if (outputDevices & AudioSystem::DEVICE_OUT_SPEAKER) {
1324f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                    LOGI("Routing audio to Speakerphone with back mic\n");
1325f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                    sndDevice = SND_DEVICE_SPEAKER_BACK_MIC;
1326f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                } else if (outputDevices == AudioSystem::DEVICE_OUT_EARPIECE) {
1327f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                    LOGI("Routing audio to Handset with back mic\n");
1328f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                    sndDevice = SND_DEVICE_HANDSET_BACK_MIC;
1329f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                } else {
1330f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                    LOGI("Routing audio to Headset with back mic\n");
1331f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                    sndDevice = SND_DEVICE_NO_MIC_HEADSET_BACK_MIC;
1332f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                }
1333f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi            } else {
1334f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                if (outputDevices & AudioSystem::DEVICE_OUT_SPEAKER) {
1335f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                    LOGI("Routing audio to Speakerphone\n");
1336f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                    sndDevice = SND_DEVICE_SPEAKER;
1337f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                } else if (outputDevices == AudioSystem::DEVICE_OUT_WIRED_HEADPHONE) {
1338f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                    LOGI("Routing audio to Speakerphone\n");
1339f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                    sndDevice = SND_DEVICE_NO_MIC_HEADSET;
1340f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                } else {
1341f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                    LOGI("Routing audio to Handset\n");
1342f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                    sndDevice = SND_DEVICE_HANDSET;
1343956f7ba5ee0f087c91b5fefd2718dae30f8c1e29Eric Laurent                }
1344956f7ba5ee0f087c91b5fefd2718dae30f8c1e29Eric Laurent            }
1345956f7ba5ee0f087c91b5fefd2718dae30f8c1e29Eric Laurent        }
1346f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        // if inputDevice == 0, restore output routing
1347f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi    }
1348956f7ba5ee0f087c91b5fefd2718dae30f8c1e29Eric Laurent
1349f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi    if (sndDevice == -1) {
1350f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        if (outputDevices & (outputDevices - 1)) {
1351f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi            if ((outputDevices & AudioSystem::DEVICE_OUT_SPEAKER) == 0) {
1352f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                LOGW("Hardware does not support requested route combination (%#X),"
1353f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                        " picking closest possible route...", outputDevices);
1354956f7ba5ee0f087c91b5fefd2718dae30f8c1e29Eric Laurent            }
1355f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        }
1356956f7ba5ee0f087c91b5fefd2718dae30f8c1e29Eric Laurent
1357f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        if (outputDevices &
1358dd65e38951ed174f9d3d34886795438440f7eea0Eric Laurent                (AudioSystem::DEVICE_OUT_BLUETOOTH_SCO | AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET)) {
1359f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                    LOGI("Routing audio to Bluetooth PCM\n");
1360f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                    sndDevice = SND_DEVICE_BT;
1361f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        } else if (outputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT) {
1362f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi            LOGI("Routing audio to Bluetooth PCM\n");
1363f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi            sndDevice = SND_DEVICE_CARKIT;
1364f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        } else if ((outputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) &&
1365f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                (outputDevices & AudioSystem::DEVICE_OUT_SPEAKER)) {
1366f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                    LOGI("Routing audio to Wired Headset and Speaker\n");
1367956f7ba5ee0f087c91b5fefd2718dae30f8c1e29Eric Laurent                    sndDevice = SND_DEVICE_HEADSET_AND_SPEAKER;
1368f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        } else if (outputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE) {
1369f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi            if (outputDevices & AudioSystem::DEVICE_OUT_SPEAKER) {
1370f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                LOGI("Routing audio to No microphone Wired Headset and Speaker (%d,%x)\n", mMode, outputDevices);
1371f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                sndDevice = SND_DEVICE_HEADSET_AND_SPEAKER;
1372956f7ba5ee0f087c91b5fefd2718dae30f8c1e29Eric Laurent            } else {
1373f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                LOGI("Routing audio to No microphone Wired Headset (%d,%x)\n", mMode, outputDevices);
1374f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                sndDevice = SND_DEVICE_NO_MIC_HEADSET;
13752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            }
1376f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        } else if (outputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) {
1377f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi            LOGI("Routing audio to Wired Headset\n");
1378f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi            sndDevice = SND_DEVICE_HEADSET;
1379f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        } else if (outputDevices & AudioSystem::DEVICE_OUT_SPEAKER) {
1380f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi            LOGI("Routing audio to Speakerphone\n");
1381f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi            sndDevice = SND_DEVICE_SPEAKER;
1382f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        } else {
1383f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi            LOGI("Routing audio to Handset\n");
1384f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi            sndDevice = SND_DEVICE_HANDSET;
13852aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
1386f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi    }
13872aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
1388f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi    if ((vr_mode_change) || (sndDevice != -1 && sndDevice != mCurSndDevice)) {
1389f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        ret = doAudioRouteOrMute(sndDevice);
1390f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        mCurSndDevice = sndDevice;
13913964d4ed448b00791bc1b574913be24f44b45f0fEric Laurent        if (mMode == AudioSystem::MODE_IN_CALL) {
13923964d4ed448b00791bc1b574913be24f44b45f0fEric Laurent            set_volume_rpc(mVoiceVolume);
13933964d4ed448b00791bc1b574913be24f44b45f0fEric Laurent        }
13942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
13952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
13962aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return ret;
13972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
13982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
13992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::checkMicMute()
14002aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
14012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    Mutex::Autolock lock(mLock);
14022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mMode != AudioSystem::MODE_IN_CALL) {
14032aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        setMicMute_nosync(true);
14042aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
14052aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
14062aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
14072aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
14082aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
14092aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::dumpInternals(int fd, const Vector<String16>& args)
14102aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
14112aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    const size_t SIZE = 256;
14122aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    char buffer[SIZE];
14132aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    String8 result;
14142aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append("AudioHardware::dumpInternals\n");
14152aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmInit: %s\n", mInit? "true": "false");
14162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
14172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmMicMute: %s\n", mMicMute? "true": "false");
14182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
14192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmBluetoothNrec: %s\n", mBluetoothNrec? "true": "false");
14202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
14210f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    snprintf(buffer, SIZE, "\tmBluetoothIdtx: %d\n", mBluetoothIdTx);
14220f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    result.append(buffer);
14230f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    snprintf(buffer, SIZE, "\tmBluetoothIdrx: %d\n", mBluetoothIdRx);
14242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
14252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    ::write(fd, result.string(), result.size());
14262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
14272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
14282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
14292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::dump(int fd, const Vector<String16>& args)
14302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
14312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    dumpInternals(fd, args);
14322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    for (size_t index = 0; index < mInputs.size(); index++) {
14332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mInputs[index]->dump(fd, args);
14342aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
14352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
14362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mOutput) {
14372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mOutput->dump(fd, args);
14382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
14392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
14402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
14412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
14422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlanduint32_t AudioHardware::getInputSampleRate(uint32_t sampleRate)
14432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
14442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    uint32_t i;
14452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    uint32_t prevDelta;
14462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    uint32_t delta;
14472aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
14482aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    for (i = 0, prevDelta = 0xFFFFFFFF; i < sizeof(inputSamplingRates)/sizeof(uint32_t); i++, prevDelta = delta) {
14492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        delta = abs(sampleRate - inputSamplingRates[i]);
14502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (delta > prevDelta) break;
14512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
14522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // i is always > 0 here
14532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return inputSamplingRates[i-1];
14542aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
14552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
14562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland// ----------------------------------------------------------------------------
14572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
14582aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandAudioHardware::AudioStreamOutMSM72xx::AudioStreamOutMSM72xx() :
14592aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mHardware(0), mFd(-1), mStartCount(0), mRetryCount(0), mStandby(true), mDevices(0)
14602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
14612aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
14622aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
14632aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::AudioStreamOutMSM72xx::set(
14642aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        AudioHardware* hw, uint32_t devices, int *pFormat, uint32_t *pChannels, uint32_t *pRate)
14652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
14662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    int lFormat = pFormat ? *pFormat : 0;
14672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    uint32_t lChannels = pChannels ? *pChannels : 0;
14682aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    uint32_t lRate = pRate ? *pRate : 0;
14692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
14702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mHardware = hw;
14712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
14722aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // fix up defaults
14732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (lFormat == 0) lFormat = format();
14742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (lChannels == 0) lChannels = channels();
14752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (lRate == 0) lRate = sampleRate();
14762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
14772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // check values
14782aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if ((lFormat != format()) ||
14792aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        (lChannels != channels()) ||
14802aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        (lRate != sampleRate())) {
14812aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (pFormat) *pFormat = format();
14822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (pChannels) *pChannels = channels();
14832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (pRate) *pRate = sampleRate();
14842aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return BAD_VALUE;
14852aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
14862aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
14872aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (pFormat) *pFormat = lFormat;
14882aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (pChannels) *pChannels = lChannels;
14892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (pRate) *pRate = lRate;
14902aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
14912aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mDevices = devices;
14922aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
14932aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
14942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
14952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
14962aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandAudioHardware::AudioStreamOutMSM72xx::~AudioStreamOutMSM72xx()
14972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
14982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mFd >= 0) close(mFd);
14992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
15002aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
15012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandssize_t AudioHardware::AudioStreamOutMSM72xx::write(const void* buffer, size_t bytes)
15022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
15032aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // LOGD("AudioStreamOutMSM72xx::write(%p, %u)", buffer, bytes);
15042aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    status_t status = NO_INIT;
15052aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    size_t count = bytes;
15062aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    const uint8_t* p = static_cast<const uint8_t*>(buffer);
15072aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
15082aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mStandby) {
15092aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
15102aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        // open driver
15112aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGV("open pcm_out driver");
15122aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        status = ::open("/dev/msm_pcm_out", O_RDWR);
15132aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (status < 0) {
15142aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            if (errCount++ < 10) {
15152aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                LOGE("Cannot open /dev/msm_pcm_out errno: %d", errno);
15162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            }
15172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            goto Error;
15182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
15192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mFd = status;
15202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
15212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        // configuration
15222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGV("get config");
15232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        struct msm_audio_config config;
15242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        status = ioctl(mFd, AUDIO_GET_CONFIG, &config);
15252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (status < 0) {
15262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            LOGE("Cannot read pcm_out config");
15272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            goto Error;
15282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
15292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
15302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGV("set pcm_out config");
15312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        config.channel_count = AudioSystem::popCount(channels());
15322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        config.sample_rate = sampleRate();
15332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        config.buffer_size = bufferSize();
15342aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        config.buffer_count = AUDIO_HW_NUM_OUT_BUF;
15352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        config.codec_type = CODEC_TYPE_PCM;
15362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        status = ioctl(mFd, AUDIO_SET_CONFIG, &config);
15372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (status < 0) {
15382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            LOGE("Cannot set config");
15392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            goto Error;
15402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
15412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
15422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGV("buffer_size: %u", config.buffer_size);
15432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGV("buffer_count: %u", config.buffer_count);
15442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGV("channel_count: %u", config.channel_count);
15452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGV("sample_rate: %u", config.sample_rate);
15462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
15477fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi        uint32_t acdb_id = mHardware->getACDB(MOD_PLAY, mHardware->get_snd_dev());
15487fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi        status = ioctl(mFd, AUDIO_START, &acdb_id);
154931923bb6797ec304d26395acf6d946ab8e44aa6eHK Chen        if (status < 0) {
155031923bb6797ec304d26395acf6d946ab8e44aa6eHK Chen            LOGE("Cannot start pcm playback");
155131923bb6797ec304d26395acf6d946ab8e44aa6eHK Chen            goto Error;
15522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
155310254cc35f5cb7ebe2c7ef452815486cb8e92a33Jean-Michel Trivi
155410254cc35f5cb7ebe2c7ef452815486cb8e92a33Jean-Michel Trivi        status = ioctl(mFd, AUDIO_SET_VOLUME, &stream_volume);
155510254cc35f5cb7ebe2c7ef452815486cb8e92a33Jean-Michel Trivi        if (status < 0) {
155610254cc35f5cb7ebe2c7ef452815486cb8e92a33Jean-Michel Trivi            LOGE("Cannot start pcm playback");
155710254cc35f5cb7ebe2c7ef452815486cb8e92a33Jean-Michel Trivi            goto Error;
155810254cc35f5cb7ebe2c7ef452815486cb8e92a33Jean-Michel Trivi        }
155910254cc35f5cb7ebe2c7ef452815486cb8e92a33Jean-Michel Trivi
15605d89308f2e1252eff2743bf823bf558dbb0de2faDave Sparks        LOGV("acquire wakelock");
15615d89308f2e1252eff2743bf823bf558dbb0de2faDave Sparks        acquire_wake_lock(PARTIAL_WAKE_LOCK, kOutputWakelockStr);
156231923bb6797ec304d26395acf6d946ab8e44aa6eHK Chen        mStandby = false;
15632aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
15642aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
15652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    while (count) {
15662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        ssize_t written = ::write(mFd, p, count);
15672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (written >= 0) {
15682aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            count -= written;
15692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            p += written;
15702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        } else {
15712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            if (errno != EAGAIN) return written;
15722aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            mRetryCount++;
15732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            LOGW("EAGAIN - retry");
15742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
15752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
15762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
15772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return bytes;
15782aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
15792aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandError:
15802aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mFd >= 0) {
15812aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        ::close(mFd);
15822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mFd = -1;
15832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
15842aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // Simulate audio output timing in case of error
15852aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    usleep(bytes * 1000000 / frameSize() / sampleRate());
15862aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
15872aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return status;
15882aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
15892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
15902aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::AudioStreamOutMSM72xx::standby()
15912aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
15922aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    status_t status = NO_ERROR;
15932aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (!mStandby && mFd >= 0) {
15942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        ::close(mFd);
15952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mFd = -1;
15965d89308f2e1252eff2743bf823bf558dbb0de2faDave Sparks        LOGV("release wakelock");
15975d89308f2e1252eff2743bf823bf558dbb0de2faDave Sparks        release_wake_lock(kOutputWakelockStr);
15982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
15992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mStandby = true;
16002aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGI("AudioHardware pcm playback is going to standby.");
16012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return status;
16022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
16032aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
16042aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::AudioStreamOutMSM72xx::dump(int fd, const Vector<String16>& args)
16052aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
16062aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    const size_t SIZE = 256;
16072aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    char buffer[SIZE];
16082aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    String8 result;
16092aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append("AudioStreamOutMSM72xx::dump\n");
16102aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tsample rate: %d\n", sampleRate());
16112aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
16122aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize());
16132aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
16142aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tchannels: %d\n", channels());
16152aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
16162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tformat: %d\n", format());
16172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
16182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmHardware: %p\n", mHardware);
16192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
16202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmFd: %d\n", mFd);
16212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
16222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmStartCount: %d\n", mStartCount);
16232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
16242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmRetryCount: %d\n", mRetryCount);
16252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
16262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmStandby: %s\n", mStandby? "true": "false");
16272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
16282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    ::write(fd, result.string(), result.size());
16292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
16302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
16312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
16322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandbool AudioHardware::AudioStreamOutMSM72xx::checkStandby()
16332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
16342aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return mStandby;
16352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
16362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
16372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
16382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::AudioStreamOutMSM72xx::setParameters(const String8& keyValuePairs)
16392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
16402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    AudioParameter param = AudioParameter(keyValuePairs);
16412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    String8 key = String8(AudioParameter::keyRouting);
16422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    status_t status = NO_ERROR;
16432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    int device;
16442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("AudioStreamOutMSM72xx::setParameters() %s", keyValuePairs.string());
16452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
16462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (param.getInt(key, device) == NO_ERROR) {
16472aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mDevices = device;
16482aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGV("set output routing %x", mDevices);
16492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        status = mHardware->doRouting(NULL);
16502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        param.remove(key);
16512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
16522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
16532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (param.size()) {
16542aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        status = BAD_VALUE;
16552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
16562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return status;
16572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
16582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
16592aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandString8 AudioHardware::AudioStreamOutMSM72xx::getParameters(const String8& keys)
16602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
16612aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    AudioParameter param = AudioParameter(keys);
16622aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    String8 value;
16632aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    String8 key = String8(AudioParameter::keyRouting);
16642aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
16652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (param.get(key, value) == NO_ERROR) {
16662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGV("get routing %x", mDevices);
16672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        param.addInt(key, (int)mDevices);
16682aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
16692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
16702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("AudioStreamOutMSM72xx::getParameters() %s", param.toString().string());
16712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return param.toString();
16722aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
16732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
16742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
16752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland// ----------------------------------------------------------------------------
16762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
16772aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandAudioHardware::AudioStreamInMSM72xx::AudioStreamInMSM72xx() :
16782aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mHardware(0), mFd(-1), mState(AUDIO_INPUT_CLOSED), mRetryCount(0),
16792aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mFormat(AUDIO_HW_IN_FORMAT), mChannels(AUDIO_HW_IN_CHANNELS),
1680a4fe0167c6cad83d88b3bc56efa1ffad85b345b5Eric Laurent    mSampleRate(AUDIO_HW_IN_SAMPLERATE), mBufferSize(AUDIO_KERNEL_PCM_IN_BUFFERSIZE),
16812aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mAcoustics((AudioSystem::audio_in_acoustics)0), mDevices(0)
16822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
16832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
16842aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
16852aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::AudioStreamInMSM72xx::set(
16862aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        AudioHardware* hw, uint32_t devices, int *pFormat, uint32_t *pChannels, uint32_t *pRate,
16872aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        AudioSystem::audio_in_acoustics acoustic_flags)
16882aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
16892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (pFormat == 0 || *pFormat != AUDIO_HW_IN_FORMAT) {
16902aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        *pFormat = AUDIO_HW_IN_FORMAT;
16912aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return BAD_VALUE;
16922aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
16932aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (pRate == 0) {
16942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return BAD_VALUE;
16952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
16962aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    uint32_t rate = hw->getInputSampleRate(*pRate);
16972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (rate != *pRate) {
16982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        *pRate = rate;
16992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return BAD_VALUE;
17002aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
17012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
17022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (pChannels == 0 || (*pChannels != AudioSystem::CHANNEL_IN_MONO &&
17032aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        *pChannels != AudioSystem::CHANNEL_IN_STEREO)) {
17042aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        *pChannels = AUDIO_HW_IN_CHANNELS;
17052aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return BAD_VALUE;
17062aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
17072aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
17082aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mHardware = hw;
17092aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
17102aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("AudioStreamInMSM72xx::set(%d, %d, %u)", *pFormat, *pChannels, *pRate);
17112aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mFd >= 0) {
17122aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGE("Audio record already open");
17132aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return -EPERM;
17142aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
17152aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
17162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // open audio input device
17172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    status_t status = ::open("/dev/msm_pcm_in", O_RDWR);
17182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (status < 0) {
17192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGE("Cannot open /dev/msm_pcm_in errno: %d", errno);
17202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        goto Error;
17212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
17222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mFd = status;
17232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
17242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // configuration
17252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("get config");
17262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    struct msm_audio_config config;
17272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    status = ioctl(mFd, AUDIO_GET_CONFIG, &config);
17282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (status < 0) {
17292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGE("Cannot read config");
17302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        goto Error;
17312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
17322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
17332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("set config");
17342aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    config.channel_count = AudioSystem::popCount(*pChannels);
17352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    config.sample_rate = *pRate;
17362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    config.buffer_size = bufferSize();
17372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    config.buffer_count = 2;
17382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    config.codec_type = CODEC_TYPE_PCM;
17392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    status = ioctl(mFd, AUDIO_SET_CONFIG, &config);
17402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (status < 0) {
17412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGE("Cannot set config");
17422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (ioctl(mFd, AUDIO_GET_CONFIG, &config) == 0) {
17432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            if (config.channel_count == 1) {
17442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                *pChannels = AudioSystem::CHANNEL_IN_MONO;
17452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            } else {
17462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                *pChannels = AudioSystem::CHANNEL_IN_STEREO;
17472aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            }
17482aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            *pRate = config.sample_rate;
17492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
17502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        goto Error;
17512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
17522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
17532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("confirm config");
17542aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    status = ioctl(mFd, AUDIO_GET_CONFIG, &config);
17552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (status < 0) {
17562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGE("Cannot read config");
17572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        goto Error;
17582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
17592aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("buffer_size: %u", config.buffer_size);
17602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("buffer_count: %u", config.buffer_count);
17612aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("channel_count: %u", config.channel_count);
17622aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("sample_rate: %u", config.sample_rate);
17632aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
17642aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mDevices = devices;
17652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mFormat = AUDIO_HW_IN_FORMAT;
17662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mChannels = *pChannels;
17672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mSampleRate = config.sample_rate;
17682aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mBufferSize = config.buffer_size;
17692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
17702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    //mHardware->setMicMute_nosync(false);
17712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mState = AUDIO_INPUT_OPENED;
17722aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
17732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
17742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
17752aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandError:
17762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mFd >= 0) {
17772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        ::close(mFd);
17782aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mFd = -1;
17792aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
17802aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return status;
17812aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
17822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
17832aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandAudioHardware::AudioStreamInMSM72xx::~AudioStreamInMSM72xx()
17842aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
17852aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("AudioStreamInMSM72xx destructor");
17862aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    standby();
17872aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
17882aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
17892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandssize_t AudioHardware::AudioStreamInMSM72xx::read( void* buffer, ssize_t bytes)
17902aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
17912aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("AudioStreamInMSM72xx::read(%p, %ld)", buffer, bytes);
17922aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (!mHardware) return -1;
17932aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
17942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    size_t count = bytes;
17952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    uint8_t* p = static_cast<uint8_t*>(buffer);
17962aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
17972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mState < AUDIO_INPUT_OPENED) {
17982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        Mutex::Autolock lock(mHardware->mLock);
17992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (set(mHardware, mDevices, &mFormat, &mChannels, &mSampleRate, mAcoustics) != NO_ERROR) {
18002aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            return -1;
18012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
18022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
18032aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
18040f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    if (mState < AUDIO_INPUT_STARTED) {
18052aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mHardware->set_mRecordState(1);
1806956f7ba5ee0f087c91b5fefd2718dae30f8c1e29Eric Laurent        if (support_a1026 == 1) {
1807956f7ba5ee0f087c91b5fefd2718dae30f8c1e29Eric Laurent            mHardware->doAudience_A1026_Control(mHardware->get_mMode(), 1, mHardware->get_snd_dev());
18082aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
18097fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi        uint32_t acdb_id = mHardware->getACDB(MOD_REC, mHardware->get_snd_dev());
18107fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi        if (ioctl(mFd, AUDIO_START, &acdb_id)) {
18112aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            LOGE("Error starting record");
18122aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            return -1;
18132aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
18142aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGI("AUDIO_START: start kernel pcm_in driver.");
18152aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mState = AUDIO_INPUT_STARTED;
18162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
18172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
18182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    while (count) {
18192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        ssize_t bytesRead = ::read(mFd, buffer, count);
18202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (bytesRead >= 0) {
18212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            count -= bytesRead;
18222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            p += bytesRead;
18232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        } else {
18242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            if (errno != EAGAIN) return bytesRead;
18252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            mRetryCount++;
18262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            LOGW("EAGAIN - retrying");
18272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
18282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
18292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return bytes;
18302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
18312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
18322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::AudioStreamInMSM72xx::standby()
18332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
1834956f7ba5ee0f087c91b5fefd2718dae30f8c1e29Eric Laurent    if (mHardware) {
18352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mHardware->set_mRecordState(0);
18360f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        if (support_a1026 == 1) {
1837956f7ba5ee0f087c91b5fefd2718dae30f8c1e29Eric Laurent            mHardware->doAudience_A1026_Control(mHardware->get_mMode(), 0, mHardware->get_snd_dev());
18382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
18392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
18402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
18412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (!mHardware) return -1;
18422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mState > AUDIO_INPUT_CLOSED) {
18432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (mFd >= 0) {
18442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            ::close(mFd);
18452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            mFd = -1;
18462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
18472aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        //mHardware->checkMicMute();
18482aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mState = AUDIO_INPUT_CLOSED;
18492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
18502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGI("AudioHardware PCM record is going to standby.");
18512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
18522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
18532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
18542aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::AudioStreamInMSM72xx::dump(int fd, const Vector<String16>& args)
18552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
18562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    const size_t SIZE = 256;
18572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    char buffer[SIZE];
18582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    String8 result;
18592aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append("AudioStreamInMSM72xx::dump\n");
18602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tsample rate: %d\n", sampleRate());
18612aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
18622aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize());
18632aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
18642aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tchannels: %d\n", channels());
18652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
18662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tformat: %d\n", format());
18672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
18682aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmHardware: %p\n", mHardware);
18692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
18702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmFd count: %d\n", mFd);
18712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
18722aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmState: %d\n", mState);
18732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
18742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmRetryCount: %d\n", mRetryCount);
18752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
18762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    ::write(fd, result.string(), result.size());
18772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
18782aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
18792aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
18802aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::AudioStreamInMSM72xx::setParameters(const String8& keyValuePairs)
18812aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
18822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    AudioParameter param = AudioParameter(keyValuePairs);
18832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    status_t status = NO_ERROR;
18842aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    int device;
1885255bdedb2d7ebf4b14690776ff652df1de97fe95Eric Laurent    String8 key = String8(KEY_A1026_VR_MODE);
1886739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    int enabled;
18872aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("AudioStreamInMSM72xx::setParameters() %s", keyValuePairs.string());
18882aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
1889739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    // reading voice recognition mode parameter
1890255bdedb2d7ebf4b14690776ff652df1de97fe95Eric Laurent    if (param.getInt(key, enabled) == NO_ERROR) {
189108516fe50b023532d5a3010050970de28e14621bIliyan Malchev        LOGV("set vr_mode_enabled to %d", enabled);
189208516fe50b023532d5a3010050970de28e14621bIliyan Malchev        vr_mode_change = (vr_mode_enabled != enabled);
18939ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi        vr_mode_enabled = enabled;
1894739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        param.remove(key);
1895739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    }
1896739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi
1897739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    // reading routing parameter
1898255bdedb2d7ebf4b14690776ff652df1de97fe95Eric Laurent    key = String8(AudioParameter::keyRouting);
18992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (param.getInt(key, device) == NO_ERROR) {
19002aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGV("set input routing %x", device);
19012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (device & (device - 1)) {
19022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            status = BAD_VALUE;
19032aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        } else {
19042aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            mDevices = device;
19052aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            status = mHardware->doRouting(this);
19062aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
19072aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        param.remove(key);
19082aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
19092aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
19102aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (param.size()) {
19112aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        status = BAD_VALUE;
19122aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
19132aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return status;
19142aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
19152aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
19162aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandString8 AudioHardware::AudioStreamInMSM72xx::getParameters(const String8& keys)
19172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
19182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    AudioParameter param = AudioParameter(keys);
19192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    String8 value;
19202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    String8 key = String8(AudioParameter::keyRouting);
19212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
19222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (param.get(key, value) == NO_ERROR) {
19232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGV("get routing %x", mDevices);
19242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        param.addInt(key, (int)mDevices);
19252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
19262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
19272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("AudioStreamInMSM72xx::getParameters() %s", param.toString().string());
19282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return param.toString();
19292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
19302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
19312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland// ----------------------------------------------------------------------------
19322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
19332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandextern "C" AudioHardwareInterface* createAudioHardware(void) {
19342aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return new AudioHardware();
19352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
19362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
19372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}; // namespace android
1938