AudioHardware.cpp revision 710f4558c4f660e59551b1ed13c5106f9e460a59
12aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland/*
22aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland** Copyright 2008, Google Inc.
32aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland**
42aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland** Licensed under the Apache License, Version 2.0 (the "License");
52aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland** you may not use this file except in compliance with the License.
62aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland** You may obtain a copy of the License at
72aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland**
82aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland**     http://www.apache.org/licenses/LICENSE-2.0
92aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland**
102aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland** Unless required by applicable law or agreed to in writing, software
112aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland** distributed under the License is distributed on an "AS IS" BASIS,
122aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland** See the License for the specific language governing permissions and
142aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland** limitations under the License.
152aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland*/
162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#include <math.h>
182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland//#define LOG_NDEBUG 0
202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#define LOG_TAG "AudioHardwareQSD"
212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#include <utils/Log.h>
222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#include <utils/String8.h>
235d89308f2e1252eff2743bf823bf558dbb0de2faDave Sparks#include <hardware_legacy/power.h>
242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#include <stdio.h>
262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#include <unistd.h>
272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#include <sys/ioctl.h>
282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#include <sys/types.h>
292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#include <sys/stat.h>
302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#include <dlfcn.h>
312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#include <fcntl.h>
322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
33739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi#include <cutils/properties.h> // for property_get for the voice recognition mode switch
34739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi
352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland// hardware specific functions
362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#include "AudioHardware.h"
382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#include <media/AudioRecord.h>
392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandextern "C" {
412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#include "msm_audio.h"
429ab0b5b1f3244f261fcda2ead8fcdd5fe5d714b6Iliyan Malchev#include <linux/a1026.h>
43f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev#include <linux/tpa2018d1.h>
442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#define LOG_SND_RPC 0  // Set to 1 to log sound RPC's
472aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#define TX_PATH (1)
482aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_CURRENT = 256;
502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_HANDSET = 0;
512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_SPEAKER = 1;
522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_BT = 3;
532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_CARKIT = 4;
542aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_BT_EC_OFF = 45;
552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_HEADSET = 2;
562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_HEADSET_AND_SPEAKER = 10;
572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_FM_HEADSET = 9;
582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_FM_SPEAKER = 11;
592aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_NO_MIC_HEADSET = 8;
602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_TTY_FULL = 5;
61da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurentstatic const uint32_t SND_DEVICE_HANDSET_BACK_MIC = 20;
62da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurentstatic const uint32_t SND_DEVICE_SPEAKER_BACK_MIC = 21;
63da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurentstatic const uint32_t SND_DEVICE_NO_MIC_HEADSET_BACK_MIC = 28;
6458cf88a5a91d82ae2fb3e23365eaa4524a9cd089Jean-Michel Trivistatic const uint32_t SND_DEVICE_HEADSET_AND_SPEAKER_BACK_MIC = 30;
652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandnamespace android {
662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic int support_a1026 = 1;
67f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchevstatic bool support_tpa2018d1 = true;
682aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic int fd_a1026 = -1;
692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic int old_pathid = -1;
702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic int new_pathid = -1;
710f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurentstatic int curr_out_device = -1;
720f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurentstatic int curr_mic_device = -1;
732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic int voice_started = 0;
742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic int fd_fm_device = -1;
7510254cc35f5cb7ebe2c7ef452815486cb8e92a33Jean-Michel Trivistatic int stream_volume = -300;
76739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi// use VR mode on inputs: 1 == VR mode enabled when selected, 0 = VR mode disabled when selected
7708516fe50b023532d5a3010050970de28e14621bIliyan Malchevstatic int vr_mode_enabled;
78739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivistatic bool vr_mode_change = false;
79739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivistatic int vr_uses_ns = 0;
80f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchevstatic int alt_enable = 0;
81f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchevstatic int hac_enable = 0;
829ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi// enable or disable 2-mic noise suppression in call on receiver mode
83739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivistatic int enable1026 = 1;
849ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi//FIXME add new settings in A1026 driver for an incall no ns mode, based on the current vr no ns
859ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi#define A1026_PATH_INCALL_NO_NS_RECEIVER A1026_PATH_VR_NO_NS_RECEIVER
8610254cc35f5cb7ebe2c7ef452815486cb8e92a33Jean-Michel Trivi
872aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandint errCount = 0;
880f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurentstatic void * acoustic;
892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandconst uint32_t AudioHardware::inputSamplingRates[] = {
902aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000
912aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland};
925d89308f2e1252eff2743bf823bf558dbb0de2faDave Sparks
935d89308f2e1252eff2743bf823bf558dbb0de2faDave Sparks// ID string for audio wakelock
945d89308f2e1252eff2743bf823bf558dbb0de2faDave Sparksstatic const char kOutputWakelockStr[] = "AudioHardwareQSD";
955d89308f2e1252eff2743bf823bf558dbb0de2faDave Sparks
962aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland// ----------------------------------------------------------------------------
972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
982aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandAudioHardware::AudioHardware() :
990f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    mA1026Init(false), mInit(false), mMicMute(true),
100f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    mBluetoothNrec(true),
101f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    mHACSetting(false),
102f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    mBluetoothIdTx(0), mBluetoothIdRx(0),
103f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    mOutput(0),
1043964d4ed448b00791bc1b574913be24f44b45f0fEric Laurent    mNoiseSuppressionState(A1026_NS_STATE_AUTO),
1053964d4ed448b00791bc1b574913be24f44b45f0fEric Laurent    mVoiceVolume(VOICE_VOLUME_MAX)
1062aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
1070f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    int (*snd_get_num)();
1080f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    int (*snd_get_bt_endpoint)(msm_bt_endpoint *);
1090f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    int (*set_acoustic_parameters)();
110f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    int (*set_tpa2018d1_parameters)();
1110f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent
1120f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    struct msm_bt_endpoint *ept;
1130f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent
1142aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    doA1026_init();
1150f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent
1160f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    acoustic =:: dlopen("/system/lib/libhtc_acoustic.so", RTLD_NOW);
1170f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    if (acoustic == NULL ) {
1180f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        LOGE("Could not open libhtc_acoustic.so");
1190f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        /* this is not really an error on non-htc devices... */
1200f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        mNumBTEndpoints = 0;
1210f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        mInit = true;
1220f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        return;
1230f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    }
1240f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    set_acoustic_parameters = (int (*)(void))::dlsym(acoustic, "set_acoustic_parameters");
1250f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    if ((*set_acoustic_parameters) == 0 ) {
1260f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        LOGE("Could not open set_acoustic_parameters()");
1270f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        return;
1280f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    }
1290f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent
130f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    set_tpa2018d1_parameters = (int (*)(void))::dlsym(acoustic, "set_tpa2018d1_parameters");
131f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    if ((*set_tpa2018d1_parameters) == 0) {
132f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        LOGI("set_tpa2018d1_parameters() not present");
133f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        support_tpa2018d1 = false;
134f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    }
135f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev
1360f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    int rc = set_acoustic_parameters();
1370f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    if (rc < 0) {
1380f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        LOGE("Could not set acoustic parameters to share memory: %d", rc);
1390f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    }
1400f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent
141f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    if (support_tpa2018d1) {
142f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev       rc = set_tpa2018d1_parameters();
143f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev       if (rc < 0) {
144f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev           support_tpa2018d1 = false;
145f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev           LOGE("speaker amplifier tpa2018 is not supported\n");
146f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev       }
147f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    }
148f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev
1490f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    snd_get_num = (int (*)(void))::dlsym(acoustic, "snd_get_num");
1500f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    if ((*snd_get_num) == 0 ) {
1510f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        LOGE("Could not open snd_get_num()");
1520f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    }
1530f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent
1540f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    mNumBTEndpoints = snd_get_num();
1550f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    LOGD("mNumBTEndpoints = %d", mNumBTEndpoints);
1560f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    mBTEndpoints = new msm_bt_endpoint[mNumBTEndpoints];
1570f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    mInit = true;
1580f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    LOGV("constructed %d SND endpoints)", mNumBTEndpoints);
1590f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    ept = mBTEndpoints;
1600f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    snd_get_bt_endpoint = (int (*)(msm_bt_endpoint *))::dlsym(acoustic, "snd_get_bt_endpoint");
1610f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    if ((*snd_get_bt_endpoint) == 0 ) {
1620f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        LOGE("Could not open snd_get_bt_endpoint()");
1630f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        return;
1640f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    }
1650f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    snd_get_bt_endpoint(mBTEndpoints);
1660f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent
1670f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    for (int i = 0; i < mNumBTEndpoints; i++) {
1680f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        LOGE("BT name %s (tx,rx)=(%d,%d)", mBTEndpoints[i].name, mBTEndpoints[i].tx, mBTEndpoints[i].rx);
1690f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    }
1700f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent
171d1dc8c30a969ec3539fc21b940789b2f23197756Eric Laurent    // reset voice mode in case media_server crashed and restarted while in call
172d1dc8c30a969ec3539fc21b940789b2f23197756Eric Laurent    int fd = open("/dev/msm_audio_ctl", O_RDWR);
173d1dc8c30a969ec3539fc21b940789b2f23197756Eric Laurent    if (fd >= 0) {
174d1dc8c30a969ec3539fc21b940789b2f23197756Eric Laurent        ioctl(fd, AUDIO_STOP_VOICE, NULL);
175d1dc8c30a969ec3539fc21b940789b2f23197756Eric Laurent        close(fd);
176d1dc8c30a969ec3539fc21b940789b2f23197756Eric Laurent    }
177d1dc8c30a969ec3539fc21b940789b2f23197756Eric Laurent
178739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    vr_mode_change = false;
17908516fe50b023532d5a3010050970de28e14621bIliyan Malchev    vr_mode_enabled = 0;
180739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    enable1026 = 1;
181739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    char value[PROPERTY_VALUE_MAX];
182739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    // Check the system property to enable or not the special recording modes
183739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    property_get("media.a1026.enableA1026", value, "1");
184739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    enable1026 = atoi(value);
185739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    LOGV("Enable mode selection for A1026 is %d", enable1026);
186739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    // Check the system property for which VR mode to use
187739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    property_get("media.a1026.nsForVoiceRec", value, "0");
188739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    vr_uses_ns = atoi(value);
189739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    LOGV("Using Noise Suppression for Voice Rec is %d", vr_uses_ns);
190739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi
191f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    // Check the system property for enable or not the ALT function
192f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    property_get("htc.audio.alt.enable", value, "0");
193f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    alt_enable = atoi(value);
194f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    LOGV("Enable ALT function: %d", alt_enable);
195f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev
196f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    // Check the system property for enable or not the HAC function
197f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    property_get("htc.audio.hac.enable", value, "0");
198f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    hac_enable = atoi(value);
199f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    LOGV("Enable HAC function: %d", hac_enable);
200f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev
2012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mInit = true;
2022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
2032aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2042aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandAudioHardware::~AudioHardware()
2052aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
2062aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    for (size_t index = 0; index < mInputs.size(); index++) {
2072aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        closeInputStream((AudioStreamIn*)mInputs[index]);
2082aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
2092aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mInputs.clear();
2102aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    closeOutputStream((AudioStreamOut*)mOutput);
2112aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mInit = false;
2122aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
2132aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2142aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::initCheck()
2152aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
2162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return mInit ? NO_ERROR : NO_INIT;
2172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
2182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2192aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandAudioStreamOut* AudioHardware::openOutputStream(
2202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status)
2212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
2222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    { // scope for the lock
2232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        Mutex::Autolock lock(mLock);
2242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        // only one output stream allowed
2262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (mOutput) {
2272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            if (status) {
2282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                *status = INVALID_OPERATION;
2292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            }
2302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            return 0;
2312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
2322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        // create new output stream
2342aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        AudioStreamOutMSM72xx* out = new AudioStreamOutMSM72xx();
2352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        status_t lStatus = out->set(this, devices, format, channels, sampleRate);
2362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (status) {
2372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            *status = lStatus;
2382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
2392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (lStatus == NO_ERROR) {
2402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            mOutput = out;
2412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        } else {
2422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            delete out;
2432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
2442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
2452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return mOutput;
2462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
2472aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2482aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandvoid AudioHardware::closeOutputStream(AudioStreamOut* out) {
2492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    Mutex::Autolock lock(mLock);
2502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mOutput == 0 || mOutput != out) {
2512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGW("Attempt to close invalid output stream");
2522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
2532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    else {
2542aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        delete mOutput;
2552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mOutput = 0;
2562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
2572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
2582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2592aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandAudioStreamIn* AudioHardware::openInputStream(
2602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status,
2612aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        AudioSystem::audio_in_acoustics acoustic_flags)
2622aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
2632aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // check for valid input source
2642aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (!AudioSystem::isInputDevice((AudioSystem::audio_devices)devices)) {
2652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return 0;
2662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
2672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2682aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mLock.lock();
2692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    AudioStreamInMSM72xx* in = new AudioStreamInMSM72xx();
2712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    status_t lStatus = in->set(this, devices, format, channels, sampleRate, acoustic_flags);
2722aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (status) {
2732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        *status = lStatus;
2742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
2752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (lStatus != NO_ERROR) {
2762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mLock.unlock();
2772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        delete in;
2782aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return 0;
2792aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
2802aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2812aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mInputs.add(in);
2822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mLock.unlock();
2832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2842aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return in;
2852aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
2862aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2872aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandvoid AudioHardware::closeInputStream(AudioStreamIn* in) {
2882aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    Mutex::Autolock lock(mLock);
2892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2902aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    ssize_t index = mInputs.indexOf((AudioStreamInMSM72xx *)in);
2912aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (index < 0) {
2922aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGW("Attempt to close invalid input stream");
2932aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else {
2942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mLock.unlock();
2952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        delete mInputs[index];
2962aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mLock.lock();
2972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mInputs.removeAt(index);
2982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
2992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
3002aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
3012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::setMode(int mode)
3022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
303739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    // VR mode is never used in a call and must be cleared when entering the IN_CALL mode
304739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    if (mode == AudioSystem::MODE_IN_CALL) {
30508516fe50b023532d5a3010050970de28e14621bIliyan Malchev        vr_mode_enabled = 0;
306739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    }
307739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi
308f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    if (support_tpa2018d1)
309f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        do_tpa2018_control(mode);
310f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev
3112aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    status_t status = AudioHardwareBase::setMode(mode);
3122aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (status == NO_ERROR) {
3132aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        // make sure that doAudioRouteOrMute() is called by doRouting()
3142aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        // even if the new device selected is the same as current one.
31511c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent        clearCurDevice();
3162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
3172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return status;
3182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
3192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
3202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandbool AudioHardware::checkOutputStandby()
3212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
3222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mOutput)
3232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (!mOutput->checkStandby())
3242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            return false;
3252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
3262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return true;
3272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
3283cb8864598e72c04859f410bb03f242cf3965dbeHK Chenstatic status_t set_mic_mute(bool _mute)
3292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
3303cb8864598e72c04859f410bb03f242cf3965dbeHK Chen    uint32_t mute = _mute;
3313cb8864598e72c04859f410bb03f242cf3965dbeHK Chen    int fd = -1;
3322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    fd = open("/dev/msm_audio_ctl", O_RDWR);
3332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (fd < 0) {
3342aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGE("Cannot open msm_audio_ctl device\n");
3352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return -1;
3362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
3372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGD("Setting mic mute to %d\n", mute);
3383cb8864598e72c04859f410bb03f242cf3965dbeHK Chen    if (ioctl(fd, AUDIO_SET_MUTE, &mute)) {
3392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGE("Cannot set mic mute on current device\n");
3402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        close(fd);
3412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return -1;
3422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
3432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    close(fd);
3442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
3452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
3462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
3472aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::setMicMute(bool state)
3482aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
3492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    Mutex::Autolock lock(mLock);
3502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return setMicMute_nosync(state);
3512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
3522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
3532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland// always call with mutex held
3542aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::setMicMute_nosync(bool state)
3552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
3562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mMicMute != state) {
3572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mMicMute = state;
3582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return set_mic_mute(mMicMute); //always set current TX device
3592aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
3602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
3612aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
3622aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
3632aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::getMicMute(bool* state)
3642aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
3652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    *state = mMicMute;
3662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
3672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
3682aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
3692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::setParameters(const String8& keyValuePairs)
3702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
3712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    AudioParameter param = AudioParameter(keyValuePairs);
3722aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    String8 value;
3732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    String8 key;
3742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    const char BT_NREC_KEY[] = "bt_headset_nrec";
3752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    const char BT_NAME_KEY[] = "bt_headset_name";
376f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    const char HAC_KEY[] = "HACSetting";
3772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    const char BT_NREC_VALUE_ON[] = "on";
378f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    const char HAC_VALUE_ON[] = "ON";
3792aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
3802aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
3812aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("setParameters() %s", keyValuePairs.string());
3822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
3832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (keyValuePairs.length() == 0) return BAD_VALUE;
3842aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
385f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    if(hac_enable) {
386f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        key = String8(HAC_KEY);
387f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        if (param.get(key, value) == NO_ERROR) {
388f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            if (value == HAC_VALUE_ON) {
389f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev                mHACSetting = true;
390f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev                LOGD("Enable HAC");
391f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            } else {
392f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev                mHACSetting = false;
393f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev                LOGD("Disable HAC");
394f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            }
395f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        }
396f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    }
397f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev
3982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    key = String8(BT_NREC_KEY);
3992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (param.get(key, value) == NO_ERROR) {
4002aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (value == BT_NREC_VALUE_ON) {
4012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            mBluetoothNrec = true;
4022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        } else {
4032aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            mBluetoothNrec = false;
4042aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            LOGI("Turning noise reduction and echo cancellation off for BT "
4052aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                 "headset");
4062aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
4072aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
4082aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    key = String8(BT_NAME_KEY);
4092aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (param.get(key, value) == NO_ERROR) {
4100f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        mBluetoothIdTx = 0;
4110f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        mBluetoothIdRx = 0;
4120f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        for (int i = 0; i < mNumBTEndpoints; i++) {
4130f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            if (!strcasecmp(value.string(), mBTEndpoints[i].name)) {
4140f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                mBluetoothIdTx = mBTEndpoints[i].tx;
4150f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                mBluetoothIdRx = mBTEndpoints[i].rx;
4162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                LOGI("Using custom acoustic parameters for %s", value.string());
4172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                break;
4182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            }
4192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
4200f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        if (mBluetoothIdTx == 0) {
4212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            LOGI("Using default acoustic parameters "
4222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                 "(%s not in acoustic database)", value.string());
4232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
42411c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent        doRouting();
4252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
426da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    key = String8("noise_suppression");
427da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    if (param.get(key, value) == NO_ERROR) {
428da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent        if (support_a1026 == 1) {
429da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            int noiseSuppressionState;
430da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            if (value == "off") {
431da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                noiseSuppressionState = A1026_NS_STATE_OFF;
432da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            } else if (value == "auto") {
433da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                noiseSuppressionState = A1026_NS_STATE_AUTO;
434da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            } else if (value == "far_talk") {
435da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                noiseSuppressionState = A1026_NS_STATE_FT;
436da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            } else if (value == "close_talk") {
437da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                noiseSuppressionState = A1026_NS_STATE_CT;
438da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            } else {
439da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                return BAD_VALUE;
440da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            }
441da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent
442da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            if (noiseSuppressionState != mNoiseSuppressionState) {
443da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                if (!mA1026Init) {
444da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                    LOGW("Audience A1026 not initialized.\n");
445da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                    return INVALID_OPERATION;
446da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                }
447da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent
44811c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent                mA1026Lock.lock();
449da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                if (fd_a1026 < 0) {
450da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                    fd_a1026 = open("/dev/audience_a1026", O_RDWR);
451da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                    if (fd_a1026 < 0) {
452da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                        LOGE("Cannot open audience_a1026 device (%d)\n", fd_a1026);
45311c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent                        mA1026Lock.unlock();
454da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                        return -1;
455da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                    }
456da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                }
457da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                LOGV("Setting noise suppression %s", value.string());
45811c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent
459da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                int rc = ioctl(fd_a1026, A1026_SET_NS_STATE, &noiseSuppressionState);
460da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                if (!rc) {
461da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                    mNoiseSuppressionState = noiseSuppressionState;
462da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                } else {
463da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                    LOGE("Failed to set noise suppression %s", value.string());
464da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                }
46511c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent                close(fd_a1026);
466da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                mA1026Lock.unlock();
467da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            }
468da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent        } else {
469da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            return INVALID_OPERATION;
470da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent        }
471da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent     }
472da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent
4732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
4742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
4752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
4762aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandString8 AudioHardware::getParameters(const String8& keys)
4772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
478da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    AudioParameter request = AudioParameter(keys);
479da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    AudioParameter reply = AudioParameter();
480da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    String8 value;
481da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    String8 key;
482da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent
483da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    LOGV("getParameters() %s", keys.string());
484da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent
485da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    key = "noise_suppression";
486da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    if (request.get(key, value) == NO_ERROR) {
487da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent        switch(mNoiseSuppressionState) {
488da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent        case A1026_NS_STATE_OFF:
489da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            value = "off";
490da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            break;
491da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent        case A1026_NS_STATE_AUTO:
492da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            value = "auto";
493da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            break;
494da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent        case A1026_NS_STATE_FT:
495da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            value = "far_talk";
496da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            break;
497da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent        case A1026_NS_STATE_CT:
498da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            value = "close_talk";
499da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            break;
500da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent        }
501da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent        reply.add(key, value);
502da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    }
503da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent
504da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    return reply.toString();
5052aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
5062aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
5072aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
5082aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic unsigned calculate_audpre_table_index(unsigned index)
5092aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
5102aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    switch (index) {
5112aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        case 48000:    return SAMP_RATE_INDX_48000;
5122aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        case 44100:    return SAMP_RATE_INDX_44100;
5132aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        case 32000:    return SAMP_RATE_INDX_32000;
5142aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        case 24000:    return SAMP_RATE_INDX_24000;
5152aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        case 22050:    return SAMP_RATE_INDX_22050;
5162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        case 16000:    return SAMP_RATE_INDX_16000;
5172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        case 12000:    return SAMP_RATE_INDX_12000;
5182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        case 11025:    return SAMP_RATE_INDX_11025;
5192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        case 8000:    return SAMP_RATE_INDX_8000;
5202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        default:     return -1;
5212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
5222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
5232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandsize_t AudioHardware::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
5242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
5252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (format != AudioSystem::PCM_16_BIT) {
5262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGW("getInputBufferSize bad format: %d", format);
5272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return 0;
5282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
5292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (channelCount < 1 || channelCount > 2) {
5302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGW("getInputBufferSize bad channel count: %d", channelCount);
5312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return 0;
5322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
5332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
534a4fe0167c6cad83d88b3bc56efa1ffad85b345b5Eric Laurent    return AUDIO_KERNEL_PCM_IN_BUFFERSIZE*channelCount;
5352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
5362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
5372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic status_t set_volume_rpc(uint32_t volume)
5382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
5392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    int fd = -1;
5402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    fd = open("/dev/msm_audio_ctl", O_RDWR);
5412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (fd < 0) {
5422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGE("Cannot open msm_audio_ctl device\n");
5432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return -1;
5442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
5452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    volume *= 20; //percentage
5462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGD("Setting in-call volume to %d\n", volume);
5472aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (ioctl(fd, AUDIO_SET_VOLUME, &volume)) {
5482aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGW("Cannot set volume on current device\n");
5492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
5502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    close(fd);
5512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
5522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
5532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
5542aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::setVoiceVolume(float v)
5552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
5562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (v < 0.0) {
5572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGW("setVoiceVolume(%f) under 0.0, assuming 0.0\n", v);
5582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        v = 0.0;
5592aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else if (v > 1.0) {
5602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGW("setVoiceVolume(%f) over 1.0, assuming 1.0\n", v);
5612aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        v = 1.0;
5622aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
5632aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
564f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    if (mHACSetting && hac_enable)
565f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        v = 1.0;
566f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev
5673964d4ed448b00791bc1b574913be24f44b45f0fEric Laurent    int vol = lrint(v * VOICE_VOLUME_MAX);
5682aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGD("setVoiceVolume(%f)\n", v);
5693964d4ed448b00791bc1b574913be24f44b45f0fEric Laurent    LOGI("Setting in-call volume to %d (available range is 0 to %d)\n", vol, VOICE_VOLUME_MAX);
5702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
5712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    Mutex::Autolock lock(mLock);
5722aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    set_volume_rpc(vol); //always set current device
5733964d4ed448b00791bc1b574913be24f44b45f0fEric Laurent    mVoiceVolume = vol;
5742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
5752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
5762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
5772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::setMasterVolume(float v)
5782aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
5793964d4ed448b00791bc1b574913be24f44b45f0fEric Laurent    LOGI("Set master volume to %f.\n", v);
5802aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // We return an error code here to let the audioflinger do in-software
5812aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // volume on top of the maximum volume that we set through the SND API.
5822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // return error - software mixer will handle it
5832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return -1;
5842aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
5852aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
5867fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivistatic status_t do_route_audio_dev_ctrl(uint32_t device, bool inCall, uint32_t rx_acdb_id, uint32_t tx_acdb_id)
5872aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
5887fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    uint32_t out_device = 0, mic_device = 0;
5897fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    uint32_t path[2];
5902aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    int fd = 0;
5912aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
5922aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (device == SND_DEVICE_CURRENT)
5932aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        goto Incall;
5942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
5952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // hack -- kernel needs to put these in include file
5962aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGD("Switching audio device to ");
5972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (device == SND_DEVICE_HANDSET) {
5982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           out_device = HANDSET_SPKR;
5992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           mic_device = HANDSET_MIC;
6002aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           LOGD("Handset");
6012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else if ((device  == SND_DEVICE_BT) || (device == SND_DEVICE_BT_EC_OFF)) {
6022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           out_device = BT_SCO_SPKR;
6032aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           mic_device = BT_SCO_MIC;
6042aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           LOGD("BT Headset");
605da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    } else if (device == SND_DEVICE_SPEAKER ||
606da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent               device == SND_DEVICE_SPEAKER_BACK_MIC) {
6072aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           out_device = SPKR_PHONE_MONO;
6082aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           mic_device = SPKR_PHONE_MIC;
6092aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           LOGD("Speakerphone");
6102aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else if (device == SND_DEVICE_HEADSET) {
6112aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           out_device = HEADSET_SPKR_STEREO;
6122aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           mic_device = HEADSET_MIC;
6132aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           LOGD("Stereo Headset");
6142aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else if (device == SND_DEVICE_HEADSET_AND_SPEAKER) {
6152aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           out_device = SPKR_PHONE_HEADSET_STEREO;
6162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           mic_device = HEADSET_MIC;
6172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           LOGD("Stereo Headset + Speaker");
61858cf88a5a91d82ae2fb3e23365eaa4524a9cd089Jean-Michel Trivi    } else if (device == SND_DEVICE_HEADSET_AND_SPEAKER_BACK_MIC) {
61958cf88a5a91d82ae2fb3e23365eaa4524a9cd089Jean-Michel Trivi           out_device = SPKR_PHONE_HEADSET_STEREO;
62058cf88a5a91d82ae2fb3e23365eaa4524a9cd089Jean-Michel Trivi           mic_device = SPKR_PHONE_MIC;
62158cf88a5a91d82ae2fb3e23365eaa4524a9cd089Jean-Michel Trivi           LOGD("Stereo Headset + Speaker and back mic");
6222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else if (device == SND_DEVICE_NO_MIC_HEADSET) {
6232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           out_device = HEADSET_SPKR_STEREO;
6242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           mic_device = HANDSET_MIC;
6252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           LOGD("No microphone Wired Headset");
626da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    } else if (device == SND_DEVICE_NO_MIC_HEADSET_BACK_MIC) {
627da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent           out_device = HEADSET_SPKR_STEREO;
628da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent           mic_device = SPKR_PHONE_MIC;
629da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent           LOGD("No microphone Wired Headset and back mic");
630da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    } else if (device == SND_DEVICE_HANDSET_BACK_MIC) {
631da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent           out_device = HANDSET_SPKR;
632da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent           mic_device = SPKR_PHONE_MIC;
633da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent           LOGD("Handset and back mic");
6342aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else if (device == SND_DEVICE_FM_HEADSET) {
6352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           out_device = FM_HEADSET;
6362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           mic_device = HEADSET_MIC;
6372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           LOGD("Stereo FM headset");
6382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else if (device == SND_DEVICE_FM_SPEAKER) {
6392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           out_device = FM_SPKR;
6402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           mic_device = HEADSET_MIC;
6412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           LOGD("Stereo FM speaker");
642c42d5b9bd789034e4e10679b24a7bd38e68f4556Eric Laurent    } else if (device == SND_DEVICE_CARKIT) {
643c42d5b9bd789034e4e10679b24a7bd38e68f4556Eric Laurent           out_device = BT_SCO_SPKR;
644c42d5b9bd789034e4e10679b24a7bd38e68f4556Eric Laurent           mic_device = BT_SCO_MIC;
645c42d5b9bd789034e4e10679b24a7bd38e68f4556Eric Laurent           LOGD("Carkit");
6462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else {
6472aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           LOGE("unknown device %d", device);
6482aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           return -1;
6492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
6502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
6512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#if 0 //Add for FM support
6522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (out_device == FM_HEADSET ||
6532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        out_device == FM_SPKR) {
6542aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (fd_fm_device < 0) {
6552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            fd_fm_device = open("/dev/msm_htc_fm", O_RDWR);
6562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            if (fd_fm_device < 0) {
6572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                LOGE("Cannot open msm_htc_fm device");
6582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                return -1;
6592aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            }
6602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            LOGD("Opened msm_htc_fm for FM radio");
6612aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
6622aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else if (fd_fm_device >= 0) {
6632aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        close(fd_fm_device);
6642aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        fd_fm_device = -1;
6652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGD("Closed msm_htc_fm after FM radio");
6662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
6672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#endif
6682aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
6692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    fd = open("/dev/msm_audio_ctl", O_RDWR);
6702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (fd < 0)        {
6712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland       LOGE("Cannot open msm_audio_ctl");
6722aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland       return -1;
6732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
6747fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    path[0] = out_device;
6757fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    path[1] = rx_acdb_id;
6767fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    if (ioctl(fd, AUDIO_SWITCH_DEVICE, &path)) {
6772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland       LOGE("Cannot switch audio device");
6782aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland       close(fd);
6792aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland       return -1;
6802aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
6817fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    path[0] = mic_device;
6827fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    path[1] = tx_acdb_id;
6837fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    if (ioctl(fd, AUDIO_SWITCH_DEVICE, &path)) {
6842aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland       LOGE("Cannot switch mic device");
6852aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland       close(fd);
6862aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland       return -1;
6872aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
6880f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    curr_out_device = out_device;
6890f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    curr_mic_device = mic_device;
6902aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
6912aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandIncall:
6922aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (inCall == true && !voice_started) {
693f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        if (fd < 0) {
6942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            fd = open("/dev/msm_audio_ctl", O_RDWR);
6952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
6962aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            if (fd < 0) {
6972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                LOGE("Cannot open msm_audio_ctl");
6982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                return -1;
6992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            }
7002aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
701f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        if (rx_acdb_id == ACDB_ID_HAC_HANDSET_SPKR &&
702f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            tx_acdb_id == ACDB_ID_HAC_HANDSET_MIC) {
703f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            path[0] = rx_acdb_id;
704f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            path[1] = tx_acdb_id;
705f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            if (ioctl(fd, AUDIO_START_VOICE, &path)) {
706f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev                LOGE("Cannot start voice");
707f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev                close(fd);
708f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev                return -1;
709f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            }
710f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        } else {
711f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            if (ioctl(fd, AUDIO_START_VOICE, NULL)) {
712f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev                LOGE("Cannot start voice");
713f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev                close(fd);
714f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev                return -1;
715f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            }
7162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
7172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGD("Voice Started!!");
7182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        voice_started = 1;
7192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
7202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    else if (inCall == false && voice_started) {
7212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (fd < 0) {
7222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            fd = open("/dev/msm_audio_ctl", O_RDWR);
7232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
7242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            if (fd < 0) {
7252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                LOGE("Cannot open msm_audio_ctl");
7262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                return -1;
7272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            }
7282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
7292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (ioctl(fd, AUDIO_STOP_VOICE, NULL)) {
7302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland               LOGE("Cannot stop voice");
7312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland               close(fd);
7322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland               return -1;
7332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
7342aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGD("Voice Stopped!!");
7352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        voice_started = 0;
7362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
7372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
7382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    close(fd);
7392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
7402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
7412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
7422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
7432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland// always call with mutex held
7442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::doAudioRouteOrMute(uint32_t device)
7452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
7467fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    uint32_t rx_acdb_id = 0;
7477fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    uint32_t tx_acdb_id = 0;
7487fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi
749f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi    if (support_a1026 == 1)
750f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi            doAudience_A1026_Control(mMode, mRecordState, device);
751f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi
7522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (device == (uint32_t)SND_DEVICE_BT || device == (uint32_t)SND_DEVICE_CARKIT) {
7530f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        if (!mBluetoothNrec) {
7542aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            device = SND_DEVICE_BT_EC_OFF;
7552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
7562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
7577fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi
758f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    if (mMode == AudioSystem::MODE_IN_CALL
759f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            && (device == (int) SND_DEVICE_BT
760f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            || device == (int) SND_DEVICE_BT_EC_OFF)) {
761f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        if (mBluetoothIdTx != 0) {
7627fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi        rx_acdb_id = mBluetoothIdRx;
7637fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi        tx_acdb_id = mBluetoothIdTx;
7647fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    } else {
765f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            /* use default BT entry defined in AudioBTID.csv */
766f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            rx_acdb_id = mBTEndpoints[0].rx;
767f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            tx_acdb_id = mBTEndpoints[0].tx;
768f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            LOGD("Update ACDB ID to default BT setting\n");
769f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        }
770f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    } else if (mMode == AudioSystem::MODE_IN_CALL
771f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            && device == (int) SND_DEVICE_CARKIT) {
772f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        if (mBluetoothIdTx != 0) {
773f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            rx_acdb_id = mBluetoothIdRx;
774f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            tx_acdb_id = mBluetoothIdTx;
775f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        } else {
776f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            /* use default carkit entry defined in AudioBTID.csv */
777f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            rx_acdb_id = mBTEndpoints[1].rx;
778f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            tx_acdb_id = mBTEndpoints[1].tx;
779f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            LOGD("Update ACDB ID to default carkit setting");
780f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        }
781f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    } else if (mMode == AudioSystem::MODE_IN_CALL && hac_enable && mHACSetting) {
782f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        LOGE("Update acdb id to hac profile.");
783f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        rx_acdb_id = ACDB_ID_HAC_HANDSET_SPKR;
784f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        tx_acdb_id = ACDB_ID_HAC_HANDSET_MIC;
785f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    } else {
786f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        if (!checkOutputStandby() || mMode != AudioSystem::MODE_IN_CALL)
7877fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi            rx_acdb_id = getACDB(MOD_PLAY, device);
7887fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi        if (mRecordState)
7897fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi            tx_acdb_id = getACDB(MOD_REC, device);
7907fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    }
7917fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    LOGV("doAudioRouteOrMute: rx acdb %d, tx acdb %d\n", rx_acdb_id, tx_acdb_id);
7927fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi
7937fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    return do_route_audio_dev_ctrl(device, mMode == AudioSystem::MODE_IN_CALL, rx_acdb_id, tx_acdb_id);
7942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
7952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
7962aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::get_mMode(void)
7972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
7982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return mMode;
7992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
8002aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
8012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::get_mRoutes(void)
8022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
8032aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return mRoutes[mMode];
8042aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
8052aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
8062aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::set_mRecordState(bool onoff)
8072aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
8082aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mRecordState = onoff;
8092aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return 0;
8102aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
8112aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
812f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchevstatus_t AudioHardware::get_batt_temp(int *batt_temp)
813f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev{
814f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    int fd, len;
815f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    const char *fn =
816f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        "/sys/devices/platform/rs30100001:00000000/power_supply/battery/batt_temp";
817f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    char get_batt_temp[6] = { 0 };
818f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev
819f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    if ((fd = open(fn, O_RDONLY)) < 0) {
820f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        LOGE("%s: cannot open %s: %s\n", __FUNCTION__, fn, strerror(errno));
821f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        return UNKNOWN_ERROR;
822f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    }
823f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev
824f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    if ((len = read(fd, get_batt_temp, sizeof(get_batt_temp))) <= 1) {
825f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        LOGE("read battery temp fail: %s\n", strerror(errno));
826f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        close(fd);
827f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        return BAD_VALUE;
828f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    }
829f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev
830f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    *batt_temp = strtol(get_batt_temp, NULL, 10);
831f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    close(fd);
832f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    return NO_ERROR;
833f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev}
834f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev
8352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::doA1026_init(void)
8362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
8372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    struct a1026img fwimg;
8382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    char char_tmp = 0;
83908516fe50b023532d5a3010050970de28e14621bIliyan Malchev    unsigned char local_vpimg_buf[A1026_MAX_FW_SIZE], *ptr = local_vpimg_buf;
84008516fe50b023532d5a3010050970de28e14621bIliyan Malchev    int rc = 0, fw_fd = -1;
84108516fe50b023532d5a3010050970de28e14621bIliyan Malchev    ssize_t nr;
84208516fe50b023532d5a3010050970de28e14621bIliyan Malchev    size_t remaining;
84308516fe50b023532d5a3010050970de28e14621bIliyan Malchev    struct stat fw_stat;
8442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
84508516fe50b023532d5a3010050970de28e14621bIliyan Malchev    static const char *const fn = "/system/etc/vpimg";
84608516fe50b023532d5a3010050970de28e14621bIliyan Malchev    static const char *const path = "/dev/audience_a1026";
84708516fe50b023532d5a3010050970de28e14621bIliyan Malchev
84808516fe50b023532d5a3010050970de28e14621bIliyan Malchev    if (fd_a1026 < 0)
84908516fe50b023532d5a3010050970de28e14621bIliyan Malchev        fd_a1026 = open(path, O_RDWR | O_NONBLOCK, 0);
8502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
8512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (fd_a1026 < 0) {
85208516fe50b023532d5a3010050970de28e14621bIliyan Malchev        LOGE("Cannot open %s %d\n", path, fd_a1026);
85308516fe50b023532d5a3010050970de28e14621bIliyan Malchev        support_a1026 = 0;
85408516fe50b023532d5a3010050970de28e14621bIliyan Malchev        goto open_drv_err;
8552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
8562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
85708516fe50b023532d5a3010050970de28e14621bIliyan Malchev    fw_fd = open(fn, O_RDONLY);
85808516fe50b023532d5a3010050970de28e14621bIliyan Malchev    if (fw_fd < 0) {
8592aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGE("Fail to open %s\n", fn);
8602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        goto ld_img_error;
8617fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    } else LOGI("open %s success\n", fn);
8622aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
86308516fe50b023532d5a3010050970de28e14621bIliyan Malchev    rc = fstat(fw_fd, &fw_stat);
86408516fe50b023532d5a3010050970de28e14621bIliyan Malchev    if (rc < 0) {
86508516fe50b023532d5a3010050970de28e14621bIliyan Malchev        LOGE("Cannot stat file %s: %s\n", fn, strerror(errno));
86608516fe50b023532d5a3010050970de28e14621bIliyan Malchev        goto ld_img_error;
86708516fe50b023532d5a3010050970de28e14621bIliyan Malchev    }
86808516fe50b023532d5a3010050970de28e14621bIliyan Malchev
86908516fe50b023532d5a3010050970de28e14621bIliyan Malchev    remaining = (int)fw_stat.st_size;
8702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
87108516fe50b023532d5a3010050970de28e14621bIliyan Malchev    LOGI("Firmware %s size %d\n", fn, remaining);
87208516fe50b023532d5a3010050970de28e14621bIliyan Malchev
87308516fe50b023532d5a3010050970de28e14621bIliyan Malchev    if (remaining > sizeof(local_vpimg_buf)) {
87408516fe50b023532d5a3010050970de28e14621bIliyan Malchev        LOGE("File %s size %d exceeds internal limit %d\n",
87508516fe50b023532d5a3010050970de28e14621bIliyan Malchev             fn, remaining, sizeof(local_vpimg_buf));
87608516fe50b023532d5a3010050970de28e14621bIliyan Malchev        goto ld_img_error;
8772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
8782aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
87908516fe50b023532d5a3010050970de28e14621bIliyan Malchev    while (remaining) {
88008516fe50b023532d5a3010050970de28e14621bIliyan Malchev        nr = read(fw_fd, ptr, remaining);
88108516fe50b023532d5a3010050970de28e14621bIliyan Malchev        if (nr < 0) {
88208516fe50b023532d5a3010050970de28e14621bIliyan Malchev            LOGE("Error reading firmware: %s\n", strerror(errno));
88308516fe50b023532d5a3010050970de28e14621bIliyan Malchev            goto ld_img_error;
88408516fe50b023532d5a3010050970de28e14621bIliyan Malchev        }
88508516fe50b023532d5a3010050970de28e14621bIliyan Malchev        else if (!nr) {
88608516fe50b023532d5a3010050970de28e14621bIliyan Malchev            if (remaining)
88708516fe50b023532d5a3010050970de28e14621bIliyan Malchev                LOGW("EOF reading firmware %s while %d bytes remain\n",
88808516fe50b023532d5a3010050970de28e14621bIliyan Malchev                     fn, remaining);
88908516fe50b023532d5a3010050970de28e14621bIliyan Malchev            break;
89008516fe50b023532d5a3010050970de28e14621bIliyan Malchev        }
89108516fe50b023532d5a3010050970de28e14621bIliyan Malchev        remaining -= nr;
89208516fe50b023532d5a3010050970de28e14621bIliyan Malchev        ptr += nr;
89308516fe50b023532d5a3010050970de28e14621bIliyan Malchev    }
89408516fe50b023532d5a3010050970de28e14621bIliyan Malchev
89508516fe50b023532d5a3010050970de28e14621bIliyan Malchev    close (fw_fd);
89608516fe50b023532d5a3010050970de28e14621bIliyan Malchev    fw_fd = -1;
89708516fe50b023532d5a3010050970de28e14621bIliyan Malchev
8982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    fwimg.buf = local_vpimg_buf;
89908516fe50b023532d5a3010050970de28e14621bIliyan Malchev    fwimg.img_size = (int)(fw_stat.st_size - remaining);
90008516fe50b023532d5a3010050970de28e14621bIliyan Malchev    LOGI("Total %d bytes put to user space buffer.\n", fwimg.img_size);
9012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
9022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    rc = ioctl(fd_a1026, A1026_BOOTUP_INIT, &fwimg);
9032aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (!rc) {
9042aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGI("audience_a1026 init OK\n");
9052aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mA1026Init = 1;
9062aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else
9072aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGE("audience_a1026 init failed\n");
9082aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
9092aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandld_img_error:
91008516fe50b023532d5a3010050970de28e14621bIliyan Malchev    if (fw_fd >= 0)
91108516fe50b023532d5a3010050970de28e14621bIliyan Malchev        close(fw_fd);
9122aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    close(fd_a1026);
9132aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandopen_drv_err:
9142aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    fd_a1026 = -1;
9152aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return rc;
9162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
9172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
9182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::get_snd_dev(void)
9192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
9202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    Mutex::Autolock lock(mLock);
9217161d052ce69228825bd5deca3bfa4a213a99f06HK Chen    return mCurSndDevice;
9222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
9232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
9247fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Triviuint32_t AudioHardware::getACDB(int mode, int device)
9250f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent{
9267fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    uint32_t acdb_id = 0;
927f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    int batt_temp = 0;
9280f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    if (mMode == AudioSystem::MODE_IN_CALL) {
9290f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        LOGD("skip update ACDB due to in-call");
9300f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        return 0;
9310f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    }
9320f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent
9337fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    if (mode == MOD_PLAY) {
9347fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi        switch (device) {
9350f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            case SND_DEVICE_HEADSET:
9360f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            case SND_DEVICE_NO_MIC_HEADSET:
937da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            case SND_DEVICE_NO_MIC_HEADSET_BACK_MIC:
9380f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            case SND_DEVICE_FM_HEADSET:
9390f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                acdb_id = ACDB_ID_HEADSET_PLAYBACK;
9400f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                break;
9410f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            case SND_DEVICE_SPEAKER:
9420f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            case SND_DEVICE_FM_SPEAKER:
943da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            case SND_DEVICE_SPEAKER_BACK_MIC:
9440f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                acdb_id = ACDB_ID_SPKR_PLAYBACK;
945f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev                if(alt_enable) {
946f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev                    LOGD("Enable ALT for speaker\n");
947f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev                    if (get_batt_temp(&batt_temp)) {
948f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev                        if (batt_temp < 50)
949f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev                            acdb_id = ACDB_ID_ALT_SPKR_PLAYBACK;
950f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev                        LOGD("ALT batt temp = %d\n", batt_temp);
951f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev                    }
952f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev                }
9530f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                break;
9540f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            case SND_DEVICE_HEADSET_AND_SPEAKER:
95558cf88a5a91d82ae2fb3e23365eaa4524a9cd089Jean-Michel Trivi            case SND_DEVICE_HEADSET_AND_SPEAKER_BACK_MIC:
9560f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                acdb_id = ACDB_ID_HEADSET_RINGTONE_PLAYBACK;
9570f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                break;
9580f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            default:
9590f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                break;
9600f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        }
9617fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    } else if (mode == MOD_REC) {
9627fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi        switch (device) {
9630f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            case SND_DEVICE_HEADSET:
9640f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            case SND_DEVICE_FM_HEADSET:
9650f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            case SND_DEVICE_FM_SPEAKER:
96658cf88a5a91d82ae2fb3e23365eaa4524a9cd089Jean-Michel Trivi            case SND_DEVICE_HEADSET_AND_SPEAKER:
9670f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                acdb_id = ACDB_ID_EXT_MIC_REC;
9680f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                break;
9690f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            case SND_DEVICE_HANDSET:
9700f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            case SND_DEVICE_NO_MIC_HEADSET:
9710f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            case SND_DEVICE_SPEAKER:
97208516fe50b023532d5a3010050970de28e14621bIliyan Malchev                if (vr_mode_enabled == 0) {
97363af0f3cbd387e97bcaca82d1e22787c224d6430Jean-Michel Trivi                    acdb_id = ACDB_ID_INT_MIC_REC;
97463af0f3cbd387e97bcaca82d1e22787c224d6430Jean-Michel Trivi                } else {
97563af0f3cbd387e97bcaca82d1e22787c224d6430Jean-Michel Trivi                    acdb_id = ACDB_ID_INT_MIC_VR;
97663af0f3cbd387e97bcaca82d1e22787c224d6430Jean-Michel Trivi                }
97763af0f3cbd387e97bcaca82d1e22787c224d6430Jean-Michel Trivi                break;
978da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            case SND_DEVICE_SPEAKER_BACK_MIC:
979da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            case SND_DEVICE_NO_MIC_HEADSET_BACK_MIC:
980da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            case SND_DEVICE_HANDSET_BACK_MIC:
98158cf88a5a91d82ae2fb3e23365eaa4524a9cd089Jean-Michel Trivi            case SND_DEVICE_HEADSET_AND_SPEAKER_BACK_MIC:
98263af0f3cbd387e97bcaca82d1e22787c224d6430Jean-Michel Trivi                acdb_id = ACDB_ID_CAMCORDER;
9830f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                break;
9840f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            default:
9850f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                break;
9860f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        }
9870f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    }
9887fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    LOGV("getACDB, return ID %d\n", acdb_id);
9897fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    return acdb_id;
9900f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent}
9910f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent
992f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchevstatus_t AudioHardware::do_tpa2018_control(int mode)
993f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev{
994f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    if (curr_out_device == HANDSET_SPKR ||
995f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        curr_out_device == SPKR_PHONE_MONO ||
996f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        curr_out_device == HEADSET_SPKR_STEREO ||
997f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        curr_out_device == SPKR_PHONE_HEADSET_STEREO ||
998f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        curr_out_device == FM_SPKR) {
999f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev
1000f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev	int fd, rc;
1001f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        int retry = 3;
1002f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev
1003f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        switch (mode) {
1004f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        case AudioSystem::MODE_NORMAL:
1005f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            mode = TPA2018_MODE_PLAYBACK;
1006f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            break;
1007f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        case AudioSystem::MODE_RINGTONE:
1008f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            mode = TPA2018_MODE_RINGTONE;
1009f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            break;
1010f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        case AudioSystem::MODE_IN_CALL:
1011f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            mode = TPA2018_MODE_VOICE_CALL;
1012f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            break;
1013f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        default:
1014f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            return 0;
1015f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        }
1016f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev
1017f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        fd = open("/dev/tpa2018d1", O_RDWR);
1018f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        if (fd < 0) {
1019f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            LOGE("can't open /dev/tpa2018d1 %d", fd);
1020f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            return -1;
1021f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        }
1022f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev
1023f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        do {
1024f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            rc = ioctl(fd, TPA2018_SET_MODE, &mode);
1025f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            if (!rc)
1026f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev                break;
1027f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        } while (--retry);
1028f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev
1029f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        if (rc < 0) {
1030f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            LOGE("ioctl TPA2018_SET_MODE failed: %s", strerror(errno));
1031f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        } else
1032f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            LOGD("Update TPA2018_SET_MODE to mode %d success", mode);
1033f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev
1034f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        close(fd);
1035f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    }
1036f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    return 0;
1037f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev}
10387fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi
10392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::doAudience_A1026_Control(int Mode, bool Record, uint32_t Routes)
10402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
10412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    int rc = 0;
10420f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    int retry = 4;
10432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
10442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (!mA1026Init) {
104511c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent        LOGW("Audience A1026 not initialized.\n");
104611c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent        return NO_INIT;
10472aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
10482aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
104911c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent    mA1026Lock.lock();
10502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (fd_a1026 < 0) {
10512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        fd_a1026 = open("/dev/audience_a1026", O_RDWR);
10522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (fd_a1026 < 0) {
10532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            LOGE("Cannot open audience_a1026 device (%d)\n", fd_a1026);
105411c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent            mA1026Lock.unlock();
10552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            return -1;
105611c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent        }
10572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
10582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
10592aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if ((Mode < AudioSystem::MODE_CURRENT) || (Mode >= AudioSystem::NUM_MODES)) {
10602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGW("Illegal value: doAudience_A1026_Control(%d, %u, %u)", Mode, Record, Routes);
10612aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mA1026Lock.unlock();
10622aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return BAD_VALUE;
10632aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
10642aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
10652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (Mode == AudioSystem::MODE_IN_CALL) {
10662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (Record == 1) {
10672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	    switch (Routes) {
10682aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        case SND_DEVICE_HANDSET:
10692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        case SND_DEVICE_NO_MIC_HEADSET:
1070da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent	            //TODO: what do we do for camcorder when in call?
1071da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent	        case SND_DEVICE_NO_MIC_HEADSET_BACK_MIC:
1072da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent	        case SND_DEVICE_HANDSET_BACK_MIC:
10739ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	            if (enable1026) {
10744bcd5b16c66bc5c2bffe232f15f5cb83aea18318Jean-Michel Trivi                    new_pathid = A1026_PATH_INCALL_RECEIVER;
107563af0f3cbd387e97bcaca82d1e22787c224d6430Jean-Michel Trivi                    LOGV("A1026 control: new path is A1026_PATH_INCALL_RECEIVER");
10769ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	            } else {
10779ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	                new_pathid = A1026_PATH_INCALL_NO_NS_RECEIVER;
10789ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	                LOGV("A1026 control: new path is A1026_PATH_INCALL_NO_NS_RECEIVER");
10799ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	            }
10809ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	            break;
10819ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	        case SND_DEVICE_HEADSET:
10829ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	        case SND_DEVICE_HEADSET_AND_SPEAKER:
10839ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	        case SND_DEVICE_FM_HEADSET:
10849ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	        case SND_DEVICE_FM_SPEAKER:
10859ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	        case SND_DEVICE_HEADSET_AND_SPEAKER_BACK_MIC:
10864bcd5b16c66bc5c2bffe232f15f5cb83aea18318Jean-Michel Trivi	            new_pathid = A1026_PATH_INCALL_HEADSET;
108763af0f3cbd387e97bcaca82d1e22787c224d6430Jean-Michel Trivi	            LOGV("A1026 control: new path is A1026_PATH_INCALL_HEADSET");
10882aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            break;
10892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        case SND_DEVICE_SPEAKER:
1090da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent	            //TODO: what do we do for camcorder when in call?
1091da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent	        case SND_DEVICE_SPEAKER_BACK_MIC:
10924bcd5b16c66bc5c2bffe232f15f5cb83aea18318Jean-Michel Trivi	            new_pathid = A1026_PATH_INCALL_SPEAKER;
109363af0f3cbd387e97bcaca82d1e22787c224d6430Jean-Michel Trivi	            LOGV("A1026 control: new path is A1026_PATH_INCALL_SPEAKER");
10942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            break;
10952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        case SND_DEVICE_BT:
10962aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        case SND_DEVICE_BT_EC_OFF:
1097c42d5b9bd789034e4e10679b24a7bd38e68f4556Eric Laurent	        case SND_DEVICE_CARKIT:
10984bcd5b16c66bc5c2bffe232f15f5cb83aea18318Jean-Michel Trivi	            new_pathid = A1026_PATH_INCALL_BT;
109963af0f3cbd387e97bcaca82d1e22787c224d6430Jean-Michel Trivi	            LOGV("A1026 control: new path is A1026_PATH_INCALL_BT");
11002aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            break;
11012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        default:
11022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            break;
11032aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            }
11042aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland       } else {
11052aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           switch (Routes) {
11062aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        case SND_DEVICE_HANDSET:
11072aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        case SND_DEVICE_NO_MIC_HEADSET:
11089ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	            if (enable1026) {
11099ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	                new_pathid = A1026_PATH_INCALL_RECEIVER; /* NS CT mode, Dual MIC */
111063af0f3cbd387e97bcaca82d1e22787c224d6430Jean-Michel Trivi                    LOGV("A1026 control: new path is A1026_PATH_INCALL_RECEIVER");
11119ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	            } else {
11129ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	                new_pathid = A1026_PATH_INCALL_NO_NS_RECEIVER;
11139ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	                LOGV("A1026 control: new path is A1026_PATH_INCALL_NO_NS_RECEIVER");
11149ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	            }
11159ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	            break;
11169ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	        case SND_DEVICE_HEADSET:
11179ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	        case SND_DEVICE_HEADSET_AND_SPEAKER:
11189ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	        case SND_DEVICE_FM_HEADSET:
11199ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	        case SND_DEVICE_FM_SPEAKER:
11202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            new_pathid = A1026_PATH_INCALL_HEADSET; /* NS disable, Headset MIC */
112163af0f3cbd387e97bcaca82d1e22787c224d6430Jean-Michel Trivi	            LOGV("A1026 control: new path is A1026_PATH_INCALL_HEADSET");
11222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            break;
11232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        case SND_DEVICE_SPEAKER:
11242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            new_pathid = A1026_PATH_INCALL_SPEAKER; /* NS FT mode, Main MIC */
112563af0f3cbd387e97bcaca82d1e22787c224d6430Jean-Michel Trivi	            LOGV("A1026 control: new path is A1026_PATH_INCALL_SPEAKER");
11262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            break;
11272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        case SND_DEVICE_BT:
11282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        case SND_DEVICE_BT_EC_OFF:
1129c42d5b9bd789034e4e10679b24a7bd38e68f4556Eric Laurent	        case SND_DEVICE_CARKIT:
11302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            new_pathid = A1026_PATH_INCALL_BT; /* QCOM NS, BT MIC */
113163af0f3cbd387e97bcaca82d1e22787c224d6430Jean-Michel Trivi	            LOGV("A1026 control: new path is A1026_PATH_INCALL_BT");
11322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            break;
11332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        default:
11342aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            break;
11352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            }
11362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland       }
11372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else if (Record == 1) {
11382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        switch (Routes) {
1139ba36d4fa33072ef14183365fffd289762c26905eJean-Michel Trivi        case SND_DEVICE_SPEAKER:
1140ba36d4fa33072ef14183365fffd289762c26905eJean-Michel Trivi            // default output is speaker, recording from phone mic, user RECEIVER configuration
1141739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        case SND_DEVICE_HANDSET:
1142739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        case SND_DEVICE_NO_MIC_HEADSET:
114308516fe50b023532d5a3010050970de28e14621bIliyan Malchev	        if (vr_mode_enabled) {
1144739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	            if (vr_uses_ns) {
11454bcd5b16c66bc5c2bffe232f15f5cb83aea18318Jean-Michel Trivi	                new_pathid = A1026_PATH_VR_NS_RECEIVER;
1146739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	                LOGV("A1026 control: new path is A1026_PATH_VR_NS_RECEIVER");
1147739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	            } else {
11484bcd5b16c66bc5c2bffe232f15f5cb83aea18318Jean-Michel Trivi	                new_pathid = A1026_PATH_VR_NO_NS_RECEIVER;
1149739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	                LOGV("A1026 control: new path is A1026_PATH_VR_NO_NS_RECEIVER");
1150739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	            }
1151739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	        } else {
11529ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	            new_pathid = A1026_PATH_RECORD_RECEIVER; /* INT-MIC Recording: NS disable, Main MIC */
1153739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi                LOGV("A1026 control: new path is A1026_PATH_RECORD_RECEIVER");
1154739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	        }
11552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        break;
1156739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        case SND_DEVICE_HEADSET:
1157739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        case SND_DEVICE_HEADSET_AND_SPEAKER:
1158739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        case SND_DEVICE_FM_HEADSET:
1159739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        case SND_DEVICE_FM_SPEAKER:
116008516fe50b023532d5a3010050970de28e14621bIliyan Malchev	        if (vr_mode_enabled) {
1161739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	            if (vr_uses_ns) {
11624bcd5b16c66bc5c2bffe232f15f5cb83aea18318Jean-Michel Trivi	                new_pathid = A1026_PATH_VR_NS_HEADSET;
1163739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	                LOGV("A1026 control: new path is A1026_PATH_VR_NS_HEADSET");
1164739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	            } else {
11654bcd5b16c66bc5c2bffe232f15f5cb83aea18318Jean-Michel Trivi	                new_pathid = A1026_PATH_VR_NO_NS_HEADSET;
1166739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	                LOGV("A1026 control: new path is A1026_PATH_VR_NO_NS_HEADSET");
1167739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	            }
1168739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	        } else {
1169739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	            new_pathid = A1026_PATH_RECORD_HEADSET; /* EXT-MIC Recording: NS disable, Headset MIC */
1170739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	            LOGV("A1026 control: new path is A1026_PATH_RECORD_HEADSET");
1171739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	        }
1172739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	        break;
1173739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        case SND_DEVICE_SPEAKER_BACK_MIC:
1174739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        case SND_DEVICE_NO_MIC_HEADSET_BACK_MIC:
1175739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        case SND_DEVICE_HANDSET_BACK_MIC:
117658cf88a5a91d82ae2fb3e23365eaa4524a9cd089Jean-Michel Trivi        case SND_DEVICE_HEADSET_AND_SPEAKER_BACK_MIC:
1177da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent	        new_pathid = A1026_PATH_CAMCORDER; /* CAM-Coder: NS FT mode, Back MIC */
1178f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi	        LOGV("A1026 control: new path is A1026_PATH_CAMCORDER");
11792aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        break;
1180739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        case SND_DEVICE_BT:
1181739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        case SND_DEVICE_BT_EC_OFF:
1182c42d5b9bd789034e4e10679b24a7bd38e68f4556Eric Laurent        case SND_DEVICE_CARKIT:
118308516fe50b023532d5a3010050970de28e14621bIliyan Malchev	        if (vr_mode_enabled) {
1184739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	            if (vr_uses_ns) {
11854bcd5b16c66bc5c2bffe232f15f5cb83aea18318Jean-Michel Trivi	                new_pathid = A1026_PATH_VR_NS_BT;
1186739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	                LOGV("A1026 control: new path is A1026_PATH_VR_NS_BT");
1187739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	            } else {
11884bcd5b16c66bc5c2bffe232f15f5cb83aea18318Jean-Michel Trivi	                new_pathid = A1026_PATH_VR_NO_NS_BT;
1189739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	                LOGV("A1026 control: new path is A1026_PATH_VR_NO_NS_BT");
1190739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	            }
1191739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	        } else {
1192739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	            new_pathid = A1026_PATH_RECORD_BT; /* BT MIC */
1193739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	            LOGV("A1026 control: new path is A1026_PATH_RECORD_BT");
1194739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	        }
11952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        break;
1196739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        default:
11972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        break;
11982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
11992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
12002aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    else {
12012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        new_pathid = A1026_PATH_SUSPEND;
12022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
12032aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
12042aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (old_pathid != new_pathid) {
12052aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        //LOGI("A1026: do ioctl(A1026_SET_CONFIG) to %d\n", new_pathid);
12060f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        do {
12070f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            rc = ioctl(fd_a1026, A1026_SET_CONFIG, &new_pathid);
12080f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            if (!rc) {
12090f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                old_pathid = new_pathid;
12100f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                break;
12110f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            }
12120f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        } while (--retry);
12130f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent
12140f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        if (rc < 0) {
12150f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            LOGE("A1026 do hard reset to recover from error!\n");
12160f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            rc = doA1026_init(); /* A1026 needs to do hard reset! */
12170f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            if (!rc) {
121811c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent                rc = ioctl(fd_a1026, A1026_SET_CONFIG, &new_pathid);
121911c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent                if (!rc)
122011c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent                    old_pathid = new_pathid;
122111c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent                else
12220f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                    LOGE("A1026 Fatal Error!\n");
12230f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            } else
12240f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                LOGE("A1026 Fatal Error: Re-init A1026 Failed\n");
12250f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        }
12262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
12272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
12282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    close(fd_a1026);
12292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    fd_a1026 = -1;
123011c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent    mA1026Lock.unlock();
12312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
12322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return rc;
12332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
12342aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
12352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
123611c6a166fa684a2e44d22a142aad106f74a9409fEric Laurentstatus_t AudioHardware::doRouting()
12372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
1238f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi    Mutex::Autolock lock(mLock);
1239f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi    uint32_t outputDevices = mOutput->devices();
12402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    status_t ret = NO_ERROR;
124111c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent    AudioStreamInMSM72xx *input = getActiveInput_l();
124211c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent    uint32_t inputDevice = (input == NULL) ? 0 : input->devices();
1243f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi    int sndDevice = -1;
12442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
124511c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent    if (inputDevice != 0) {
1246f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        LOGI("do input routing device %x\n", inputDevice);
1247710f4558c4f660e59551b1ed13c5106f9e460a59Eric Laurent        if (inputDevice & AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
1248710f4558c4f660e59551b1ed13c5106f9e460a59Eric Laurent            LOGI("Routing audio to Bluetooth PCM\n");
1249710f4558c4f660e59551b1ed13c5106f9e460a59Eric Laurent            sndDevice = SND_DEVICE_BT;
1250710f4558c4f660e59551b1ed13c5106f9e460a59Eric Laurent        } else if (inputDevice & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT) {
1251710f4558c4f660e59551b1ed13c5106f9e460a59Eric Laurent            LOGI("Routing audio to Bluetooth car kit\n");
1252710f4558c4f660e59551b1ed13c5106f9e460a59Eric Laurent            sndDevice = SND_DEVICE_CARKIT;
1253710f4558c4f660e59551b1ed13c5106f9e460a59Eric Laurent        } else if (inputDevice & AudioSystem::DEVICE_IN_WIRED_HEADSET) {
1254710f4558c4f660e59551b1ed13c5106f9e460a59Eric Laurent            if ((outputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) &&
1255710f4558c4f660e59551b1ed13c5106f9e460a59Eric Laurent                    (outputDevices & AudioSystem::DEVICE_OUT_SPEAKER)) {
1256710f4558c4f660e59551b1ed13c5106f9e460a59Eric Laurent                        LOGI("Routing audio to Wired Headset and Speaker\n");
1257710f4558c4f660e59551b1ed13c5106f9e460a59Eric Laurent                        sndDevice = SND_DEVICE_HEADSET_AND_SPEAKER;
1258f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi            } else {
125911c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent                LOGI("Routing audio to Wired Headset\n");
126011c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent                sndDevice = SND_DEVICE_HEADSET;
126111c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent            }
126211c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent        } else if (inputDevice & AudioSystem::DEVICE_IN_BACK_MIC) {
126311c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent            if (outputDevices & (AudioSystem:: DEVICE_OUT_WIRED_HEADSET) &&
126411c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent                   (outputDevices & AudioSystem:: DEVICE_OUT_SPEAKER)) {
126511c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent                LOGI("Routing audio to Wired Headset and Speaker with back mic\n");
126611c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent                sndDevice = SND_DEVICE_HEADSET_AND_SPEAKER_BACK_MIC;
126711c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent            } else if (outputDevices & AudioSystem::DEVICE_OUT_SPEAKER) {
126811c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent                LOGI("Routing audio to Speakerphone with back mic\n");
126911c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent                sndDevice = SND_DEVICE_SPEAKER_BACK_MIC;
127011c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent            } else if (outputDevices == AudioSystem::DEVICE_OUT_EARPIECE) {
127111c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent                LOGI("Routing audio to Handset with back mic\n");
127211c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent                sndDevice = SND_DEVICE_HANDSET_BACK_MIC;
127311c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent            } else {
127411c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent                LOGI("Routing audio to Headset with back mic\n");
127511c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent                sndDevice = SND_DEVICE_NO_MIC_HEADSET_BACK_MIC;
127611c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent            }
127711c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent        } else {
127811c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent            if (outputDevices & AudioSystem::DEVICE_OUT_SPEAKER) {
127911c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent                LOGI("Routing audio to Speakerphone\n");
128011c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent                sndDevice = SND_DEVICE_SPEAKER;
128111c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent            } else if (outputDevices == AudioSystem::DEVICE_OUT_WIRED_HEADPHONE) {
128211c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent                LOGI("Routing audio to Speakerphone\n");
128311c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent                sndDevice = SND_DEVICE_NO_MIC_HEADSET;
128411c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent            } else {
128511c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent                LOGI("Routing audio to Handset\n");
128611c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent                sndDevice = SND_DEVICE_HANDSET;
1287956f7ba5ee0f087c91b5fefd2718dae30f8c1e29Eric Laurent            }
1288956f7ba5ee0f087c91b5fefd2718dae30f8c1e29Eric Laurent        }
1289f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi    }
129011c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent    // if inputDevice == 0, restore output routing
1291956f7ba5ee0f087c91b5fefd2718dae30f8c1e29Eric Laurent
1292f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi    if (sndDevice == -1) {
1293f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        if (outputDevices & (outputDevices - 1)) {
1294f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi            if ((outputDevices & AudioSystem::DEVICE_OUT_SPEAKER) == 0) {
1295f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                LOGW("Hardware does not support requested route combination (%#X),"
1296f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                        " picking closest possible route...", outputDevices);
1297956f7ba5ee0f087c91b5fefd2718dae30f8c1e29Eric Laurent            }
1298f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        }
1299956f7ba5ee0f087c91b5fefd2718dae30f8c1e29Eric Laurent
1300f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        if (outputDevices &
1301dd65e38951ed174f9d3d34886795438440f7eea0Eric Laurent                (AudioSystem::DEVICE_OUT_BLUETOOTH_SCO | AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET)) {
1302f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                    LOGI("Routing audio to Bluetooth PCM\n");
1303f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                    sndDevice = SND_DEVICE_BT;
1304f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        } else if (outputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT) {
1305f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi            LOGI("Routing audio to Bluetooth PCM\n");
1306f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi            sndDevice = SND_DEVICE_CARKIT;
1307f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        } else if ((outputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) &&
1308f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                (outputDevices & AudioSystem::DEVICE_OUT_SPEAKER)) {
1309f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                    LOGI("Routing audio to Wired Headset and Speaker\n");
1310956f7ba5ee0f087c91b5fefd2718dae30f8c1e29Eric Laurent                    sndDevice = SND_DEVICE_HEADSET_AND_SPEAKER;
1311f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        } else if (outputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE) {
1312f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi            if (outputDevices & AudioSystem::DEVICE_OUT_SPEAKER) {
1313f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                LOGI("Routing audio to No microphone Wired Headset and Speaker (%d,%x)\n", mMode, outputDevices);
1314f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                sndDevice = SND_DEVICE_HEADSET_AND_SPEAKER;
1315956f7ba5ee0f087c91b5fefd2718dae30f8c1e29Eric Laurent            } else {
1316f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                LOGI("Routing audio to No microphone Wired Headset (%d,%x)\n", mMode, outputDevices);
1317f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                sndDevice = SND_DEVICE_NO_MIC_HEADSET;
13182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            }
1319f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        } else if (outputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) {
1320f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi            LOGI("Routing audio to Wired Headset\n");
1321f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi            sndDevice = SND_DEVICE_HEADSET;
1322f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        } else if (outputDevices & AudioSystem::DEVICE_OUT_SPEAKER) {
1323f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi            LOGI("Routing audio to Speakerphone\n");
1324f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi            sndDevice = SND_DEVICE_SPEAKER;
1325f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        } else {
1326f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi            LOGI("Routing audio to Handset\n");
1327f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi            sndDevice = SND_DEVICE_HANDSET;
13282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
1329f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi    }
13302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
1331f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi    if ((vr_mode_change) || (sndDevice != -1 && sndDevice != mCurSndDevice)) {
1332f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        ret = doAudioRouteOrMute(sndDevice);
1333f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        mCurSndDevice = sndDevice;
13343964d4ed448b00791bc1b574913be24f44b45f0fEric Laurent        if (mMode == AudioSystem::MODE_IN_CALL) {
13353964d4ed448b00791bc1b574913be24f44b45f0fEric Laurent            set_volume_rpc(mVoiceVolume);
13363964d4ed448b00791bc1b574913be24f44b45f0fEric Laurent        }
13372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
13382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
13392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return ret;
13402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
13412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
13422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::checkMicMute()
13432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
13442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    Mutex::Autolock lock(mLock);
13452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mMode != AudioSystem::MODE_IN_CALL) {
13462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        setMicMute_nosync(true);
13472aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
13482aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
13492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
13502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
13512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
13522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::dumpInternals(int fd, const Vector<String16>& args)
13532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
13542aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    const size_t SIZE = 256;
13552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    char buffer[SIZE];
13562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    String8 result;
13572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append("AudioHardware::dumpInternals\n");
13582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmInit: %s\n", mInit? "true": "false");
13592aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
13602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmMicMute: %s\n", mMicMute? "true": "false");
13612aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
13622aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmBluetoothNrec: %s\n", mBluetoothNrec? "true": "false");
13632aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
13640f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    snprintf(buffer, SIZE, "\tmBluetoothIdtx: %d\n", mBluetoothIdTx);
13650f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    result.append(buffer);
13660f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    snprintf(buffer, SIZE, "\tmBluetoothIdrx: %d\n", mBluetoothIdRx);
13672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
13682aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    ::write(fd, result.string(), result.size());
13692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
13702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
13712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
13722aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::dump(int fd, const Vector<String16>& args)
13732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
13742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    dumpInternals(fd, args);
13752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    for (size_t index = 0; index < mInputs.size(); index++) {
13762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mInputs[index]->dump(fd, args);
13772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
13782aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
13792aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mOutput) {
13802aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mOutput->dump(fd, args);
13812aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
13822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
13832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
13842aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
13852aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlanduint32_t AudioHardware::getInputSampleRate(uint32_t sampleRate)
13862aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
13872aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    uint32_t i;
13882aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    uint32_t prevDelta;
13892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    uint32_t delta;
13902aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
13912aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    for (i = 0, prevDelta = 0xFFFFFFFF; i < sizeof(inputSamplingRates)/sizeof(uint32_t); i++, prevDelta = delta) {
13922aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        delta = abs(sampleRate - inputSamplingRates[i]);
13932aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (delta > prevDelta) break;
13942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
13952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // i is always > 0 here
13962aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return inputSamplingRates[i-1];
13972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
13982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
139911c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent// getActiveInput_l() must be called with mLock held
140011c6a166fa684a2e44d22a142aad106f74a9409fEric LaurentAudioHardware::AudioStreamInMSM72xx *AudioHardware::getActiveInput_l()
140111c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent{
140211c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent    for (size_t i = 0; i < mInputs.size(); i++) {
140311c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent        // return first input found not being in standby mode
140411c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent        // as only one input can be in this state
140511c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent        if (mInputs[i]->state() > AudioStreamInMSM72xx::AUDIO_INPUT_CLOSED) {
140611c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent            return mInputs[i];
140711c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent        }
140811c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent    }
140911c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent
141011c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent    return NULL;
141111c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent}
14122aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland// ----------------------------------------------------------------------------
14132aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
14142aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandAudioHardware::AudioStreamOutMSM72xx::AudioStreamOutMSM72xx() :
14152aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mHardware(0), mFd(-1), mStartCount(0), mRetryCount(0), mStandby(true), mDevices(0)
14162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
14172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
14182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
14192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::AudioStreamOutMSM72xx::set(
14202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        AudioHardware* hw, uint32_t devices, int *pFormat, uint32_t *pChannels, uint32_t *pRate)
14212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
14222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    int lFormat = pFormat ? *pFormat : 0;
14232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    uint32_t lChannels = pChannels ? *pChannels : 0;
14242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    uint32_t lRate = pRate ? *pRate : 0;
14252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
14262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mHardware = hw;
14272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
14282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // fix up defaults
14292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (lFormat == 0) lFormat = format();
14302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (lChannels == 0) lChannels = channels();
14312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (lRate == 0) lRate = sampleRate();
14322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
14332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // check values
14342aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if ((lFormat != format()) ||
14352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        (lChannels != channels()) ||
14362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        (lRate != sampleRate())) {
14372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (pFormat) *pFormat = format();
14382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (pChannels) *pChannels = channels();
14392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (pRate) *pRate = sampleRate();
14402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return BAD_VALUE;
14412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
14422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
14432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (pFormat) *pFormat = lFormat;
14442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (pChannels) *pChannels = lChannels;
14452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (pRate) *pRate = lRate;
14462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
14472aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mDevices = devices;
14482aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
14492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
14502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
14512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
14522aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandAudioHardware::AudioStreamOutMSM72xx::~AudioStreamOutMSM72xx()
14532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
14542aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mFd >= 0) close(mFd);
14552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
14562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
14572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandssize_t AudioHardware::AudioStreamOutMSM72xx::write(const void* buffer, size_t bytes)
14582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
14592aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // LOGD("AudioStreamOutMSM72xx::write(%p, %u)", buffer, bytes);
14602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    status_t status = NO_INIT;
14612aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    size_t count = bytes;
14622aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    const uint8_t* p = static_cast<const uint8_t*>(buffer);
14632aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
14642aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mStandby) {
14652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
14662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        // open driver
14672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGV("open pcm_out driver");
14682aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        status = ::open("/dev/msm_pcm_out", O_RDWR);
14692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (status < 0) {
14702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            if (errCount++ < 10) {
14712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                LOGE("Cannot open /dev/msm_pcm_out errno: %d", errno);
14722aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            }
14732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            goto Error;
14742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
14752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mFd = status;
14762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
14772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        // configuration
14782aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGV("get config");
14792aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        struct msm_audio_config config;
14802aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        status = ioctl(mFd, AUDIO_GET_CONFIG, &config);
14812aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (status < 0) {
14822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            LOGE("Cannot read pcm_out config");
14832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            goto Error;
14842aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
14852aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
14862aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGV("set pcm_out config");
14872aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        config.channel_count = AudioSystem::popCount(channels());
14882aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        config.sample_rate = sampleRate();
14892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        config.buffer_size = bufferSize();
14902aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        config.buffer_count = AUDIO_HW_NUM_OUT_BUF;
14912aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        config.codec_type = CODEC_TYPE_PCM;
14922aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        status = ioctl(mFd, AUDIO_SET_CONFIG, &config);
14932aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (status < 0) {
14942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            LOGE("Cannot set config");
14952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            goto Error;
14962aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
14972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
14982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGV("buffer_size: %u", config.buffer_size);
14992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGV("buffer_count: %u", config.buffer_count);
15002aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGV("channel_count: %u", config.channel_count);
15012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGV("sample_rate: %u", config.sample_rate);
15022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
15037fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi        uint32_t acdb_id = mHardware->getACDB(MOD_PLAY, mHardware->get_snd_dev());
15047fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi        status = ioctl(mFd, AUDIO_START, &acdb_id);
150531923bb6797ec304d26395acf6d946ab8e44aa6eHK Chen        if (status < 0) {
150631923bb6797ec304d26395acf6d946ab8e44aa6eHK Chen            LOGE("Cannot start pcm playback");
150731923bb6797ec304d26395acf6d946ab8e44aa6eHK Chen            goto Error;
15082aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
150910254cc35f5cb7ebe2c7ef452815486cb8e92a33Jean-Michel Trivi
151010254cc35f5cb7ebe2c7ef452815486cb8e92a33Jean-Michel Trivi        status = ioctl(mFd, AUDIO_SET_VOLUME, &stream_volume);
151110254cc35f5cb7ebe2c7ef452815486cb8e92a33Jean-Michel Trivi        if (status < 0) {
151210254cc35f5cb7ebe2c7ef452815486cb8e92a33Jean-Michel Trivi            LOGE("Cannot start pcm playback");
151310254cc35f5cb7ebe2c7ef452815486cb8e92a33Jean-Michel Trivi            goto Error;
151410254cc35f5cb7ebe2c7ef452815486cb8e92a33Jean-Michel Trivi        }
151510254cc35f5cb7ebe2c7ef452815486cb8e92a33Jean-Michel Trivi
15165d89308f2e1252eff2743bf823bf558dbb0de2faDave Sparks        LOGV("acquire wakelock");
15175d89308f2e1252eff2743bf823bf558dbb0de2faDave Sparks        acquire_wake_lock(PARTIAL_WAKE_LOCK, kOutputWakelockStr);
151831923bb6797ec304d26395acf6d946ab8e44aa6eHK Chen        mStandby = false;
15192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
15202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
15212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    while (count) {
15222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        ssize_t written = ::write(mFd, p, count);
15232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (written >= 0) {
15242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            count -= written;
15252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            p += written;
15262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        } else {
15272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            if (errno != EAGAIN) return written;
15282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            mRetryCount++;
15292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            LOGW("EAGAIN - retry");
15302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
15312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
15322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
15332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return bytes;
15342aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
15352aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandError:
15362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mFd >= 0) {
15372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        ::close(mFd);
15382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mFd = -1;
15392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
15402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // Simulate audio output timing in case of error
15412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    usleep(bytes * 1000000 / frameSize() / sampleRate());
15422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
15432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return status;
15442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
15452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
15462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::AudioStreamOutMSM72xx::standby()
15472aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
15482aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    status_t status = NO_ERROR;
15492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (!mStandby && mFd >= 0) {
15502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        ::close(mFd);
15512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mFd = -1;
15525d89308f2e1252eff2743bf823bf558dbb0de2faDave Sparks        LOGV("release wakelock");
15535d89308f2e1252eff2743bf823bf558dbb0de2faDave Sparks        release_wake_lock(kOutputWakelockStr);
15542aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
15552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mStandby = true;
15562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGI("AudioHardware pcm playback is going to standby.");
15572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return status;
15582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
15592aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
15602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::AudioStreamOutMSM72xx::dump(int fd, const Vector<String16>& args)
15612aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
15622aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    const size_t SIZE = 256;
15632aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    char buffer[SIZE];
15642aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    String8 result;
15652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append("AudioStreamOutMSM72xx::dump\n");
15662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tsample rate: %d\n", sampleRate());
15672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
15682aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize());
15692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
15702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tchannels: %d\n", channels());
15712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
15722aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tformat: %d\n", format());
15732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
15742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmHardware: %p\n", mHardware);
15752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
15762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmFd: %d\n", mFd);
15772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
15782aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmStartCount: %d\n", mStartCount);
15792aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
15802aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmRetryCount: %d\n", mRetryCount);
15812aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
15822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmStandby: %s\n", mStandby? "true": "false");
15832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
15842aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    ::write(fd, result.string(), result.size());
15852aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
15862aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
15872aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
15882aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandbool AudioHardware::AudioStreamOutMSM72xx::checkStandby()
15892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
15902aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return mStandby;
15912aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
15922aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
15932aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
15942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::AudioStreamOutMSM72xx::setParameters(const String8& keyValuePairs)
15952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
15962aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    AudioParameter param = AudioParameter(keyValuePairs);
15972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    String8 key = String8(AudioParameter::keyRouting);
15982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    status_t status = NO_ERROR;
15992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    int device;
16002aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("AudioStreamOutMSM72xx::setParameters() %s", keyValuePairs.string());
16012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
16022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (param.getInt(key, device) == NO_ERROR) {
16032aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mDevices = device;
16042aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGV("set output routing %x", mDevices);
160511c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent        status = mHardware->doRouting();
16062aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        param.remove(key);
16072aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
16082aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
16092aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (param.size()) {
16102aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        status = BAD_VALUE;
16112aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
16122aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return status;
16132aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
16142aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
16152aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandString8 AudioHardware::AudioStreamOutMSM72xx::getParameters(const String8& keys)
16162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
16172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    AudioParameter param = AudioParameter(keys);
16182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    String8 value;
16192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    String8 key = String8(AudioParameter::keyRouting);
16202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
16212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (param.get(key, value) == NO_ERROR) {
16222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGV("get routing %x", mDevices);
16232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        param.addInt(key, (int)mDevices);
16242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
16252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
16262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("AudioStreamOutMSM72xx::getParameters() %s", param.toString().string());
16272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return param.toString();
16282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
16292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
16303b9744cccd99fd9f32ae3b99fbc8d6898b118a43Eric Laurentstatus_t AudioHardware::AudioStreamOutMSM72xx::getRenderPosition(uint32_t *dspFrames)
16313b9744cccd99fd9f32ae3b99fbc8d6898b118a43Eric Laurent{
16323b9744cccd99fd9f32ae3b99fbc8d6898b118a43Eric Laurent    //TODO: enable when supported by driver
16333b9744cccd99fd9f32ae3b99fbc8d6898b118a43Eric Laurent    return INVALID_OPERATION;
16343b9744cccd99fd9f32ae3b99fbc8d6898b118a43Eric Laurent}
16352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
16362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland// ----------------------------------------------------------------------------
16372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
16382aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandAudioHardware::AudioStreamInMSM72xx::AudioStreamInMSM72xx() :
16392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mHardware(0), mFd(-1), mState(AUDIO_INPUT_CLOSED), mRetryCount(0),
16402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mFormat(AUDIO_HW_IN_FORMAT), mChannels(AUDIO_HW_IN_CHANNELS),
1641a4fe0167c6cad83d88b3bc56efa1ffad85b345b5Eric Laurent    mSampleRate(AUDIO_HW_IN_SAMPLERATE), mBufferSize(AUDIO_KERNEL_PCM_IN_BUFFERSIZE),
16422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mAcoustics((AudioSystem::audio_in_acoustics)0), mDevices(0)
16432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
16442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
16452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
16462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::AudioStreamInMSM72xx::set(
16472aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        AudioHardware* hw, uint32_t devices, int *pFormat, uint32_t *pChannels, uint32_t *pRate,
16482aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        AudioSystem::audio_in_acoustics acoustic_flags)
16492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
16502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (pFormat == 0 || *pFormat != AUDIO_HW_IN_FORMAT) {
16512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        *pFormat = AUDIO_HW_IN_FORMAT;
16522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return BAD_VALUE;
16532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
16542aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (pRate == 0) {
16552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return BAD_VALUE;
16562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
16572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    uint32_t rate = hw->getInputSampleRate(*pRate);
16582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (rate != *pRate) {
16592aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        *pRate = rate;
16602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return BAD_VALUE;
16612aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
16622aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
16632aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (pChannels == 0 || (*pChannels != AudioSystem::CHANNEL_IN_MONO &&
16642aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        *pChannels != AudioSystem::CHANNEL_IN_STEREO)) {
16652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        *pChannels = AUDIO_HW_IN_CHANNELS;
16662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return BAD_VALUE;
16672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
16682aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
16692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mHardware = hw;
16702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
16712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("AudioStreamInMSM72xx::set(%d, %d, %u)", *pFormat, *pChannels, *pRate);
16722aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mFd >= 0) {
16732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGE("Audio record already open");
16742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return -EPERM;
16752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
16762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
16772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // open audio input device
16782aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    status_t status = ::open("/dev/msm_pcm_in", O_RDWR);
16792aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (status < 0) {
16802aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGE("Cannot open /dev/msm_pcm_in errno: %d", errno);
16812aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        goto Error;
16822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
16832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mFd = status;
16842aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
16852aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // configuration
16862aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("get config");
16872aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    struct msm_audio_config config;
16882aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    status = ioctl(mFd, AUDIO_GET_CONFIG, &config);
16892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (status < 0) {
16902aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGE("Cannot read config");
16912aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        goto Error;
16922aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
16932aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
16942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("set config");
16952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    config.channel_count = AudioSystem::popCount(*pChannels);
16962aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    config.sample_rate = *pRate;
16972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    config.buffer_size = bufferSize();
16982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    config.buffer_count = 2;
16992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    config.codec_type = CODEC_TYPE_PCM;
17002aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    status = ioctl(mFd, AUDIO_SET_CONFIG, &config);
17012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (status < 0) {
17022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGE("Cannot set config");
17032aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (ioctl(mFd, AUDIO_GET_CONFIG, &config) == 0) {
17042aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            if (config.channel_count == 1) {
17052aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                *pChannels = AudioSystem::CHANNEL_IN_MONO;
17062aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            } else {
17072aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                *pChannels = AudioSystem::CHANNEL_IN_STEREO;
17082aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            }
17092aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            *pRate = config.sample_rate;
17102aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
17112aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        goto Error;
17122aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
17132aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
17142aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("confirm config");
17152aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    status = ioctl(mFd, AUDIO_GET_CONFIG, &config);
17162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (status < 0) {
17172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGE("Cannot read config");
17182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        goto Error;
17192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
17202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("buffer_size: %u", config.buffer_size);
17212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("buffer_count: %u", config.buffer_count);
17222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("channel_count: %u", config.channel_count);
17232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("sample_rate: %u", config.sample_rate);
17242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
17252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mDevices = devices;
17262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mFormat = AUDIO_HW_IN_FORMAT;
17272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mChannels = *pChannels;
17282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mSampleRate = config.sample_rate;
17292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mBufferSize = config.buffer_size;
17302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
17312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    //mHardware->setMicMute_nosync(false);
17322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mState = AUDIO_INPUT_OPENED;
17332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
17342aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
17352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
17362aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandError:
17372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mFd >= 0) {
17382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        ::close(mFd);
17392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mFd = -1;
17402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
17412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return status;
17422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
17432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
17442aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandAudioHardware::AudioStreamInMSM72xx::~AudioStreamInMSM72xx()
17452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
17462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("AudioStreamInMSM72xx destructor");
17472aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    standby();
17482aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
17492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
17502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandssize_t AudioHardware::AudioStreamInMSM72xx::read( void* buffer, ssize_t bytes)
17512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
17522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("AudioStreamInMSM72xx::read(%p, %ld)", buffer, bytes);
17532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (!mHardware) return -1;
17542aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
17552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    size_t count = bytes;
17562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    uint8_t* p = static_cast<uint8_t*>(buffer);
17572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
17582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mState < AUDIO_INPUT_OPENED) {
17592aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        Mutex::Autolock lock(mHardware->mLock);
17602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (set(mHardware, mDevices, &mFormat, &mChannels, &mSampleRate, mAcoustics) != NO_ERROR) {
17612aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            return -1;
17622aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
17632aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
17642aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
17650f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    if (mState < AUDIO_INPUT_STARTED) {
176611c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent        mState = AUDIO_INPUT_STARTED;
17672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mHardware->set_mRecordState(1);
176811c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent        // make sure a1026 config is re-applied even is input device is not changed
176911c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent        mHardware->clearCurDevice();
177011c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent        mHardware->doRouting();
177111c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent
17727fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi        uint32_t acdb_id = mHardware->getACDB(MOD_REC, mHardware->get_snd_dev());
17737fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi        if (ioctl(mFd, AUDIO_START, &acdb_id)) {
17742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            LOGE("Error starting record");
177511c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent            standby();
17762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            return -1;
17772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
17782aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
17792aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
17802aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    while (count) {
17812aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        ssize_t bytesRead = ::read(mFd, buffer, count);
17822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (bytesRead >= 0) {
17832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            count -= bytesRead;
17842aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            p += bytesRead;
17852aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        } else {
17862aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            if (errno != EAGAIN) return bytesRead;
17872aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            mRetryCount++;
17882aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            LOGW("EAGAIN - retrying");
17892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
17902aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
17912aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return bytes;
17922aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
17932aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
17942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::AudioStreamInMSM72xx::standby()
17952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
17962aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mState > AUDIO_INPUT_CLOSED) {
17972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (mFd >= 0) {
17982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            ::close(mFd);
17992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            mFd = -1;
18002aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
18012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mState = AUDIO_INPUT_CLOSED;
18022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
180311c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent
180411c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent    if (!mHardware) return -1;
180511c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent
180611c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent    mHardware->set_mRecordState(0);
180711c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent    // make sure a1026 config is re-applied even is input device is not changed
180811c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent    mHardware->clearCurDevice();
180911c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent    mHardware->doRouting();
181011c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent
18112aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGI("AudioHardware PCM record is going to standby.");
18122aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
18132aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
18142aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
18152aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::AudioStreamInMSM72xx::dump(int fd, const Vector<String16>& args)
18162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
18172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    const size_t SIZE = 256;
18182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    char buffer[SIZE];
18192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    String8 result;
18202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append("AudioStreamInMSM72xx::dump\n");
18212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tsample rate: %d\n", sampleRate());
18222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
18232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize());
18242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
18252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tchannels: %d\n", channels());
18262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
18272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tformat: %d\n", format());
18282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
18292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmHardware: %p\n", mHardware);
18302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
18312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmFd count: %d\n", mFd);
18322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
18332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmState: %d\n", mState);
18342aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
18352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmRetryCount: %d\n", mRetryCount);
18362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
18372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    ::write(fd, result.string(), result.size());
18382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
18392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
18402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
18412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::AudioStreamInMSM72xx::setParameters(const String8& keyValuePairs)
18422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
18432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    AudioParameter param = AudioParameter(keyValuePairs);
18442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    status_t status = NO_ERROR;
18452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    int device;
1846255bdedb2d7ebf4b14690776ff652df1de97fe95Eric Laurent    String8 key = String8(KEY_A1026_VR_MODE);
1847739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    int enabled;
18482aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("AudioStreamInMSM72xx::setParameters() %s", keyValuePairs.string());
18492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
1850739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    // reading voice recognition mode parameter
1851255bdedb2d7ebf4b14690776ff652df1de97fe95Eric Laurent    if (param.getInt(key, enabled) == NO_ERROR) {
185208516fe50b023532d5a3010050970de28e14621bIliyan Malchev        LOGV("set vr_mode_enabled to %d", enabled);
185308516fe50b023532d5a3010050970de28e14621bIliyan Malchev        vr_mode_change = (vr_mode_enabled != enabled);
18549ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi        vr_mode_enabled = enabled;
1855739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        param.remove(key);
1856739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    }
1857739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi
1858739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    // reading routing parameter
1859255bdedb2d7ebf4b14690776ff652df1de97fe95Eric Laurent    key = String8(AudioParameter::keyRouting);
18602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (param.getInt(key, device) == NO_ERROR) {
18612aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGV("set input routing %x", device);
18622aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (device & (device - 1)) {
18632aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            status = BAD_VALUE;
18642aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        } else {
18652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            mDevices = device;
186611c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent            status = mHardware->doRouting();
18672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
18682aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        param.remove(key);
18692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
18702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
18712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (param.size()) {
18722aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        status = BAD_VALUE;
18732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
18742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return status;
18752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
18762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
18772aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandString8 AudioHardware::AudioStreamInMSM72xx::getParameters(const String8& keys)
18782aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
18792aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    AudioParameter param = AudioParameter(keys);
18802aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    String8 value;
18812aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    String8 key = String8(AudioParameter::keyRouting);
18822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
18832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (param.get(key, value) == NO_ERROR) {
18842aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGV("get routing %x", mDevices);
18852aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        param.addInt(key, (int)mDevices);
18862aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
18872aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
18882aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("AudioStreamInMSM72xx::getParameters() %s", param.toString().string());
18892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return param.toString();
18902aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
18912aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
18922aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland// ----------------------------------------------------------------------------
18932aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
18942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandextern "C" AudioHardwareInterface* createAudioHardware(void) {
18952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return new AudioHardware();
18962aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
18972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
18982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}; // namespace android
1899