AudioHardware.cpp revision 58cf88a5a91d82ae2fb3e23365eaa4524a9cd089
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"
422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#include "a1026.h"
432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#define LOG_SND_RPC 0  // Set to 1 to log sound RPC's
462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#define TX_PATH (1)
472aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
482aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_CURRENT = 256;
492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_HANDSET = 0;
502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_SPEAKER = 1;
512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_BT = 3;
522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_CARKIT = 4;
532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_BT_EC_OFF = 45;
542aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_HEADSET = 2;
552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_HEADSET_AND_SPEAKER = 10;
562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_FM_HEADSET = 9;
572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_FM_SPEAKER = 11;
582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_NO_MIC_HEADSET = 8;
592aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_TTY_FULL = 5;
60da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurentstatic const uint32_t SND_DEVICE_HANDSET_BACK_MIC = 20;
61da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurentstatic const uint32_t SND_DEVICE_SPEAKER_BACK_MIC = 21;
62da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurentstatic const uint32_t SND_DEVICE_NO_MIC_HEADSET_BACK_MIC = 28;
6358cf88a5a91d82ae2fb3e23365eaa4524a9cd089Jean-Michel Trivistatic const uint32_t SND_DEVICE_HEADSET_AND_SPEAKER_BACK_MIC = 30;
642aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandnamespace android {
652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic int support_a1026 = 1;
662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic int fd_a1026 = -1;
672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic int old_pathid = -1;
682aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic int new_pathid = -1;
690f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurentstatic int curr_out_device = -1;
700f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurentstatic int curr_mic_device = -1;
712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic int voice_started = 0;
722aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic int fd_fm_device = -1;
7310254cc35f5cb7ebe2c7ef452815486cb8e92a33Jean-Michel Trivistatic int stream_volume = -300;
74739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi// use VR mode on inputs: 1 == VR mode enabled when selected, 0 = VR mode disabled when selected
7508516fe50b023532d5a3010050970de28e14621bIliyan Malchevstatic int vr_mode_enabled;
76739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivistatic bool vr_mode_change = false;
77739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivistatic int vr_uses_ns = 0;
78739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivistatic int enable1026 = 1;
7910254cc35f5cb7ebe2c7ef452815486cb8e92a33Jean-Michel Trivi
802aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandint errCount = 0;
810f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurentstatic void * acoustic;
822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandconst uint32_t AudioHardware::inputSamplingRates[] = {
832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000
842aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland};
855d89308f2e1252eff2743bf823bf558dbb0de2faDave Sparks
865d89308f2e1252eff2743bf823bf558dbb0de2faDave Sparks// ID string for audio wakelock
875d89308f2e1252eff2743bf823bf558dbb0de2faDave Sparksstatic const char kOutputWakelockStr[] = "AudioHardwareQSD";
885d89308f2e1252eff2743bf823bf558dbb0de2faDave Sparks
892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland// ----------------------------------------------------------------------------
902aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
912aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandAudioHardware::AudioHardware() :
920f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    mA1026Init(false), mInit(false), mMicMute(true),
930f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    mBluetoothNrec(true), mBluetoothIdTx(0),
94da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    mBluetoothIdRx(0), mOutput(0),
95da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    mNoiseSuppressionState(A1026_NS_STATE_AUTO)
962aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
970f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    int (*snd_get_num)();
980f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    int (*snd_get_bt_endpoint)(msm_bt_endpoint *);
990f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    int (*set_acoustic_parameters)();
1000f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent
1010f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    struct msm_bt_endpoint *ept;
1020f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent
1032aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    doA1026_init();
1040f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent
1050f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    acoustic =:: dlopen("/system/lib/libhtc_acoustic.so", RTLD_NOW);
1060f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    if (acoustic == NULL ) {
1070f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        LOGE("Could not open libhtc_acoustic.so");
1080f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        /* this is not really an error on non-htc devices... */
1090f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        mNumBTEndpoints = 0;
1100f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        mInit = true;
1110f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        return;
1120f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    }
1130f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    set_acoustic_parameters = (int (*)(void))::dlsym(acoustic, "set_acoustic_parameters");
1140f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    if ((*set_acoustic_parameters) == 0 ) {
1150f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        LOGE("Could not open set_acoustic_parameters()");
1160f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        return;
1170f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    }
1180f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent
1190f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    int rc = set_acoustic_parameters();
1200f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    if (rc < 0) {
1210f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        LOGE("Could not set acoustic parameters to share memory: %d", rc);
1220f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    }
1230f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent
1240f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    snd_get_num = (int (*)(void))::dlsym(acoustic, "snd_get_num");
1250f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    if ((*snd_get_num) == 0 ) {
1260f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        LOGE("Could not open snd_get_num()");
1270f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    }
1280f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent
1290f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    mNumBTEndpoints = snd_get_num();
1300f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    LOGD("mNumBTEndpoints = %d", mNumBTEndpoints);
1310f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    mBTEndpoints = new msm_bt_endpoint[mNumBTEndpoints];
1320f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    mInit = true;
1330f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    LOGV("constructed %d SND endpoints)", mNumBTEndpoints);
1340f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    ept = mBTEndpoints;
1350f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    snd_get_bt_endpoint = (int (*)(msm_bt_endpoint *))::dlsym(acoustic, "snd_get_bt_endpoint");
1360f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    if ((*snd_get_bt_endpoint) == 0 ) {
1370f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        LOGE("Could not open snd_get_bt_endpoint()");
1380f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        return;
1390f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    }
1400f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    snd_get_bt_endpoint(mBTEndpoints);
1410f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent
1420f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    for (int i = 0; i < mNumBTEndpoints; i++) {
1430f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        LOGE("BT name %s (tx,rx)=(%d,%d)", mBTEndpoints[i].name, mBTEndpoints[i].tx, mBTEndpoints[i].rx);
1440f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    }
1450f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent
146d1dc8c30a969ec3539fc21b940789b2f23197756Eric Laurent    // reset voice mode in case media_server crashed and restarted while in call
147d1dc8c30a969ec3539fc21b940789b2f23197756Eric Laurent    int fd = open("/dev/msm_audio_ctl", O_RDWR);
148d1dc8c30a969ec3539fc21b940789b2f23197756Eric Laurent    if (fd >= 0) {
149d1dc8c30a969ec3539fc21b940789b2f23197756Eric Laurent        ioctl(fd, AUDIO_STOP_VOICE, NULL);
150d1dc8c30a969ec3539fc21b940789b2f23197756Eric Laurent        close(fd);
151d1dc8c30a969ec3539fc21b940789b2f23197756Eric Laurent    }
152d1dc8c30a969ec3539fc21b940789b2f23197756Eric Laurent
153739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    vr_mode_change = false;
15408516fe50b023532d5a3010050970de28e14621bIliyan Malchev    vr_mode_enabled = 0;
155739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    enable1026 = 1;
156739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    char value[PROPERTY_VALUE_MAX];
157739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    // Check the system property to enable or not the special recording modes
158739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    property_get("media.a1026.enableA1026", value, "1");
159739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    enable1026 = atoi(value);
160739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    LOGV("Enable mode selection for A1026 is %d", enable1026);
161739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    // Check the system property for which VR mode to use
162739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    property_get("media.a1026.nsForVoiceRec", value, "0");
163739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    vr_uses_ns = atoi(value);
164739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    LOGV("Using Noise Suppression for Voice Rec is %d", vr_uses_ns);
165739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi
1662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mInit = true;
1672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
1682aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
1692aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandAudioHardware::~AudioHardware()
1702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
1712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    for (size_t index = 0; index < mInputs.size(); index++) {
1722aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        closeInputStream((AudioStreamIn*)mInputs[index]);
1732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
1742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mInputs.clear();
1752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    closeOutputStream((AudioStreamOut*)mOutput);
1762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mInit = false;
1772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
1782aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
1792aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::initCheck()
1802aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
1812aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return mInit ? NO_ERROR : NO_INIT;
1822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
1832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
1842aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandAudioStreamOut* AudioHardware::openOutputStream(
1852aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status)
1862aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
1872aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    { // scope for the lock
1882aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        Mutex::Autolock lock(mLock);
1892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
1902aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        // only one output stream allowed
1912aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (mOutput) {
1922aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            if (status) {
1932aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                *status = INVALID_OPERATION;
1942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            }
1952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            return 0;
1962aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
1972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
1982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        // create new output stream
1992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        AudioStreamOutMSM72xx* out = new AudioStreamOutMSM72xx();
2002aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        status_t lStatus = out->set(this, devices, format, channels, sampleRate);
2012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (status) {
2022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            *status = lStatus;
2032aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
2042aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (lStatus == NO_ERROR) {
2052aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            mOutput = out;
2062aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        } else {
2072aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            delete out;
2082aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
2092aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
2102aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return mOutput;
2112aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
2122aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2132aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandvoid AudioHardware::closeOutputStream(AudioStreamOut* out) {
2142aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    Mutex::Autolock lock(mLock);
2152aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mOutput == 0 || mOutput != out) {
2162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGW("Attempt to close invalid output stream");
2172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
2182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    else {
2192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        delete mOutput;
2202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mOutput = 0;
2212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
2222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
2232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2242aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandAudioStreamIn* AudioHardware::openInputStream(
2252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status,
2262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        AudioSystem::audio_in_acoustics acoustic_flags)
2272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
2282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // check for valid input source
2292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (!AudioSystem::isInputDevice((AudioSystem::audio_devices)devices)) {
2302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return 0;
2312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
2322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mLock.lock();
2342aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    AudioStreamInMSM72xx* in = new AudioStreamInMSM72xx();
2362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    status_t lStatus = in->set(this, devices, format, channels, sampleRate, acoustic_flags);
2372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (status) {
2382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        *status = lStatus;
2392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
2402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (lStatus != NO_ERROR) {
2412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mLock.unlock();
2422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        delete in;
2432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return 0;
2442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
2452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mInputs.add(in);
2472aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mLock.unlock();
2482aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return in;
2502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
2512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandvoid AudioHardware::closeInputStream(AudioStreamIn* in) {
2532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    Mutex::Autolock lock(mLock);
2542aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    ssize_t index = mInputs.indexOf((AudioStreamInMSM72xx *)in);
2562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (index < 0) {
2572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGW("Attempt to close invalid input stream");
2582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else {
2592aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mLock.unlock();
2602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        delete mInputs[index];
2612aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mLock.lock();
2622aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mInputs.removeAt(index);
2632aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
2642aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
2652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::setMode(int mode)
2672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
268739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    // VR mode is never used in a call and must be cleared when entering the IN_CALL mode
269739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    if (mode == AudioSystem::MODE_IN_CALL) {
27008516fe50b023532d5a3010050970de28e14621bIliyan Malchev        vr_mode_enabled = 0;
271739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    }
272739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi
2732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    status_t status = AudioHardwareBase::setMode(mode);
2742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (status == NO_ERROR) {
2752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        // make sure that doAudioRouteOrMute() is called by doRouting()
2762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        // even if the new device selected is the same as current one.
2772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mCurSndDevice = -1;
2782aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
2792aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return status;
2802aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
2812aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandbool AudioHardware::checkOutputStandby()
2832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
2842aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mOutput)
2852aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (!mOutput->checkStandby())
2862aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            return false;
2872aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2882aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return true;
2892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
2903cb8864598e72c04859f410bb03f242cf3965dbeHK Chenstatic status_t set_mic_mute(bool _mute)
2912aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
2923cb8864598e72c04859f410bb03f242cf3965dbeHK Chen    uint32_t mute = _mute;
2933cb8864598e72c04859f410bb03f242cf3965dbeHK Chen    int fd = -1;
2942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    fd = open("/dev/msm_audio_ctl", O_RDWR);
2952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (fd < 0) {
2962aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGE("Cannot open msm_audio_ctl device\n");
2972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return -1;
2982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
2992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGD("Setting mic mute to %d\n", mute);
3003cb8864598e72c04859f410bb03f242cf3965dbeHK Chen    if (ioctl(fd, AUDIO_SET_MUTE, &mute)) {
3012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGE("Cannot set mic mute on current device\n");
3022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        close(fd);
3032aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return -1;
3042aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
3052aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    close(fd);
3062aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
3072aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
3082aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
3092aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::setMicMute(bool state)
3102aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
3112aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    Mutex::Autolock lock(mLock);
3122aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return setMicMute_nosync(state);
3132aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
3142aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
3152aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland// always call with mutex held
3162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::setMicMute_nosync(bool state)
3172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
3182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mMicMute != state) {
3192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mMicMute = state;
3202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return set_mic_mute(mMicMute); //always set current TX device
3212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
3222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
3232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
3242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
3252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::getMicMute(bool* state)
3262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
3272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    *state = mMicMute;
3282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
3292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
3302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
3312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::setParameters(const String8& keyValuePairs)
3322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
3332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    AudioParameter param = AudioParameter(keyValuePairs);
3342aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    String8 value;
3352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    String8 key;
3362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    const char BT_NREC_KEY[] = "bt_headset_nrec";
3372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    const char BT_NAME_KEY[] = "bt_headset_name";
3382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    const char BT_NREC_VALUE_ON[] = "on";
3392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
3402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
3412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("setParameters() %s", keyValuePairs.string());
3422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
3432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (keyValuePairs.length() == 0) return BAD_VALUE;
3442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
3452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    key = String8(BT_NREC_KEY);
3462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (param.get(key, value) == NO_ERROR) {
3472aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (value == BT_NREC_VALUE_ON) {
3482aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            mBluetoothNrec = true;
3492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        } else {
3502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            mBluetoothNrec = false;
3512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            LOGI("Turning noise reduction and echo cancellation off for BT "
3522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                 "headset");
3532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
3542aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
3552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    key = String8(BT_NAME_KEY);
3562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (param.get(key, value) == NO_ERROR) {
3570f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        mBluetoothIdTx = 0;
3580f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        mBluetoothIdRx = 0;
3590f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        for (int i = 0; i < mNumBTEndpoints; i++) {
3600f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            if (!strcasecmp(value.string(), mBTEndpoints[i].name)) {
3610f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                mBluetoothIdTx = mBTEndpoints[i].tx;
3620f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                mBluetoothIdRx = mBTEndpoints[i].rx;
3632aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                LOGI("Using custom acoustic parameters for %s", value.string());
3642aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                break;
3652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            }
3662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
3670f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        if (mBluetoothIdTx == 0) {
3682aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            LOGI("Using default acoustic parameters "
3692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                 "(%s not in acoustic database)", value.string());
3702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
3710f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        doRouting(NULL);
3722aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
373da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    key = String8("noise_suppression");
374da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    if (param.get(key, value) == NO_ERROR) {
375da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent        if (support_a1026 == 1) {
376da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            int noiseSuppressionState;
377da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            if (value == "off") {
378da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                noiseSuppressionState = A1026_NS_STATE_OFF;
379da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            } else if (value == "auto") {
380da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                noiseSuppressionState = A1026_NS_STATE_AUTO;
381da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            } else if (value == "far_talk") {
382da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                noiseSuppressionState = A1026_NS_STATE_FT;
383da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            } else if (value == "close_talk") {
384da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                noiseSuppressionState = A1026_NS_STATE_CT;
385da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            } else {
386da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                return BAD_VALUE;
387da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            }
388da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent
389da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            if (noiseSuppressionState != mNoiseSuppressionState) {
390da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                if (!mA1026Init) {
391da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                    LOGW("Audience A1026 not initialized.\n");
392da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                    return INVALID_OPERATION;
393da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                }
394da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent
395da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                if (fd_a1026 < 0) {
396da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                    fd_a1026 = open("/dev/audience_a1026", O_RDWR);
397da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                    if (fd_a1026 < 0) {
398da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                        LOGE("Cannot open audience_a1026 device (%d)\n", fd_a1026);
399da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                        return -1;
400da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                    }
401da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                }
402da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                LOGV("Setting noise suppression %s", value.string());
403da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                mA1026Lock.lock();
404da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                int rc = ioctl(fd_a1026, A1026_SET_NS_STATE, &noiseSuppressionState);
405da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                if (!rc) {
406da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                    mNoiseSuppressionState = noiseSuppressionState;
407da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                } else {
408da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                    LOGE("Failed to set noise suppression %s", value.string());
409da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                }
410da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                mA1026Lock.unlock();
411da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            }
412da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent        } else {
413da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            return INVALID_OPERATION;
414da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent        }
415da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent     }
416da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent
4172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
4182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
4192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
4202aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandString8 AudioHardware::getParameters(const String8& keys)
4212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
422da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    AudioParameter request = AudioParameter(keys);
423da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    AudioParameter reply = AudioParameter();
424da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    String8 value;
425da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    String8 key;
426da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent
427da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    LOGV("getParameters() %s", keys.string());
428da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent
429da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    key = "noise_suppression";
430da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    if (request.get(key, value) == NO_ERROR) {
431da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent        switch(mNoiseSuppressionState) {
432da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent        case A1026_NS_STATE_OFF:
433da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            value = "off";
434da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            break;
435da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent        case A1026_NS_STATE_AUTO:
436da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            value = "auto";
437da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            break;
438da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent        case A1026_NS_STATE_FT:
439da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            value = "far_talk";
440da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            break;
441da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent        case A1026_NS_STATE_CT:
442da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            value = "close_talk";
443da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            break;
444da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent        }
445da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent        reply.add(key, value);
446da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    }
447da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent
448da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    return reply.toString();
4492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
4502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
4512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
4522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic unsigned calculate_audpre_table_index(unsigned index)
4532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
4542aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    switch (index) {
4552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        case 48000:    return SAMP_RATE_INDX_48000;
4562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        case 44100:    return SAMP_RATE_INDX_44100;
4572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        case 32000:    return SAMP_RATE_INDX_32000;
4582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        case 24000:    return SAMP_RATE_INDX_24000;
4592aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        case 22050:    return SAMP_RATE_INDX_22050;
4602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        case 16000:    return SAMP_RATE_INDX_16000;
4612aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        case 12000:    return SAMP_RATE_INDX_12000;
4622aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        case 11025:    return SAMP_RATE_INDX_11025;
4632aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        case 8000:    return SAMP_RATE_INDX_8000;
4642aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        default:     return -1;
4652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
4662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
4672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandsize_t AudioHardware::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
4682aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
4692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (format != AudioSystem::PCM_16_BIT) {
4702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGW("getInputBufferSize bad format: %d", format);
4712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return 0;
4722aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
4732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (channelCount < 1 || channelCount > 2) {
4742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGW("getInputBufferSize bad channel count: %d", channelCount);
4752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return 0;
4762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
4772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
4782aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return 2048*channelCount;
4792aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
4802aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
4812aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic status_t set_volume_rpc(uint32_t volume)
4822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
4832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    int fd = -1;
4842aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    fd = open("/dev/msm_audio_ctl", O_RDWR);
4852aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (fd < 0) {
4862aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGE("Cannot open msm_audio_ctl device\n");
4872aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return -1;
4882aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
4892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    volume *= 20; //percentage
4902aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGD("Setting in-call volume to %d\n", volume);
4912aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (ioctl(fd, AUDIO_SET_VOLUME, &volume)) {
4922aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGW("Cannot set volume on current device\n");
4932aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
4942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    close(fd);
4952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
4962aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
4972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
4982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::setVoiceVolume(float v)
4992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
5002aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (v < 0.0) {
5012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGW("setVoiceVolume(%f) under 0.0, assuming 0.0\n", v);
5022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        v = 0.0;
5032aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else if (v > 1.0) {
5042aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGW("setVoiceVolume(%f) over 1.0, assuming 1.0\n", v);
5052aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        v = 1.0;
5062aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
5072aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
5082aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    int vol = lrint(v * 5.0);
5092aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGD("setVoiceVolume(%f)\n", v);
5102aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGI("Setting in-call volume to %d (available range is 0 to 5)\n", vol);
5112aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
5122aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    Mutex::Autolock lock(mLock);
5132aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    set_volume_rpc(vol); //always set current device
5142aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
5152aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
5162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
5172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::setMasterVolume(float v)
5182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
5192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    Mutex::Autolock lock(mLock);
5202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    int vol = ceil(v * 5.0);
5212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGI("Set master volume to %d.\n", vol);
5222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // We return an error code here to let the audioflinger do in-software
5232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // volume on top of the maximum volume that we set through the SND API.
5242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // return error - software mixer will handle it
5252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return -1;
5262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
5272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
5282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic status_t do_route_audio_dev_ctrl(uint32_t device, bool inCall)
5292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
5302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    int out_device = 0, mic_device = 0;
5312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    int fd = 0;
5322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
5332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (device == SND_DEVICE_CURRENT)
5342aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        goto Incall;
5352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
5362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // hack -- kernel needs to put these in include file
5372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGD("Switching audio device to ");
5382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (device == SND_DEVICE_HANDSET) {
5392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           out_device = HANDSET_SPKR;
5402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           mic_device = HANDSET_MIC;
5412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           LOGD("Handset");
5422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else if ((device  == SND_DEVICE_BT) || (device == SND_DEVICE_BT_EC_OFF)) {
5432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           out_device = BT_SCO_SPKR;
5442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           mic_device = BT_SCO_MIC;
5452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           LOGD("BT Headset");
546da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    } else if (device == SND_DEVICE_SPEAKER ||
547da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent               device == SND_DEVICE_SPEAKER_BACK_MIC) {
5482aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           out_device = SPKR_PHONE_MONO;
5492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           mic_device = SPKR_PHONE_MIC;
5502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           LOGD("Speakerphone");
5512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else if (device == SND_DEVICE_HEADSET) {
5522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           out_device = HEADSET_SPKR_STEREO;
5532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           mic_device = HEADSET_MIC;
5542aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           LOGD("Stereo Headset");
5552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else if (device == SND_DEVICE_HEADSET_AND_SPEAKER) {
5562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           out_device = SPKR_PHONE_HEADSET_STEREO;
5572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           mic_device = HEADSET_MIC;
5582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           LOGD("Stereo Headset + Speaker");
55958cf88a5a91d82ae2fb3e23365eaa4524a9cd089Jean-Michel Trivi    } else if (device == SND_DEVICE_HEADSET_AND_SPEAKER_BACK_MIC) {
56058cf88a5a91d82ae2fb3e23365eaa4524a9cd089Jean-Michel Trivi           out_device = SPKR_PHONE_HEADSET_STEREO;
56158cf88a5a91d82ae2fb3e23365eaa4524a9cd089Jean-Michel Trivi           mic_device = SPKR_PHONE_MIC;
56258cf88a5a91d82ae2fb3e23365eaa4524a9cd089Jean-Michel Trivi           LOGD("Stereo Headset + Speaker and back mic");
5632aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else if (device == SND_DEVICE_NO_MIC_HEADSET) {
5642aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           out_device = HEADSET_SPKR_STEREO;
5652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           mic_device = HANDSET_MIC;
5662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           LOGD("No microphone Wired Headset");
567da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    } else if (device == SND_DEVICE_NO_MIC_HEADSET_BACK_MIC) {
568da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent           out_device = HEADSET_SPKR_STEREO;
569da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent           mic_device = SPKR_PHONE_MIC;
570da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent           LOGD("No microphone Wired Headset and back mic");
571da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    } else if (device == SND_DEVICE_HANDSET_BACK_MIC) {
572da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent           out_device = HANDSET_SPKR;
573da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent           mic_device = SPKR_PHONE_MIC;
574da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent           LOGD("Handset and back mic");
5752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else if (device == SND_DEVICE_FM_HEADSET) {
5762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           out_device = FM_HEADSET;
5772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           mic_device = HEADSET_MIC;
5782aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           LOGD("Stereo FM headset");
5792aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else if (device == SND_DEVICE_FM_SPEAKER) {
5802aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           out_device = FM_SPKR;
5812aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           mic_device = HEADSET_MIC;
5822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           LOGD("Stereo FM speaker");
5832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else {
5842aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           LOGE("unknown device %d", device);
5852aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           return -1;
5862aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
5872aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
5882aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#if 0 //Add for FM support
5892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (out_device == FM_HEADSET ||
5902aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        out_device == FM_SPKR) {
5912aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (fd_fm_device < 0) {
5922aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            fd_fm_device = open("/dev/msm_htc_fm", O_RDWR);
5932aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            if (fd_fm_device < 0) {
5942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                LOGE("Cannot open msm_htc_fm device");
5952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                return -1;
5962aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            }
5972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            LOGD("Opened msm_htc_fm for FM radio");
5982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
5992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else if (fd_fm_device >= 0) {
6002aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        close(fd_fm_device);
6012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        fd_fm_device = -1;
6022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGD("Closed msm_htc_fm after FM radio");
6032aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
6042aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#endif
6052aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
6062aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    fd = open("/dev/msm_audio_ctl", O_RDWR);
6072aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (fd < 0)        {
6082aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland       LOGE("Cannot open msm_audio_ctl");
6092aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland       return -1;
6102aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
6112aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (ioctl(fd, AUDIO_SWITCH_DEVICE, &out_device)) {
6122aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland       LOGE("Cannot switch audio device");
6132aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland       close(fd);
6142aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland       return -1;
6152aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
6162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (ioctl(fd, AUDIO_SWITCH_DEVICE, &mic_device)) {
6172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland       LOGE("Cannot switch mic device");
6182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland       close(fd);
6192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland       return -1;
6202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
6210f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    curr_out_device = out_device;
6220f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    curr_mic_device = mic_device;
6232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
6242aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandIncall:
6252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (inCall == true && !voice_started) {
6262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	if (fd < 0) {
6272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            fd = open("/dev/msm_audio_ctl", O_RDWR);
6282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
6292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            if (fd < 0) {
6302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                LOGE("Cannot open msm_audio_ctl");
6312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                return -1;
6322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            }
6332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
6342aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (ioctl(fd, AUDIO_START_VOICE, NULL)) {
6352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland               LOGE("Cannot start voice");
6362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland               close(fd);
6372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland               return -1;
6382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
6392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGD("Voice Started!!");
6402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        voice_started = 1;
6412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
6422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    else if (inCall == false && voice_started) {
6432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (fd < 0) {
6442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            fd = open("/dev/msm_audio_ctl", O_RDWR);
6452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
6462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            if (fd < 0) {
6472aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                LOGE("Cannot open msm_audio_ctl");
6482aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                return -1;
6492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            }
6502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
6512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (ioctl(fd, AUDIO_STOP_VOICE, NULL)) {
6522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland               LOGE("Cannot stop voice");
6532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland               close(fd);
6542aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland               return -1;
6552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
6562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGD("Voice Stopped!!");
6572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        voice_started = 0;
6582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
6592aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
6602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    close(fd);
6612aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
6622aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
6632aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
6642aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
6652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland// always call with mutex held
6662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::doAudioRouteOrMute(uint32_t device)
6672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
668f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi    if (support_a1026 == 1)
669f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi            doAudience_A1026_Control(mMode, mRecordState, device);
670f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi
6712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (device == (uint32_t)SND_DEVICE_BT || device == (uint32_t)SND_DEVICE_CARKIT) {
6720f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        if (!mBluetoothNrec) {
6732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            device = SND_DEVICE_BT_EC_OFF;
6742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
6752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
6762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return do_route_audio_dev_ctrl(device, mMode == AudioSystem::MODE_IN_CALL);
6772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
6782aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
6792aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::get_mMode(void)
6802aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
6812aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return mMode;
6822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
6832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
6842aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::get_mRoutes(void)
6852aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
6862aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return mRoutes[mMode];
6872aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
6882aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
6892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::set_mRecordState(bool onoff)
6902aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
6912aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mRecordState = onoff;
6922aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return 0;
6932aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
6942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
6952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::doA1026_init(void)
6962aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
6972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    struct a1026img fwimg;
6982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    char char_tmp = 0;
69908516fe50b023532d5a3010050970de28e14621bIliyan Malchev    unsigned char local_vpimg_buf[A1026_MAX_FW_SIZE], *ptr = local_vpimg_buf;
70008516fe50b023532d5a3010050970de28e14621bIliyan Malchev    int rc = 0, fw_fd = -1;
70108516fe50b023532d5a3010050970de28e14621bIliyan Malchev    ssize_t nr;
70208516fe50b023532d5a3010050970de28e14621bIliyan Malchev    size_t remaining;
70308516fe50b023532d5a3010050970de28e14621bIliyan Malchev    struct stat fw_stat;
7042aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
70508516fe50b023532d5a3010050970de28e14621bIliyan Malchev    static const char *const fn = "/system/etc/vpimg";
70608516fe50b023532d5a3010050970de28e14621bIliyan Malchev    static const char *const path = "/dev/audience_a1026";
70708516fe50b023532d5a3010050970de28e14621bIliyan Malchev
70808516fe50b023532d5a3010050970de28e14621bIliyan Malchev    if (fd_a1026 < 0)
70908516fe50b023532d5a3010050970de28e14621bIliyan Malchev        fd_a1026 = open(path, O_RDWR | O_NONBLOCK, 0);
7102aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
7112aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (fd_a1026 < 0) {
71208516fe50b023532d5a3010050970de28e14621bIliyan Malchev        LOGE("Cannot open %s %d\n", path, fd_a1026);
71308516fe50b023532d5a3010050970de28e14621bIliyan Malchev        support_a1026 = 0;
71408516fe50b023532d5a3010050970de28e14621bIliyan Malchev        goto open_drv_err;
7152aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
7162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
71708516fe50b023532d5a3010050970de28e14621bIliyan Malchev    fw_fd = open(fn, O_RDONLY);
71808516fe50b023532d5a3010050970de28e14621bIliyan Malchev    if (fw_fd < 0) {
7192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGE("Fail to open %s\n", fn);
7202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        goto ld_img_error;
721956f7ba5ee0f087c91b5fefd2718dae30f8c1e29Eric Laurent    } else LOGI("open a1026 firmware success\n");
7222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
72308516fe50b023532d5a3010050970de28e14621bIliyan Malchev    rc = fstat(fw_fd, &fw_stat);
72408516fe50b023532d5a3010050970de28e14621bIliyan Malchev    if (rc < 0) {
72508516fe50b023532d5a3010050970de28e14621bIliyan Malchev        LOGE("Cannot stat file %s: %s\n", fn, strerror(errno));
72608516fe50b023532d5a3010050970de28e14621bIliyan Malchev        goto ld_img_error;
72708516fe50b023532d5a3010050970de28e14621bIliyan Malchev    }
72808516fe50b023532d5a3010050970de28e14621bIliyan Malchev
72908516fe50b023532d5a3010050970de28e14621bIliyan Malchev    remaining = (int)fw_stat.st_size;
7302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
73108516fe50b023532d5a3010050970de28e14621bIliyan Malchev    LOGI("Firmware %s size %d\n", fn, remaining);
73208516fe50b023532d5a3010050970de28e14621bIliyan Malchev
73308516fe50b023532d5a3010050970de28e14621bIliyan Malchev    if (remaining > sizeof(local_vpimg_buf)) {
73408516fe50b023532d5a3010050970de28e14621bIliyan Malchev        LOGE("File %s size %d exceeds internal limit %d\n",
73508516fe50b023532d5a3010050970de28e14621bIliyan Malchev             fn, remaining, sizeof(local_vpimg_buf));
73608516fe50b023532d5a3010050970de28e14621bIliyan Malchev        goto ld_img_error;
7372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
7382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
73908516fe50b023532d5a3010050970de28e14621bIliyan Malchev    while (remaining) {
74008516fe50b023532d5a3010050970de28e14621bIliyan Malchev        nr = read(fw_fd, ptr, remaining);
74108516fe50b023532d5a3010050970de28e14621bIliyan Malchev        if (nr < 0) {
74208516fe50b023532d5a3010050970de28e14621bIliyan Malchev            LOGE("Error reading firmware: %s\n", strerror(errno));
74308516fe50b023532d5a3010050970de28e14621bIliyan Malchev            goto ld_img_error;
74408516fe50b023532d5a3010050970de28e14621bIliyan Malchev        }
74508516fe50b023532d5a3010050970de28e14621bIliyan Malchev        else if (!nr) {
74608516fe50b023532d5a3010050970de28e14621bIliyan Malchev            if (remaining)
74708516fe50b023532d5a3010050970de28e14621bIliyan Malchev                LOGW("EOF reading firmware %s while %d bytes remain\n",
74808516fe50b023532d5a3010050970de28e14621bIliyan Malchev                     fn, remaining);
74908516fe50b023532d5a3010050970de28e14621bIliyan Malchev            break;
75008516fe50b023532d5a3010050970de28e14621bIliyan Malchev        }
75108516fe50b023532d5a3010050970de28e14621bIliyan Malchev        remaining -= nr;
75208516fe50b023532d5a3010050970de28e14621bIliyan Malchev        ptr += nr;
75308516fe50b023532d5a3010050970de28e14621bIliyan Malchev    }
75408516fe50b023532d5a3010050970de28e14621bIliyan Malchev
75508516fe50b023532d5a3010050970de28e14621bIliyan Malchev    close (fw_fd);
75608516fe50b023532d5a3010050970de28e14621bIliyan Malchev    fw_fd = -1;
75708516fe50b023532d5a3010050970de28e14621bIliyan Malchev
7582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    fwimg.buf = local_vpimg_buf;
75908516fe50b023532d5a3010050970de28e14621bIliyan Malchev    fwimg.img_size = (int)(fw_stat.st_size - remaining);
76008516fe50b023532d5a3010050970de28e14621bIliyan Malchev    LOGI("Total %d bytes put to user space buffer.\n", fwimg.img_size);
7612aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
7622aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    rc = ioctl(fd_a1026, A1026_BOOTUP_INIT, &fwimg);
7632aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (!rc) {
7642aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGI("audience_a1026 init OK\n");
7652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mA1026Init = 1;
7662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else
7672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGE("audience_a1026 init failed\n");
7682aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
7692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandld_img_error:
77008516fe50b023532d5a3010050970de28e14621bIliyan Malchev    if (fw_fd >= 0)
77108516fe50b023532d5a3010050970de28e14621bIliyan Malchev        close(fw_fd);
7722aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    close(fd_a1026);
7732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandopen_drv_err:
7742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    fd_a1026 = -1;
7752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return rc;
7762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
7772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
7782aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::get_snd_dev(void)
7792aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
7802aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    Mutex::Autolock lock(mLock);
7817161d052ce69228825bd5deca3bfa4a213a99f06HK Chen    return mCurSndDevice;
7822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
7832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
7840f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurentstatus_t AudioHardware::updateBT(void)
7850f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent{
7860f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    int fd = 0;
7870f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    uint32_t id[2];
7880f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent
7890f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    fd = open("/dev/msm_audio_ctl", O_RDWR);
7900f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    if (fd < 0)        {
7910f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent       LOGE("Cannot open msm_audio_ctl");
7920f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent       return -1;
7930f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    }
7940f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    int rc = 0;
795956f7ba5ee0f087c91b5fefd2718dae30f8c1e29Eric Laurent    if (mBluetoothIdRx != 0) {
7960f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        id[0] = mBluetoothIdRx;
7970f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        id[1] = curr_out_device;
7980f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        LOGE("(mBluetoothIdRx, curr_out_device) = (%d, %d)", mBluetoothIdRx, curr_out_device);
7990f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        rc = ioctl(fd, AUDIO_UPDATE_ACDB, &id);
8000f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        if (rc) {
8010f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent           LOGE("Cannot update RX ACDB %d, rc=%d", mBluetoothIdRx, rc);
8020f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent           close(fd);
8030f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent           return -1;
8040f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        } else
8050f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent           LOGD("update TX ACDB %d success", mBluetoothIdRx);
8060f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    }
8070f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent
808956f7ba5ee0f087c91b5fefd2718dae30f8c1e29Eric Laurent    if (mBluetoothIdTx != 0) {
8090f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        id[0] = mBluetoothIdTx;
8100f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        id[1] = curr_mic_device;
8110f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        LOGE("(mBluetoothIdTx, curr_out_device) = (%d, %d)", mBluetoothIdTx, curr_out_device);
8120f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        rc = ioctl(fd, AUDIO_UPDATE_ACDB, &id);
8130f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        if (rc) {
8140f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent           LOGE("Cannot update TX ACDB %d, rc = %d", mBluetoothIdTx, rc);
8150f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent           close(fd);
8160f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent           return -1;
8170f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        } else
8180f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent           LOGD("update TX ACDB %d success", mBluetoothIdTx);
8190f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    }
8200f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    close(fd);
8210f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    return 0;
8220f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent}
8230f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent
8240f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent// always call with mutex held
8250f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurentstatus_t AudioHardware::updateACDB(void)
8260f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent{
82763af0f3cbd387e97bcaca82d1e22787c224d6430Jean-Michel Trivi
8280f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    int fd = 0;
8290f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    int acdb_id = -1;
8300f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    uint32_t id[2];
8310f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent
8320f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    fd = open("/dev/msm_audio_ctl", O_RDWR);
8330f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    if (fd < 0)        {
8340f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent       LOGE("Cannot open msm_audio_ctl");
8350f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent       return -1;
8360f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    }
8370f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent
8380f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    if (mMode == AudioSystem::MODE_IN_CALL) {
8390f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        LOGD("skip update ACDB due to in-call");
8400f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        close(fd);
8410f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        return 0;
8420f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    }
8430f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent
8440f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    //update RX acdb parameters.
8450f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    if (!checkOutputStandby()) {
8460f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        switch (mCurSndDevice) {
8470f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            case SND_DEVICE_HEADSET:
8480f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            case SND_DEVICE_NO_MIC_HEADSET:
849da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            case SND_DEVICE_NO_MIC_HEADSET_BACK_MIC:
8500f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            case SND_DEVICE_FM_HEADSET:
8510f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                acdb_id = ACDB_ID_HEADSET_PLAYBACK;
8520f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                break;
8530f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            case SND_DEVICE_SPEAKER:
8540f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            case SND_DEVICE_FM_SPEAKER:
855da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            case SND_DEVICE_SPEAKER_BACK_MIC:
8560f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                acdb_id = ACDB_ID_SPKR_PLAYBACK;
8570f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                break;
8580f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            case SND_DEVICE_HEADSET_AND_SPEAKER:
85958cf88a5a91d82ae2fb3e23365eaa4524a9cd089Jean-Michel Trivi            case SND_DEVICE_HEADSET_AND_SPEAKER_BACK_MIC:
8600f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                acdb_id = ACDB_ID_HEADSET_RINGTONE_PLAYBACK;
8610f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                break;
8620f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            default:
8630f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                break;
8640f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        }
8650f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    }
8660f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    if (acdb_id != -1) {
8670f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        id[0] = acdb_id;
8680f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        id[1] = curr_out_device;
8690f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        if (ioctl(fd, AUDIO_UPDATE_ACDB, &id)) {
8700f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent           LOGE("Cannot update RX ACDB %d", acdb_id);
8710f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent           close(fd);
8720f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent           return -1;
8730f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        } else
8740f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent           LOGD("update RX ACDB %d success", acdb_id);
8750f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    }
8760f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent
8770f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    //update TX acdb parameters.
8780f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    acdb_id = -1;
8790f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    if (mRecordState) {
8800f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        switch (mCurSndDevice) {
8810f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            case SND_DEVICE_HEADSET:
8820f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            case SND_DEVICE_FM_HEADSET:
8830f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            case SND_DEVICE_FM_SPEAKER:
88458cf88a5a91d82ae2fb3e23365eaa4524a9cd089Jean-Michel Trivi            case SND_DEVICE_HEADSET_AND_SPEAKER:
8850f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                acdb_id = ACDB_ID_EXT_MIC_REC;
8860f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                break;
8870f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            case SND_DEVICE_HANDSET:
8880f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            case SND_DEVICE_NO_MIC_HEADSET:
8890f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            case SND_DEVICE_SPEAKER:
89008516fe50b023532d5a3010050970de28e14621bIliyan Malchev                if (vr_mode_enabled == 0) {
89163af0f3cbd387e97bcaca82d1e22787c224d6430Jean-Michel Trivi                    acdb_id = ACDB_ID_INT_MIC_REC;
89263af0f3cbd387e97bcaca82d1e22787c224d6430Jean-Michel Trivi                } else {
89363af0f3cbd387e97bcaca82d1e22787c224d6430Jean-Michel Trivi                    acdb_id = ACDB_ID_INT_MIC_VR;
89463af0f3cbd387e97bcaca82d1e22787c224d6430Jean-Michel Trivi                }
89563af0f3cbd387e97bcaca82d1e22787c224d6430Jean-Michel Trivi                break;
896da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            case SND_DEVICE_SPEAKER_BACK_MIC:
897da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            case SND_DEVICE_NO_MIC_HEADSET_BACK_MIC:
898da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            case SND_DEVICE_HANDSET_BACK_MIC:
89958cf88a5a91d82ae2fb3e23365eaa4524a9cd089Jean-Michel Trivi            case SND_DEVICE_HEADSET_AND_SPEAKER_BACK_MIC:
90063af0f3cbd387e97bcaca82d1e22787c224d6430Jean-Michel Trivi                acdb_id = ACDB_ID_CAMCORDER;
9010f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                break;
9020f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            default:
9030f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                break;
9040f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        }
9050f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    }
9060f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    if (acdb_id != -1) {
9070f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        id[0] = acdb_id;
9080f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        id[1] = curr_mic_device;
9090f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        if (ioctl(fd, AUDIO_UPDATE_ACDB, &id)) {
9100f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent           LOGE("Cannot update TX ACDB %d", acdb_id);
9110f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent           close(fd);
9120f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent           return -1;
9130f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        } else
9140f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent           LOGD("update TX ACDB %d success", acdb_id);
9150f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    }
9160f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    close(fd);
9170f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    return 0;
9180f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent}
9190f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent
9202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::doAudience_A1026_Control(int Mode, bool Record, uint32_t Routes)
9212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
9222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    int rc = 0;
9230f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    int retry = 4;
9242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
9252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (!mA1026Init) {
9262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	LOGW("Audience A1026 not initialized.\n");
9272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	return NO_INIT;
9282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
9292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
9302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (fd_a1026 < 0) {
9312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        fd_a1026 = open("/dev/audience_a1026", O_RDWR);
9322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (fd_a1026 < 0) {
9332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            LOGE("Cannot open audience_a1026 device (%d)\n", fd_a1026);
9342aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            return -1;
9352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	}
9362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
9372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
9382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mA1026Lock.lock();
9392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
9402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if ((Mode < AudioSystem::MODE_CURRENT) || (Mode >= AudioSystem::NUM_MODES)) {
9412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGW("Illegal value: doAudience_A1026_Control(%d, %u, %u)", Mode, Record, Routes);
9422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mA1026Lock.unlock();
9432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return BAD_VALUE;
9442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
9452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
9462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (Mode == AudioSystem::MODE_IN_CALL) {
9472aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (Record == 1) {
9482aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	    switch (Routes) {
9492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        case SND_DEVICE_HANDSET:
9502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        case SND_DEVICE_NO_MIC_HEADSET:
951da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent	            //TODO: what do we do for camcorder when in call?
952da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent	        case SND_DEVICE_NO_MIC_HEADSET_BACK_MIC:
953da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent	        case SND_DEVICE_HANDSET_BACK_MIC:
9544bcd5b16c66bc5c2bffe232f15f5cb83aea18318Jean-Michel Trivi                    new_pathid = A1026_PATH_INCALL_RECEIVER;
95563af0f3cbd387e97bcaca82d1e22787c224d6430Jean-Michel Trivi                    LOGV("A1026 control: new path is A1026_PATH_INCALL_RECEIVER");
9562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                    break;
9572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                case SND_DEVICE_HEADSET:
9582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                case SND_DEVICE_HEADSET_AND_SPEAKER:
9592aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                case SND_DEVICE_FM_HEADSET:
9602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                case SND_DEVICE_FM_SPEAKER:
96158cf88a5a91d82ae2fb3e23365eaa4524a9cd089Jean-Michel Trivi                case SND_DEVICE_HEADSET_AND_SPEAKER_BACK_MIC:
9624bcd5b16c66bc5c2bffe232f15f5cb83aea18318Jean-Michel Trivi	            new_pathid = A1026_PATH_INCALL_HEADSET;
96363af0f3cbd387e97bcaca82d1e22787c224d6430Jean-Michel Trivi	            LOGV("A1026 control: new path is A1026_PATH_INCALL_HEADSET");
9642aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            break;
9652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        case SND_DEVICE_SPEAKER:
966da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent	            //TODO: what do we do for camcorder when in call?
967da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent	        case SND_DEVICE_SPEAKER_BACK_MIC:
9684bcd5b16c66bc5c2bffe232f15f5cb83aea18318Jean-Michel Trivi	            new_pathid = A1026_PATH_INCALL_SPEAKER;
96963af0f3cbd387e97bcaca82d1e22787c224d6430Jean-Michel Trivi	            LOGV("A1026 control: new path is A1026_PATH_INCALL_SPEAKER");
9702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            break;
9712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        case SND_DEVICE_BT:
9722aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        case SND_DEVICE_BT_EC_OFF:
9734bcd5b16c66bc5c2bffe232f15f5cb83aea18318Jean-Michel Trivi	            new_pathid = A1026_PATH_INCALL_BT;
97463af0f3cbd387e97bcaca82d1e22787c224d6430Jean-Michel Trivi	            LOGV("A1026 control: new path is A1026_PATH_INCALL_BT");
9752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            break;
9762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        default:
9772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            break;
9782aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            }
9792aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland       } else {
9802aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           switch (Routes) {
9812aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        case SND_DEVICE_HANDSET:
9822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        case SND_DEVICE_NO_MIC_HEADSET:
9832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                    new_pathid = A1026_PATH_INCALL_RECEIVER; /* NS CT mode, Dual MIC */
98463af0f3cbd387e97bcaca82d1e22787c224d6430Jean-Michel Trivi                    LOGV("A1026 control: new path is A1026_PATH_INCALL_RECEIVER");
9852aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                    break;
9862aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                case SND_DEVICE_HEADSET:
9872aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                case SND_DEVICE_HEADSET_AND_SPEAKER:
9882aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                case SND_DEVICE_FM_HEADSET:
9892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                case SND_DEVICE_FM_SPEAKER:
9902aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            new_pathid = A1026_PATH_INCALL_HEADSET; /* NS disable, Headset MIC */
99163af0f3cbd387e97bcaca82d1e22787c224d6430Jean-Michel Trivi	            LOGV("A1026 control: new path is A1026_PATH_INCALL_HEADSET");
9922aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            break;
9932aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        case SND_DEVICE_SPEAKER:
9942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            new_pathid = A1026_PATH_INCALL_SPEAKER; /* NS FT mode, Main MIC */
99563af0f3cbd387e97bcaca82d1e22787c224d6430Jean-Michel Trivi	            LOGV("A1026 control: new path is A1026_PATH_INCALL_SPEAKER");
9962aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            break;
9972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        case SND_DEVICE_BT:
9982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        case SND_DEVICE_BT_EC_OFF:
9992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            new_pathid = A1026_PATH_INCALL_BT; /* QCOM NS, BT MIC */
100063af0f3cbd387e97bcaca82d1e22787c224d6430Jean-Michel Trivi	            LOGV("A1026 control: new path is A1026_PATH_INCALL_BT");
10012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            break;
10022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        default:
10032aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            break;
10042aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            }
10052aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland       }
10062aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else if (Record == 1) {
10072aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        switch (Routes) {
1008ba36d4fa33072ef14183365fffd289762c26905eJean-Michel Trivi        case SND_DEVICE_SPEAKER:
1009ba36d4fa33072ef14183365fffd289762c26905eJean-Michel Trivi            // default output is speaker, recording from phone mic, user RECEIVER configuration
1010739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        case SND_DEVICE_HANDSET:
1011739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        case SND_DEVICE_NO_MIC_HEADSET:
101208516fe50b023532d5a3010050970de28e14621bIliyan Malchev	        if (vr_mode_enabled) {
1013739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	            if (vr_uses_ns) {
10144bcd5b16c66bc5c2bffe232f15f5cb83aea18318Jean-Michel Trivi	                new_pathid = A1026_PATH_VR_NS_RECEIVER;
1015739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	                LOGV("A1026 control: new path is A1026_PATH_VR_NS_RECEIVER");
1016739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	            } else {
10174bcd5b16c66bc5c2bffe232f15f5cb83aea18318Jean-Michel Trivi	                new_pathid = A1026_PATH_VR_NO_NS_RECEIVER;
1018739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	                LOGV("A1026 control: new path is A1026_PATH_VR_NO_NS_RECEIVER");
1019739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	            }
1020739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	        } else {
10212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                new_pathid = A1026_PATH_RECORD_RECEIVER; /* INT-MIC Recording: NS disable, Main MIC */
1022739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi                LOGV("A1026 control: new path is A1026_PATH_RECORD_RECEIVER");
1023739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	        }
10242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        break;
1025739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        case SND_DEVICE_HEADSET:
1026739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        case SND_DEVICE_HEADSET_AND_SPEAKER:
1027739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        case SND_DEVICE_FM_HEADSET:
1028739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        case SND_DEVICE_FM_SPEAKER:
102908516fe50b023532d5a3010050970de28e14621bIliyan Malchev	        if (vr_mode_enabled) {
1030739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	            if (vr_uses_ns) {
10314bcd5b16c66bc5c2bffe232f15f5cb83aea18318Jean-Michel Trivi	                new_pathid = A1026_PATH_VR_NS_HEADSET;
1032739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	                LOGV("A1026 control: new path is A1026_PATH_VR_NS_HEADSET");
1033739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	            } else {
10344bcd5b16c66bc5c2bffe232f15f5cb83aea18318Jean-Michel Trivi	                new_pathid = A1026_PATH_VR_NO_NS_HEADSET;
1035739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	                LOGV("A1026 control: new path is A1026_PATH_VR_NO_NS_HEADSET");
1036739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	            }
1037739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	        } else {
1038739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	            new_pathid = A1026_PATH_RECORD_HEADSET; /* EXT-MIC Recording: NS disable, Headset MIC */
1039739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	            LOGV("A1026 control: new path is A1026_PATH_RECORD_HEADSET");
1040739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	        }
1041739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	        break;
1042739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        case SND_DEVICE_SPEAKER_BACK_MIC:
1043739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        case SND_DEVICE_NO_MIC_HEADSET_BACK_MIC:
1044739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        case SND_DEVICE_HANDSET_BACK_MIC:
104558cf88a5a91d82ae2fb3e23365eaa4524a9cd089Jean-Michel Trivi        case SND_DEVICE_HEADSET_AND_SPEAKER_BACK_MIC:
1046da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent	        new_pathid = A1026_PATH_CAMCORDER; /* CAM-Coder: NS FT mode, Back MIC */
1047f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi	        LOGV("A1026 control: new path is A1026_PATH_CAMCORDER");
10482aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        break;
1049739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        case SND_DEVICE_BT:
1050739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        case SND_DEVICE_BT_EC_OFF:
105108516fe50b023532d5a3010050970de28e14621bIliyan Malchev	        if (vr_mode_enabled) {
1052739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	            if (vr_uses_ns) {
10534bcd5b16c66bc5c2bffe232f15f5cb83aea18318Jean-Michel Trivi	                new_pathid = A1026_PATH_VR_NS_BT;
1054739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	                LOGV("A1026 control: new path is A1026_PATH_VR_NS_BT");
1055739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	            } else {
10564bcd5b16c66bc5c2bffe232f15f5cb83aea18318Jean-Michel Trivi	                new_pathid = A1026_PATH_VR_NO_NS_BT;
1057739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	                LOGV("A1026 control: new path is A1026_PATH_VR_NO_NS_BT");
1058739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	            }
1059739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	        } else {
1060739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	            new_pathid = A1026_PATH_RECORD_BT; /* BT MIC */
1061739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	            LOGV("A1026 control: new path is A1026_PATH_RECORD_BT");
1062739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	        }
10632aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        break;
1064739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        default:
10652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        break;
10662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
10672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
10682aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    else {
10692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        new_pathid = A1026_PATH_SUSPEND;
10702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
10712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
10722aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (old_pathid != new_pathid) {
10732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        //LOGI("A1026: do ioctl(A1026_SET_CONFIG) to %d\n", new_pathid);
10740f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        do {
10750f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            rc = ioctl(fd_a1026, A1026_SET_CONFIG, &new_pathid);
10760f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            if (!rc) {
10770f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                old_pathid = new_pathid;
10780f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                break;
10790f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            }
10800f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        } while (--retry);
10810f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent
10820f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        if (rc < 0) {
10830f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            LOGE("A1026 do hard reset to recover from error!\n");
10840f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            rc = doA1026_init(); /* A1026 needs to do hard reset! */
10850f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            if (!rc) {
10862aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	rc = ioctl(fd_a1026, A1026_SET_CONFIG, &new_pathid);
10872aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	if (!rc)
10882aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland		old_pathid = new_pathid;
10892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	else
10900f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                    LOGE("A1026 Fatal Error!\n");
10910f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            } else
10920f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                LOGE("A1026 Fatal Error: Re-init A1026 Failed\n");
10930f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        }
10942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
10952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
10962aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mA1026Lock.unlock();
10972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    close(fd_a1026);
10982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    fd_a1026 = -1;
10992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
11002aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return rc;
11012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
11022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
11032aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
11042aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::doRouting(AudioStreamInMSM72xx *input)
11052aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
1106f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi    Mutex::Autolock lock(mLock);
1107f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi    uint32_t outputDevices = mOutput->devices();
11082aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    status_t ret = NO_ERROR;
1109f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi    int sndDevice = -1;
11102aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
1111f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi    if (input != NULL) {
1112f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        uint32_t inputDevice = input->devices();
1113f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        LOGI("do input routing device %x\n", inputDevice);
1114f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        if (inputDevice != 0) {
1115f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi            if (inputDevice & AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
1116f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                LOGI("Routing audio to Bluetooth PCM\n");
1117f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                sndDevice = SND_DEVICE_BT;
1118f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi            } else if (inputDevice & AudioSystem::DEVICE_IN_WIRED_HEADSET) {
1119f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                if ((outputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) &&
1120956f7ba5ee0f087c91b5fefd2718dae30f8c1e29Eric Laurent                        (outputDevices & AudioSystem::DEVICE_OUT_SPEAKER)) {
1121f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                            LOGI("Routing audio to Wired Headset and Speaker\n");
1122f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                            sndDevice = SND_DEVICE_HEADSET_AND_SPEAKER;
1123956f7ba5ee0f087c91b5fefd2718dae30f8c1e29Eric Laurent                } else {
1124f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                    LOGI("Routing audio to Wired Headset\n");
1125f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                    sndDevice = SND_DEVICE_HEADSET;
1126f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                }
1127f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi            } else if (inputDevice & AudioSystem::DEVICE_IN_BACK_MIC) {
112858cf88a5a91d82ae2fb3e23365eaa4524a9cd089Jean-Michel Trivi                if (outputDevices & (AudioSystem:: DEVICE_OUT_WIRED_HEADSET) &&
112958cf88a5a91d82ae2fb3e23365eaa4524a9cd089Jean-Michel Trivi                       (outputDevices & AudioSystem:: DEVICE_OUT_SPEAKER)) {
113058cf88a5a91d82ae2fb3e23365eaa4524a9cd089Jean-Michel Trivi                    LOGI("Routing audio to Wired Headset and Speaker with back mic\n");
113158cf88a5a91d82ae2fb3e23365eaa4524a9cd089Jean-Michel Trivi                    sndDevice = SND_DEVICE_HEADSET_AND_SPEAKER_BACK_MIC;
113258cf88a5a91d82ae2fb3e23365eaa4524a9cd089Jean-Michel Trivi                } else if (outputDevices & AudioSystem::DEVICE_OUT_SPEAKER) {
1133f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                    LOGI("Routing audio to Speakerphone with back mic\n");
1134f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                    sndDevice = SND_DEVICE_SPEAKER_BACK_MIC;
1135f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                } else if (outputDevices == AudioSystem::DEVICE_OUT_EARPIECE) {
1136f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                    LOGI("Routing audio to Handset with back mic\n");
1137f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                    sndDevice = SND_DEVICE_HANDSET_BACK_MIC;
1138f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                } else {
1139f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                    LOGI("Routing audio to Headset with back mic\n");
1140f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                    sndDevice = SND_DEVICE_NO_MIC_HEADSET_BACK_MIC;
1141f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                }
1142f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi            } else {
1143f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                if (outputDevices & AudioSystem::DEVICE_OUT_SPEAKER) {
1144f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                    LOGI("Routing audio to Speakerphone\n");
1145f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                    sndDevice = SND_DEVICE_SPEAKER;
1146f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                } else if (outputDevices == AudioSystem::DEVICE_OUT_WIRED_HEADPHONE) {
1147f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                    LOGI("Routing audio to Speakerphone\n");
1148f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                    sndDevice = SND_DEVICE_NO_MIC_HEADSET;
1149f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                } else {
1150f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                    LOGI("Routing audio to Handset\n");
1151f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                    sndDevice = SND_DEVICE_HANDSET;
1152956f7ba5ee0f087c91b5fefd2718dae30f8c1e29Eric Laurent                }
1153956f7ba5ee0f087c91b5fefd2718dae30f8c1e29Eric Laurent            }
1154956f7ba5ee0f087c91b5fefd2718dae30f8c1e29Eric Laurent        }
1155f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        // if inputDevice == 0, restore output routing
1156f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi    }
1157956f7ba5ee0f087c91b5fefd2718dae30f8c1e29Eric Laurent
1158f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi    if (sndDevice == -1) {
1159f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        if (outputDevices & (outputDevices - 1)) {
1160f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi            if ((outputDevices & AudioSystem::DEVICE_OUT_SPEAKER) == 0) {
1161f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                LOGW("Hardware does not support requested route combination (%#X),"
1162f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                        " picking closest possible route...", outputDevices);
1163956f7ba5ee0f087c91b5fefd2718dae30f8c1e29Eric Laurent            }
1164f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        }
1165956f7ba5ee0f087c91b5fefd2718dae30f8c1e29Eric Laurent
1166f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        if (outputDevices &
1167dd65e38951ed174f9d3d34886795438440f7eea0Eric Laurent                (AudioSystem::DEVICE_OUT_BLUETOOTH_SCO | AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET)) {
1168f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                    LOGI("Routing audio to Bluetooth PCM\n");
1169f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                    sndDevice = SND_DEVICE_BT;
1170f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        } else if (outputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT) {
1171f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi            LOGI("Routing audio to Bluetooth PCM\n");
1172f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi            sndDevice = SND_DEVICE_CARKIT;
1173f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        } else if ((outputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) &&
1174f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                (outputDevices & AudioSystem::DEVICE_OUT_SPEAKER)) {
1175f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                    LOGI("Routing audio to Wired Headset and Speaker\n");
1176956f7ba5ee0f087c91b5fefd2718dae30f8c1e29Eric Laurent                    sndDevice = SND_DEVICE_HEADSET_AND_SPEAKER;
1177f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        } else if (outputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE) {
1178f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi            if (outputDevices & AudioSystem::DEVICE_OUT_SPEAKER) {
1179f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                LOGI("Routing audio to No microphone Wired Headset and Speaker (%d,%x)\n", mMode, outputDevices);
1180f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                sndDevice = SND_DEVICE_HEADSET_AND_SPEAKER;
1181956f7ba5ee0f087c91b5fefd2718dae30f8c1e29Eric Laurent            } else {
1182f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                LOGI("Routing audio to No microphone Wired Headset (%d,%x)\n", mMode, outputDevices);
1183f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                sndDevice = SND_DEVICE_NO_MIC_HEADSET;
11842aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            }
1185f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        } else if (outputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) {
1186f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi            LOGI("Routing audio to Wired Headset\n");
1187f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi            sndDevice = SND_DEVICE_HEADSET;
1188f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        } else if (outputDevices & AudioSystem::DEVICE_OUT_SPEAKER) {
1189f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi            LOGI("Routing audio to Speakerphone\n");
1190f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi            sndDevice = SND_DEVICE_SPEAKER;
1191f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        } else {
1192f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi            LOGI("Routing audio to Handset\n");
1193f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi            sndDevice = SND_DEVICE_HANDSET;
11942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
1195f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi    }
11962aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
1197f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi    if ((vr_mode_change) || (sndDevice != -1 && sndDevice != mCurSndDevice)) {
1198f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        ret = doAudioRouteOrMute(sndDevice);
1199f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        mCurSndDevice = sndDevice;
1200f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        if (mMode == AudioSystem::MODE_IN_CALL && mBluetoothIdTx != 0
1201f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                && sndDevice == (int)SND_DEVICE_BT) {
1202956f7ba5ee0f087c91b5fefd2718dae30f8c1e29Eric Laurent                    updateBT();
1203f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        } else {
1204f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi            updateACDB();
12052aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
12062aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
12072aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
12082aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return ret;
12092aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
12102aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
12112aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::checkMicMute()
12122aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
12132aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    Mutex::Autolock lock(mLock);
12142aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mMode != AudioSystem::MODE_IN_CALL) {
12152aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        setMicMute_nosync(true);
12162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
12172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
12182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
12192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
12202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
12212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::dumpInternals(int fd, const Vector<String16>& args)
12222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
12232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    const size_t SIZE = 256;
12242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    char buffer[SIZE];
12252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    String8 result;
12262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append("AudioHardware::dumpInternals\n");
12272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmInit: %s\n", mInit? "true": "false");
12282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
12292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmMicMute: %s\n", mMicMute? "true": "false");
12302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
12312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmBluetoothNrec: %s\n", mBluetoothNrec? "true": "false");
12322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
12330f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    snprintf(buffer, SIZE, "\tmBluetoothIdtx: %d\n", mBluetoothIdTx);
12340f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    result.append(buffer);
12350f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    snprintf(buffer, SIZE, "\tmBluetoothIdrx: %d\n", mBluetoothIdRx);
12362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
12372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    ::write(fd, result.string(), result.size());
12382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
12392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
12402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
12412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::dump(int fd, const Vector<String16>& args)
12422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
12432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    dumpInternals(fd, args);
12442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    for (size_t index = 0; index < mInputs.size(); index++) {
12452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mInputs[index]->dump(fd, args);
12462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
12472aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
12482aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mOutput) {
12492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mOutput->dump(fd, args);
12502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
12512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
12522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
12532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
12542aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlanduint32_t AudioHardware::getInputSampleRate(uint32_t sampleRate)
12552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
12562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    uint32_t i;
12572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    uint32_t prevDelta;
12582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    uint32_t delta;
12592aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
12602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    for (i = 0, prevDelta = 0xFFFFFFFF; i < sizeof(inputSamplingRates)/sizeof(uint32_t); i++, prevDelta = delta) {
12612aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        delta = abs(sampleRate - inputSamplingRates[i]);
12622aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (delta > prevDelta) break;
12632aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
12642aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // i is always > 0 here
12652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return inputSamplingRates[i-1];
12662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
12672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
12682aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland// ----------------------------------------------------------------------------
12692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
12702aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandAudioHardware::AudioStreamOutMSM72xx::AudioStreamOutMSM72xx() :
12712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mHardware(0), mFd(-1), mStartCount(0), mRetryCount(0), mStandby(true), mDevices(0)
12722aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
12732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
12742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
12752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::AudioStreamOutMSM72xx::set(
12762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        AudioHardware* hw, uint32_t devices, int *pFormat, uint32_t *pChannels, uint32_t *pRate)
12772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
12782aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    int lFormat = pFormat ? *pFormat : 0;
12792aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    uint32_t lChannels = pChannels ? *pChannels : 0;
12802aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    uint32_t lRate = pRate ? *pRate : 0;
12812aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
12822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mHardware = hw;
12832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
12842aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // fix up defaults
12852aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (lFormat == 0) lFormat = format();
12862aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (lChannels == 0) lChannels = channels();
12872aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (lRate == 0) lRate = sampleRate();
12882aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
12892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // check values
12902aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if ((lFormat != format()) ||
12912aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        (lChannels != channels()) ||
12922aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        (lRate != sampleRate())) {
12932aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (pFormat) *pFormat = format();
12942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (pChannels) *pChannels = channels();
12952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (pRate) *pRate = sampleRate();
12962aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return BAD_VALUE;
12972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
12982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
12992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (pFormat) *pFormat = lFormat;
13002aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (pChannels) *pChannels = lChannels;
13012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (pRate) *pRate = lRate;
13022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
13032aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mDevices = devices;
13042aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
13052aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
13062aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
13072aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
13082aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandAudioHardware::AudioStreamOutMSM72xx::~AudioStreamOutMSM72xx()
13092aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
13102aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mFd >= 0) close(mFd);
13112aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
13122aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
13132aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandssize_t AudioHardware::AudioStreamOutMSM72xx::write(const void* buffer, size_t bytes)
13142aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
13152aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // LOGD("AudioStreamOutMSM72xx::write(%p, %u)", buffer, bytes);
13162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    status_t status = NO_INIT;
13172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    size_t count = bytes;
13182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    const uint8_t* p = static_cast<const uint8_t*>(buffer);
13192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
13202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mStandby) {
13212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
13222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        // open driver
13232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGV("open pcm_out driver");
13242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        status = ::open("/dev/msm_pcm_out", O_RDWR);
13252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (status < 0) {
13262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            if (errCount++ < 10) {
13272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                LOGE("Cannot open /dev/msm_pcm_out errno: %d", errno);
13282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            }
13292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            goto Error;
13302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
13312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mFd = status;
13322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
13332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        // configuration
13342aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGV("get config");
13352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        struct msm_audio_config config;
13362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        status = ioctl(mFd, AUDIO_GET_CONFIG, &config);
13372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (status < 0) {
13382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            LOGE("Cannot read pcm_out config");
13392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            goto Error;
13402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
13412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
13422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGV("set pcm_out config");
13432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        config.channel_count = AudioSystem::popCount(channels());
13442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        config.sample_rate = sampleRate();
13452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        config.buffer_size = bufferSize();
13462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        config.buffer_count = AUDIO_HW_NUM_OUT_BUF;
13472aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        config.codec_type = CODEC_TYPE_PCM;
13482aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        status = ioctl(mFd, AUDIO_SET_CONFIG, &config);
13492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (status < 0) {
13502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            LOGE("Cannot set config");
13512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            goto Error;
13522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
13532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
13542aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGV("buffer_size: %u", config.buffer_size);
13552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGV("buffer_count: %u", config.buffer_count);
13562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGV("channel_count: %u", config.channel_count);
13572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGV("sample_rate: %u", config.sample_rate);
13582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
135931923bb6797ec304d26395acf6d946ab8e44aa6eHK Chen        status = ioctl(mFd, AUDIO_START, 0);
136031923bb6797ec304d26395acf6d946ab8e44aa6eHK Chen        if (status < 0) {
136131923bb6797ec304d26395acf6d946ab8e44aa6eHK Chen            LOGE("Cannot start pcm playback");
136231923bb6797ec304d26395acf6d946ab8e44aa6eHK Chen            goto Error;
13632aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
136410254cc35f5cb7ebe2c7ef452815486cb8e92a33Jean-Michel Trivi
136510254cc35f5cb7ebe2c7ef452815486cb8e92a33Jean-Michel Trivi        status = ioctl(mFd, AUDIO_SET_VOLUME, &stream_volume);
136610254cc35f5cb7ebe2c7ef452815486cb8e92a33Jean-Michel Trivi        if (status < 0) {
136710254cc35f5cb7ebe2c7ef452815486cb8e92a33Jean-Michel Trivi            LOGE("Cannot start pcm playback");
136810254cc35f5cb7ebe2c7ef452815486cb8e92a33Jean-Michel Trivi            goto Error;
136910254cc35f5cb7ebe2c7ef452815486cb8e92a33Jean-Michel Trivi        }
137010254cc35f5cb7ebe2c7ef452815486cb8e92a33Jean-Michel Trivi
13715d89308f2e1252eff2743bf823bf558dbb0de2faDave Sparks        LOGV("acquire wakelock");
13725d89308f2e1252eff2743bf823bf558dbb0de2faDave Sparks        acquire_wake_lock(PARTIAL_WAKE_LOCK, kOutputWakelockStr);
137331923bb6797ec304d26395acf6d946ab8e44aa6eHK Chen        mStandby = false;
13740f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        Mutex::Autolock lock(mHardware->mLock);
13750f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        mHardware->updateACDB();
13762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
13772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
13782aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    while (count) {
13792aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        ssize_t written = ::write(mFd, p, count);
13802aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (written >= 0) {
13812aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            count -= written;
13822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            p += written;
13832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        } else {
13842aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            if (errno != EAGAIN) return written;
13852aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            mRetryCount++;
13862aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            LOGW("EAGAIN - retry");
13872aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
13882aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
13892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
13902aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return bytes;
13912aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
13922aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandError:
13932aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mFd >= 0) {
13942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        ::close(mFd);
13952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mFd = -1;
13962aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
13972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // Simulate audio output timing in case of error
13982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    usleep(bytes * 1000000 / frameSize() / sampleRate());
13992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
14002aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return status;
14012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
14022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
14032aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::AudioStreamOutMSM72xx::standby()
14042aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
14052aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    status_t status = NO_ERROR;
14062aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (!mStandby && mFd >= 0) {
14072aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        ::close(mFd);
14082aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mFd = -1;
14095d89308f2e1252eff2743bf823bf558dbb0de2faDave Sparks        LOGV("release wakelock");
14105d89308f2e1252eff2743bf823bf558dbb0de2faDave Sparks        release_wake_lock(kOutputWakelockStr);
14112aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
14122aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mStandby = true;
14132aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGI("AudioHardware pcm playback is going to standby.");
14142aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return status;
14152aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
14162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
14172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::AudioStreamOutMSM72xx::dump(int fd, const Vector<String16>& args)
14182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
14192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    const size_t SIZE = 256;
14202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    char buffer[SIZE];
14212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    String8 result;
14222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append("AudioStreamOutMSM72xx::dump\n");
14232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tsample rate: %d\n", sampleRate());
14242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
14252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize());
14262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
14272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tchannels: %d\n", channels());
14282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
14292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tformat: %d\n", format());
14302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
14312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmHardware: %p\n", mHardware);
14322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
14332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmFd: %d\n", mFd);
14342aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
14352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmStartCount: %d\n", mStartCount);
14362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
14372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmRetryCount: %d\n", mRetryCount);
14382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
14392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmStandby: %s\n", mStandby? "true": "false");
14402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
14412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    ::write(fd, result.string(), result.size());
14422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
14432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
14442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
14452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandbool AudioHardware::AudioStreamOutMSM72xx::checkStandby()
14462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
14472aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return mStandby;
14482aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
14492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
14502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
14512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::AudioStreamOutMSM72xx::setParameters(const String8& keyValuePairs)
14522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
14532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    AudioParameter param = AudioParameter(keyValuePairs);
14542aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    String8 key = String8(AudioParameter::keyRouting);
14552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    status_t status = NO_ERROR;
14562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    int device;
14572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("AudioStreamOutMSM72xx::setParameters() %s", keyValuePairs.string());
14582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
14592aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (param.getInt(key, device) == NO_ERROR) {
14602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mDevices = device;
14612aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGV("set output routing %x", mDevices);
14622aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        status = mHardware->doRouting(NULL);
14632aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        param.remove(key);
14642aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
14652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
14662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (param.size()) {
14672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        status = BAD_VALUE;
14682aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
14692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return status;
14702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
14712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
14722aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandString8 AudioHardware::AudioStreamOutMSM72xx::getParameters(const String8& keys)
14732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
14742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    AudioParameter param = AudioParameter(keys);
14752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    String8 value;
14762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    String8 key = String8(AudioParameter::keyRouting);
14772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
14782aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (param.get(key, value) == NO_ERROR) {
14792aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGV("get routing %x", mDevices);
14802aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        param.addInt(key, (int)mDevices);
14812aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
14822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
14832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("AudioStreamOutMSM72xx::getParameters() %s", param.toString().string());
14842aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return param.toString();
14852aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
14862aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
14872aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
14882aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland// ----------------------------------------------------------------------------
14892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
14902aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandAudioHardware::AudioStreamInMSM72xx::AudioStreamInMSM72xx() :
14912aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mHardware(0), mFd(-1), mState(AUDIO_INPUT_CLOSED), mRetryCount(0),
14922aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mFormat(AUDIO_HW_IN_FORMAT), mChannels(AUDIO_HW_IN_CHANNELS),
14932aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mSampleRate(AUDIO_HW_IN_SAMPLERATE), mBufferSize(AUDIO_HW_IN_BUFFERSIZE),
14942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mAcoustics((AudioSystem::audio_in_acoustics)0), mDevices(0)
14952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
14962aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
14972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
14982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::AudioStreamInMSM72xx::set(
14992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        AudioHardware* hw, uint32_t devices, int *pFormat, uint32_t *pChannels, uint32_t *pRate,
15002aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        AudioSystem::audio_in_acoustics acoustic_flags)
15012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
15022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (pFormat == 0 || *pFormat != AUDIO_HW_IN_FORMAT) {
15032aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        *pFormat = AUDIO_HW_IN_FORMAT;
15042aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return BAD_VALUE;
15052aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
15062aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (pRate == 0) {
15072aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return BAD_VALUE;
15082aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
15092aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    uint32_t rate = hw->getInputSampleRate(*pRate);
15102aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (rate != *pRate) {
15112aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        *pRate = rate;
15122aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return BAD_VALUE;
15132aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
15142aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
15152aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (pChannels == 0 || (*pChannels != AudioSystem::CHANNEL_IN_MONO &&
15162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        *pChannels != AudioSystem::CHANNEL_IN_STEREO)) {
15172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        *pChannels = AUDIO_HW_IN_CHANNELS;
15182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return BAD_VALUE;
15192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
15202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
15212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mHardware = hw;
15222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
15232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("AudioStreamInMSM72xx::set(%d, %d, %u)", *pFormat, *pChannels, *pRate);
15242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mFd >= 0) {
15252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGE("Audio record already open");
15262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return -EPERM;
15272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
15282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
15292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // open audio input device
15302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    status_t status = ::open("/dev/msm_pcm_in", O_RDWR);
15312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (status < 0) {
15322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGE("Cannot open /dev/msm_pcm_in errno: %d", errno);
15332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        goto Error;
15342aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
15352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mFd = status;
15362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
15372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // configuration
15382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("get config");
15392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    struct msm_audio_config config;
15402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    status = ioctl(mFd, AUDIO_GET_CONFIG, &config);
15412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (status < 0) {
15422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGE("Cannot read config");
15432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        goto Error;
15442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
15452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
15462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("set config");
15472aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    config.channel_count = AudioSystem::popCount(*pChannels);
15482aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    config.sample_rate = *pRate;
15492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    config.buffer_size = bufferSize();
15502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    config.buffer_count = 2;
15512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    config.codec_type = CODEC_TYPE_PCM;
15522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    status = ioctl(mFd, AUDIO_SET_CONFIG, &config);
15532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (status < 0) {
15542aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGE("Cannot set config");
15552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (ioctl(mFd, AUDIO_GET_CONFIG, &config) == 0) {
15562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            if (config.channel_count == 1) {
15572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                *pChannels = AudioSystem::CHANNEL_IN_MONO;
15582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            } else {
15592aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                *pChannels = AudioSystem::CHANNEL_IN_STEREO;
15602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            }
15612aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            *pRate = config.sample_rate;
15622aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
15632aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        goto Error;
15642aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
15652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
15662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("confirm config");
15672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    status = ioctl(mFd, AUDIO_GET_CONFIG, &config);
15682aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (status < 0) {
15692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGE("Cannot read config");
15702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        goto Error;
15712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
15722aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("buffer_size: %u", config.buffer_size);
15732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("buffer_count: %u", config.buffer_count);
15742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("channel_count: %u", config.channel_count);
15752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("sample_rate: %u", config.sample_rate);
15762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
15772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mDevices = devices;
15782aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mFormat = AUDIO_HW_IN_FORMAT;
15792aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mChannels = *pChannels;
15802aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mSampleRate = config.sample_rate;
15812aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mBufferSize = config.buffer_size;
15822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
15832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    //mHardware->setMicMute_nosync(false);
15842aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mState = AUDIO_INPUT_OPENED;
15852aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
15862aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
15872aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
15882aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandError:
15892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mFd >= 0) {
15902aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        ::close(mFd);
15912aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mFd = -1;
15922aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
15932aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return status;
15942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
15952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
15962aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandAudioHardware::AudioStreamInMSM72xx::~AudioStreamInMSM72xx()
15972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
15982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("AudioStreamInMSM72xx destructor");
15992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    standby();
16002aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
16012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
16022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandssize_t AudioHardware::AudioStreamInMSM72xx::read( void* buffer, ssize_t bytes)
16032aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
16042aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("AudioStreamInMSM72xx::read(%p, %ld)", buffer, bytes);
16052aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (!mHardware) return -1;
16062aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
16072aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    size_t count = bytes;
16082aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    uint8_t* p = static_cast<uint8_t*>(buffer);
16092aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
16102aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mState < AUDIO_INPUT_OPENED) {
16112aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        Mutex::Autolock lock(mHardware->mLock);
16122aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (set(mHardware, mDevices, &mFormat, &mChannels, &mSampleRate, mAcoustics) != NO_ERROR) {
16132aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            return -1;
16142aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
16152aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
16162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
16170f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    if (mState < AUDIO_INPUT_STARTED) {
16182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mHardware->set_mRecordState(1);
1619956f7ba5ee0f087c91b5fefd2718dae30f8c1e29Eric Laurent        if (support_a1026 == 1) {
1620956f7ba5ee0f087c91b5fefd2718dae30f8c1e29Eric Laurent            mHardware->doAudience_A1026_Control(mHardware->get_mMode(), 1, mHardware->get_snd_dev());
16212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
16222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (ioctl(mFd, AUDIO_START, 0)) {
16232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            LOGE("Error starting record");
16242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            return -1;
16252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
16262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGI("AUDIO_START: start kernel pcm_in driver.");
16272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mState = AUDIO_INPUT_STARTED;
16280f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        Mutex::Autolock lock(mHardware->mLock);
16290f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        mHardware->updateACDB();
16302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
16312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
16322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    while (count) {
16332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        ssize_t bytesRead = ::read(mFd, buffer, count);
16342aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (bytesRead >= 0) {
16352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            count -= bytesRead;
16362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            p += bytesRead;
16372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        } else {
16382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            if (errno != EAGAIN) return bytesRead;
16392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            mRetryCount++;
16402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            LOGW("EAGAIN - retrying");
16412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
16422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
16432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return bytes;
16442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
16452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
16462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::AudioStreamInMSM72xx::standby()
16472aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
1648956f7ba5ee0f087c91b5fefd2718dae30f8c1e29Eric Laurent    if (mHardware) {
16492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mHardware->set_mRecordState(0);
16500f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        if (support_a1026 == 1) {
1651956f7ba5ee0f087c91b5fefd2718dae30f8c1e29Eric Laurent            mHardware->doAudience_A1026_Control(mHardware->get_mMode(), 0, mHardware->get_snd_dev());
16522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
16532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
16542aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
16552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (!mHardware) return -1;
16562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mState > AUDIO_INPUT_CLOSED) {
16572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (mFd >= 0) {
16582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            ::close(mFd);
16592aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            mFd = -1;
16602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
16612aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        //mHardware->checkMicMute();
16622aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mState = AUDIO_INPUT_CLOSED;
16632aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
16642aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGI("AudioHardware PCM record is going to standby.");
16652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
16662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
16672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
16682aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::AudioStreamInMSM72xx::dump(int fd, const Vector<String16>& args)
16692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
16702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    const size_t SIZE = 256;
16712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    char buffer[SIZE];
16722aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    String8 result;
16732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append("AudioStreamInMSM72xx::dump\n");
16742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tsample rate: %d\n", sampleRate());
16752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
16762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize());
16772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
16782aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tchannels: %d\n", channels());
16792aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
16802aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tformat: %d\n", format());
16812aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
16822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmHardware: %p\n", mHardware);
16832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
16842aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmFd count: %d\n", mFd);
16852aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
16862aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmState: %d\n", mState);
16872aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
16882aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmRetryCount: %d\n", mRetryCount);
16892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
16902aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    ::write(fd, result.string(), result.size());
16912aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
16922aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
16932aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
16942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::AudioStreamInMSM72xx::setParameters(const String8& keyValuePairs)
16952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
16962aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    AudioParameter param = AudioParameter(keyValuePairs);
16972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    status_t status = NO_ERROR;
16982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    int device;
1699255bdedb2d7ebf4b14690776ff652df1de97fe95Eric Laurent    String8 key = String8(KEY_A1026_VR_MODE);
1700739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    int enabled;
17012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("AudioStreamInMSM72xx::setParameters() %s", keyValuePairs.string());
17022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
1703739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    // reading voice recognition mode parameter
1704255bdedb2d7ebf4b14690776ff652df1de97fe95Eric Laurent    if (param.getInt(key, enabled) == NO_ERROR) {
170508516fe50b023532d5a3010050970de28e14621bIliyan Malchev        LOGV("set vr_mode_enabled to %d", enabled);
170608516fe50b023532d5a3010050970de28e14621bIliyan Malchev        vr_mode_change = (vr_mode_enabled != enabled);
1707739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        if (enable1026) {
170808516fe50b023532d5a3010050970de28e14621bIliyan Malchev            vr_mode_enabled = enabled;
1709739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        } else {
171008516fe50b023532d5a3010050970de28e14621bIliyan Malchev            vr_mode_enabled = 0;
1711739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        }
1712739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        param.remove(key);
1713739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    }
1714739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi
1715739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    // reading routing parameter
1716255bdedb2d7ebf4b14690776ff652df1de97fe95Eric Laurent    key = String8(AudioParameter::keyRouting);
17172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (param.getInt(key, device) == NO_ERROR) {
17182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGV("set input routing %x", device);
17192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (device & (device - 1)) {
17202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            status = BAD_VALUE;
17212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        } else {
17222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            mDevices = device;
17232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            status = mHardware->doRouting(this);
17242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
17252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        param.remove(key);
17262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
17272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
17282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (param.size()) {
17292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        status = BAD_VALUE;
17302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
17312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return status;
17322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
17332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
17342aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandString8 AudioHardware::AudioStreamInMSM72xx::getParameters(const String8& keys)
17352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
17362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    AudioParameter param = AudioParameter(keys);
17372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    String8 value;
17382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    String8 key = String8(AudioParameter::keyRouting);
17392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
17402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (param.get(key, value) == NO_ERROR) {
17412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGV("get routing %x", mDevices);
17422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        param.addInt(key, (int)mDevices);
17432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
17442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
17452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("AudioStreamInMSM72xx::getParameters() %s", param.toString().string());
17462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return param.toString();
17472aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
17482aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
17492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland// ----------------------------------------------------------------------------
17502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
17512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandextern "C" AudioHardwareInterface* createAudioHardware(void) {
17522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return new AudioHardware();
17532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
17542aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
17552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}; // namespace android
1756