12aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland/*
28dd179b07f00e35208dd4cf48e14264717e8d5a0Jean-Baptiste Queru** Copyright 2008, The Android Open-Source Project
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
19e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent//#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>
391119793f2bc460d6417fedb54c7a51c48ded56deJean-Michel Trivi#include <media/mediarecorder.h>
402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandextern "C" {
422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#include "msm_audio.h"
439ab0b5b1f3244f261fcda2ead8fcdd5fe5d714b6Iliyan Malchev#include <linux/a1026.h>
44f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev#include <linux/tpa2018d1.h>
452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
472aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#define LOG_SND_RPC 0  // Set to 1 to log sound RPC's
482aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#define TX_PATH (1)
492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_CURRENT = 256;
512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_HANDSET = 0;
522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_SPEAKER = 1;
532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_BT = 3;
542aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_CARKIT = 4;
552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_BT_EC_OFF = 45;
562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_HEADSET = 2;
572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_HEADSET_AND_SPEAKER = 10;
582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_FM_HEADSET = 9;
592aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_FM_SPEAKER = 11;
602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_NO_MIC_HEADSET = 8;
612aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_TTY_FULL = 5;
6217b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurentstatic const uint32_t SND_DEVICE_TTY_VCO = 6;
6317b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurentstatic const uint32_t SND_DEVICE_TTY_HCO = 7;
64da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurentstatic const uint32_t SND_DEVICE_HANDSET_BACK_MIC = 20;
65da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurentstatic const uint32_t SND_DEVICE_SPEAKER_BACK_MIC = 21;
66da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurentstatic const uint32_t SND_DEVICE_NO_MIC_HEADSET_BACK_MIC = 28;
6758cf88a5a91d82ae2fb3e23365eaa4524a9cd089Jean-Michel Trivistatic const uint32_t SND_DEVICE_HEADSET_AND_SPEAKER_BACK_MIC = 30;
682aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandnamespace android {
692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic int support_a1026 = 1;
70f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchevstatic bool support_tpa2018d1 = true;
712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic int fd_a1026 = -1;
722aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic int old_pathid = -1;
732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic int new_pathid = -1;
740f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurentstatic int curr_out_device = -1;
750f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurentstatic int curr_mic_device = -1;
762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic int voice_started = 0;
772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic int fd_fm_device = -1;
7810254cc35f5cb7ebe2c7ef452815486cb8e92a33Jean-Michel Trivistatic int stream_volume = -300;
79739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi// use VR mode on inputs: 1 == VR mode enabled when selected, 0 = VR mode disabled when selected
8008516fe50b023532d5a3010050970de28e14621bIliyan Malchevstatic int vr_mode_enabled;
81739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivistatic bool vr_mode_change = false;
82739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivistatic int vr_uses_ns = 0;
83f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchevstatic int alt_enable = 0;
84f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchevstatic int hac_enable = 0;
859ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi// enable or disable 2-mic noise suppression in call on receiver mode
86739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivistatic int enable1026 = 1;
879ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi//FIXME add new settings in A1026 driver for an incall no ns mode, based on the current vr no ns
889ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi#define A1026_PATH_INCALL_NO_NS_RECEIVER A1026_PATH_VR_NO_NS_RECEIVER
8910254cc35f5cb7ebe2c7ef452815486cb8e92a33Jean-Michel Trivi
902aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandint errCount = 0;
910f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurentstatic void * acoustic;
922aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandconst uint32_t AudioHardware::inputSamplingRates[] = {
932aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000
942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland};
955d89308f2e1252eff2743bf823bf558dbb0de2faDave Sparks
965d89308f2e1252eff2743bf823bf558dbb0de2faDave Sparks// ID string for audio wakelock
972176dbc34c87e6855a912920f6868f8d211d12b4Eric Laurentstatic const char kOutputWakelockStr[] = "AudioHardwareQSDOut";
982176dbc34c87e6855a912920f6868f8d211d12b4Eric Laurentstatic const char kInputWakelockStr[] = "AudioHardwareQSDIn";
995d89308f2e1252eff2743bf823bf558dbb0de2faDave Sparks
1002aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland// ----------------------------------------------------------------------------
1012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
1022aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandAudioHardware::AudioHardware() :
1030f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    mA1026Init(false), mInit(false), mMicMute(true),
104f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    mBluetoothNrec(true),
105f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    mHACSetting(false),
106f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    mBluetoothIdTx(0), mBluetoothIdRx(0),
107f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    mOutput(0),
1083964d4ed448b00791bc1b574913be24f44b45f0fEric Laurent    mNoiseSuppressionState(A1026_NS_STATE_AUTO),
10917b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent    mVoiceVolume(VOICE_VOLUME_MAX), mTTYMode(TTY_MODE_OFF)
1102aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
1110f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    int (*snd_get_num)();
1120f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    int (*snd_get_bt_endpoint)(msm_bt_endpoint *);
1130f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    int (*set_acoustic_parameters)();
114f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    int (*set_tpa2018d1_parameters)();
1150f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent
1160f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    struct msm_bt_endpoint *ept;
1170f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent
1182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    doA1026_init();
1190f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent
1200f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    acoustic =:: dlopen("/system/lib/libhtc_acoustic.so", RTLD_NOW);
1210f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    if (acoustic == NULL ) {
122f9452ed4a7c7bbde537f3f2690fc124e5a1beaffSteve Block        ALOGD("Could not open libhtc_acoustic.so");
1230f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        /* this is not really an error on non-htc devices... */
1240f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        mNumBTEndpoints = 0;
1250f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        mInit = true;
1260f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        return;
1270f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    }
1280f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    set_acoustic_parameters = (int (*)(void))::dlsym(acoustic, "set_acoustic_parameters");
1290f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    if ((*set_acoustic_parameters) == 0 ) {
130c3dee7890047bad1136078f0f6e2b6d1a9a24947Steve Block        ALOGE("Could not open set_acoustic_parameters()");
1310f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        return;
1320f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    }
1330f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent
134f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    set_tpa2018d1_parameters = (int (*)(void))::dlsym(acoustic, "set_tpa2018d1_parameters");
135f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    if ((*set_tpa2018d1_parameters) == 0) {
136f9452ed4a7c7bbde537f3f2690fc124e5a1beaffSteve Block        ALOGD("set_tpa2018d1_parameters() not present");
137f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        support_tpa2018d1 = false;
138f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    }
139f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev
1400f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    int rc = set_acoustic_parameters();
1410f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    if (rc < 0) {
142f9452ed4a7c7bbde537f3f2690fc124e5a1beaffSteve Block        ALOGD("Could not set acoustic parameters to share memory: %d", rc);
1430f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    }
1440f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent
145f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    if (support_tpa2018d1) {
146f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev       rc = set_tpa2018d1_parameters();
147f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev       if (rc < 0) {
148f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev           support_tpa2018d1 = false;
149f9452ed4a7c7bbde537f3f2690fc124e5a1beaffSteve Block           ALOGD("speaker amplifier tpa2018 is not supported\n");
150f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev       }
151f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    }
152f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev
1530f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    snd_get_num = (int (*)(void))::dlsym(acoustic, "snd_get_num");
1540f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    if ((*snd_get_num) == 0 ) {
155f9452ed4a7c7bbde537f3f2690fc124e5a1beaffSteve Block        ALOGD("Could not open snd_get_num()");
1560f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    }
1570f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent
1580f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    mNumBTEndpoints = snd_get_num();
15922f2554680715d1ea993409217a4a21f652ef130Steve Block    ALOGV("mNumBTEndpoints = %d", mNumBTEndpoints);
1600f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    mBTEndpoints = new msm_bt_endpoint[mNumBTEndpoints];
1610f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    mInit = true;
16222f2554680715d1ea993409217a4a21f652ef130Steve Block    ALOGV("constructed %d SND endpoints)", mNumBTEndpoints);
1630f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    ept = mBTEndpoints;
1640f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    snd_get_bt_endpoint = (int (*)(msm_bt_endpoint *))::dlsym(acoustic, "snd_get_bt_endpoint");
1650f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    if ((*snd_get_bt_endpoint) == 0 ) {
166c3dee7890047bad1136078f0f6e2b6d1a9a24947Steve Block        ALOGE("Could not open snd_get_bt_endpoint()");
1670f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        return;
1680f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    }
1690f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    snd_get_bt_endpoint(mBTEndpoints);
1700f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent
1710f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    for (int i = 0; i < mNumBTEndpoints; i++) {
17222f2554680715d1ea993409217a4a21f652ef130Steve Block        ALOGV("BT name %s (tx,rx)=(%d,%d)", mBTEndpoints[i].name, mBTEndpoints[i].tx, mBTEndpoints[i].rx);
1730f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    }
1740f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent
175d1dc8c30a969ec3539fc21b940789b2f23197756Eric Laurent    // reset voice mode in case media_server crashed and restarted while in call
176d1dc8c30a969ec3539fc21b940789b2f23197756Eric Laurent    int fd = open("/dev/msm_audio_ctl", O_RDWR);
177d1dc8c30a969ec3539fc21b940789b2f23197756Eric Laurent    if (fd >= 0) {
178d1dc8c30a969ec3539fc21b940789b2f23197756Eric Laurent        ioctl(fd, AUDIO_STOP_VOICE, NULL);
179d1dc8c30a969ec3539fc21b940789b2f23197756Eric Laurent        close(fd);
180d1dc8c30a969ec3539fc21b940789b2f23197756Eric Laurent    }
181d1dc8c30a969ec3539fc21b940789b2f23197756Eric Laurent
182739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    vr_mode_change = false;
18308516fe50b023532d5a3010050970de28e14621bIliyan Malchev    vr_mode_enabled = 0;
184739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    enable1026 = 1;
185739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    char value[PROPERTY_VALUE_MAX];
186739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    // Check the system property to enable or not the special recording modes
187739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    property_get("media.a1026.enableA1026", value, "1");
188739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    enable1026 = atoi(value);
18922f2554680715d1ea993409217a4a21f652ef130Steve Block    ALOGV("Enable mode selection for A1026 is %d", enable1026);
190739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    // Check the system property for which VR mode to use
191739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    property_get("media.a1026.nsForVoiceRec", value, "0");
192739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    vr_uses_ns = atoi(value);
19322f2554680715d1ea993409217a4a21f652ef130Steve Block    ALOGV("Using Noise Suppression for Voice Rec is %d", vr_uses_ns);
194739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi
195f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    // Check the system property for enable or not the ALT function
196f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    property_get("htc.audio.alt.enable", value, "0");
197f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    alt_enable = atoi(value);
19822f2554680715d1ea993409217a4a21f652ef130Steve Block    ALOGV("Enable ALT function: %d", alt_enable);
199f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev
200f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    // Check the system property for enable or not the HAC function
201f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    property_get("htc.audio.hac.enable", value, "0");
202f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    hac_enable = atoi(value);
20322f2554680715d1ea993409217a4a21f652ef130Steve Block    ALOGV("Enable HAC function: %d", hac_enable);
204f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev
2052aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mInit = true;
2062aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
2072aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2082aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandAudioHardware::~AudioHardware()
2092aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
2102aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    for (size_t index = 0; index < mInputs.size(); index++) {
2112aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        closeInputStream((AudioStreamIn*)mInputs[index]);
2122aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
2132aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mInputs.clear();
2142aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    closeOutputStream((AudioStreamOut*)mOutput);
2152aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mInit = false;
2162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
2172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::initCheck()
2192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
2202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return mInit ? NO_ERROR : NO_INIT;
2212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
2222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2232aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandAudioStreamOut* AudioHardware::openOutputStream(
2242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status)
2252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
2262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    { // scope for the lock
2272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        Mutex::Autolock lock(mLock);
2282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        // only one output stream allowed
2302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (mOutput) {
2312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            if (status) {
2322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                *status = INVALID_OPERATION;
2332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            }
2342aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            return 0;
2352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
2362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        // create new output stream
2382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        AudioStreamOutMSM72xx* out = new AudioStreamOutMSM72xx();
2392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        status_t lStatus = out->set(this, devices, format, channels, sampleRate);
2402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (status) {
2412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            *status = lStatus;
2422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
2432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (lStatus == NO_ERROR) {
2442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            mOutput = out;
2452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        } else {
2462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            delete out;
2472aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
2482aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
2492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return mOutput;
2502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
2512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandvoid AudioHardware::closeOutputStream(AudioStreamOut* out) {
2532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    Mutex::Autolock lock(mLock);
2542aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mOutput == 0 || mOutput != out) {
2553fb19cd0b6534ef9d36f8ac0c5ddbdc73ed92a26Steve Block        ALOGW("Attempt to close invalid output stream");
2562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
2572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    else {
2582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        delete mOutput;
2592aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mOutput = 0;
2602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
2612aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
2622aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2632aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandAudioStreamIn* AudioHardware::openInputStream(
2642aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status,
2652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        AudioSystem::audio_in_acoustics acoustic_flags)
2662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
2672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // check for valid input source
2682aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (!AudioSystem::isInputDevice((AudioSystem::audio_devices)devices)) {
2692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return 0;
2702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
2712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2722aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mLock.lock();
2732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    AudioStreamInMSM72xx* in = new AudioStreamInMSM72xx();
2752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    status_t lStatus = in->set(this, devices, format, channels, sampleRate, acoustic_flags);
2762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (status) {
2772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        *status = lStatus;
2782aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
2792aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (lStatus != NO_ERROR) {
2802aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mLock.unlock();
2812aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        delete in;
2822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return 0;
2832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
2842aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2852aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mInputs.add(in);
2862aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mLock.unlock();
2872aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2882aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return in;
2892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
2902aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2912aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandvoid AudioHardware::closeInputStream(AudioStreamIn* in) {
2922aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    Mutex::Autolock lock(mLock);
2932aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    ssize_t index = mInputs.indexOf((AudioStreamInMSM72xx *)in);
2952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (index < 0) {
2963fb19cd0b6534ef9d36f8ac0c5ddbdc73ed92a26Steve Block        ALOGW("Attempt to close invalid input stream");
2972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else {
2982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mLock.unlock();
2992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        delete mInputs[index];
3002aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mLock.lock();
3012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mInputs.removeAt(index);
3022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
3032aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
3042aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
3052aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::setMode(int mode)
3062aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
307739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    // VR mode is never used in a call and must be cleared when entering the IN_CALL mode
308739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    if (mode == AudioSystem::MODE_IN_CALL) {
30908516fe50b023532d5a3010050970de28e14621bIliyan Malchev        vr_mode_enabled = 0;
310739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    }
311739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi
312f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    if (support_tpa2018d1)
313f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        do_tpa2018_control(mode);
314f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev
3158dc5375b4d5131e3b1f77874e87fff4cf18f2e4fEric Laurent    int prevMode = mMode;
3162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    status_t status = AudioHardwareBase::setMode(mode);
3172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (status == NO_ERROR) {
3182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        // make sure that doAudioRouteOrMute() is called by doRouting()
3198dc5375b4d5131e3b1f77874e87fff4cf18f2e4fEric Laurent        // when entering or exiting in call mode even if the new device
3208dc5375b4d5131e3b1f77874e87fff4cf18f2e4fEric Laurent        // selected is the same as current one.
3218dc5375b4d5131e3b1f77874e87fff4cf18f2e4fEric Laurent        if (((prevMode != AudioSystem::MODE_IN_CALL) && (mMode == AudioSystem::MODE_IN_CALL)) ||
3228dc5375b4d5131e3b1f77874e87fff4cf18f2e4fEric Laurent            ((prevMode == AudioSystem::MODE_IN_CALL) && (mMode != AudioSystem::MODE_IN_CALL))) {
3238dc5375b4d5131e3b1f77874e87fff4cf18f2e4fEric Laurent            clearCurDevice();
3248dc5375b4d5131e3b1f77874e87fff4cf18f2e4fEric Laurent        }
3252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
3268dc5375b4d5131e3b1f77874e87fff4cf18f2e4fEric Laurent
3272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return status;
3282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
3292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
3302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandbool AudioHardware::checkOutputStandby()
3312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
3322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mOutput)
3332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (!mOutput->checkStandby())
3342aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            return false;
3352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
3362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return true;
3372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
3383cb8864598e72c04859f410bb03f242cf3965dbeHK Chenstatic status_t set_mic_mute(bool _mute)
3392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
3403cb8864598e72c04859f410bb03f242cf3965dbeHK Chen    uint32_t mute = _mute;
3413cb8864598e72c04859f410bb03f242cf3965dbeHK Chen    int fd = -1;
3422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    fd = open("/dev/msm_audio_ctl", O_RDWR);
3432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (fd < 0) {
344c3dee7890047bad1136078f0f6e2b6d1a9a24947Steve Block        ALOGE("Cannot open msm_audio_ctl device\n");
3452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return -1;
3462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
347f9452ed4a7c7bbde537f3f2690fc124e5a1beaffSteve Block    ALOGD("Setting mic mute to %d\n", mute);
3483cb8864598e72c04859f410bb03f242cf3965dbeHK Chen    if (ioctl(fd, AUDIO_SET_MUTE, &mute)) {
349c3dee7890047bad1136078f0f6e2b6d1a9a24947Steve Block        ALOGE("Cannot set mic mute on current device\n");
3502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        close(fd);
3512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return -1;
3522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
3532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    close(fd);
3542aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
3552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
3562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
3572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::setMicMute(bool state)
3582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
3592aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    Mutex::Autolock lock(mLock);
3602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return setMicMute_nosync(state);
3612aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
3622aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
3632aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland// always call with mutex held
3642aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::setMicMute_nosync(bool state)
3652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
3662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mMicMute != state) {
3672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mMicMute = state;
3682aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return set_mic_mute(mMicMute); //always set current TX device
3692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
3702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
3712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
3722aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
3732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::getMicMute(bool* state)
3742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
3752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    *state = mMicMute;
3762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
3772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
3782aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
3792aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::setParameters(const String8& keyValuePairs)
3802aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
3812aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    AudioParameter param = AudioParameter(keyValuePairs);
3822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    String8 value;
3832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    String8 key;
3842aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    const char BT_NREC_KEY[] = "bt_headset_nrec";
3852aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    const char BT_NAME_KEY[] = "bt_headset_name";
386f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    const char HAC_KEY[] = "HACSetting";
3872aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    const char BT_NREC_VALUE_ON[] = "on";
388f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    const char HAC_VALUE_ON[] = "ON";
3892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
3902aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
39122f2554680715d1ea993409217a4a21f652ef130Steve Block    ALOGV("setParameters() %s", keyValuePairs.string());
3922aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
3932aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (keyValuePairs.length() == 0) return BAD_VALUE;
3942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
395f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    if(hac_enable) {
396f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        key = String8(HAC_KEY);
397f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        if (param.get(key, value) == NO_ERROR) {
398f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            if (value == HAC_VALUE_ON) {
399f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev                mHACSetting = true;
400f9452ed4a7c7bbde537f3f2690fc124e5a1beaffSteve Block                ALOGD("Enable HAC");
401f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            } else {
402f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev                mHACSetting = false;
403f9452ed4a7c7bbde537f3f2690fc124e5a1beaffSteve Block                ALOGD("Disable HAC");
404f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            }
405f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        }
406f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    }
407f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev
4082aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    key = String8(BT_NREC_KEY);
4092aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (param.get(key, value) == NO_ERROR) {
4102aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (value == BT_NREC_VALUE_ON) {
4112aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            mBluetoothNrec = true;
4122aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        } else {
4132aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            mBluetoothNrec = false;
414f9452ed4a7c7bbde537f3f2690fc124e5a1beaffSteve Block            ALOGD("Turning noise reduction and echo cancellation off for BT "
4152aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                 "headset");
4162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
4172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
4182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    key = String8(BT_NAME_KEY);
4192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (param.get(key, value) == NO_ERROR) {
4200f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        mBluetoothIdTx = 0;
4210f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        mBluetoothIdRx = 0;
4220f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        for (int i = 0; i < mNumBTEndpoints; i++) {
4230f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            if (!strcasecmp(value.string(), mBTEndpoints[i].name)) {
4240f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                mBluetoothIdTx = mBTEndpoints[i].tx;
4250f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                mBluetoothIdRx = mBTEndpoints[i].rx;
426f9452ed4a7c7bbde537f3f2690fc124e5a1beaffSteve Block                ALOGD("Using custom acoustic parameters for %s", value.string());
4272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                break;
4282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            }
4292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
4300f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        if (mBluetoothIdTx == 0) {
431f9452ed4a7c7bbde537f3f2690fc124e5a1beaffSteve Block            ALOGD("Using default acoustic parameters "
4322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                 "(%s not in acoustic database)", value.string());
4332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
43411c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent        doRouting();
4352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
436da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    key = String8("noise_suppression");
437da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    if (param.get(key, value) == NO_ERROR) {
438da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent        if (support_a1026 == 1) {
439da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            int noiseSuppressionState;
440da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            if (value == "off") {
441da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                noiseSuppressionState = A1026_NS_STATE_OFF;
442da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            } else if (value == "auto") {
443da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                noiseSuppressionState = A1026_NS_STATE_AUTO;
444da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            } else if (value == "far_talk") {
445da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                noiseSuppressionState = A1026_NS_STATE_FT;
446da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            } else if (value == "close_talk") {
447da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                noiseSuppressionState = A1026_NS_STATE_CT;
448da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            } else {
449da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                return BAD_VALUE;
450da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            }
451da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent
452da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            if (noiseSuppressionState != mNoiseSuppressionState) {
453da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                if (!mA1026Init) {
4543fb19cd0b6534ef9d36f8ac0c5ddbdc73ed92a26Steve Block                    ALOGW("Audience A1026 not initialized.\n");
455da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                    return INVALID_OPERATION;
456da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                }
457da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent
45811c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent                mA1026Lock.lock();
459da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                if (fd_a1026 < 0) {
460da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                    fd_a1026 = open("/dev/audience_a1026", O_RDWR);
461da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                    if (fd_a1026 < 0) {
462c3dee7890047bad1136078f0f6e2b6d1a9a24947Steve Block                        ALOGE("Cannot open audience_a1026 device (%d)\n", fd_a1026);
46311c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent                        mA1026Lock.unlock();
464da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                        return -1;
465da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                    }
466da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                }
46722f2554680715d1ea993409217a4a21f652ef130Steve Block                ALOGV("Setting noise suppression %s", value.string());
46811c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent
469da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                int rc = ioctl(fd_a1026, A1026_SET_NS_STATE, &noiseSuppressionState);
470da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                if (!rc) {
471da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                    mNoiseSuppressionState = noiseSuppressionState;
472da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                } else {
473c3dee7890047bad1136078f0f6e2b6d1a9a24947Steve Block                    ALOGE("Failed to set noise suppression %s", value.string());
474da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                }
47511c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent                close(fd_a1026);
476d666d60c2b157bee1aaf2233c253778929bd7d49Jean-Michel Trivi                fd_a1026 = -1;
477da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent                mA1026Lock.unlock();
478da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            }
479da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent        } else {
480da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            return INVALID_OPERATION;
481da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent        }
482da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent     }
483da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent
48417b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent    key = String8("tty_mode");
48517b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent    if (param.get(key, value) == NO_ERROR) {
48617b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent        int ttyMode;
48717b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent        if (value == "tty_off") {
48817b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent            ttyMode = TTY_MODE_OFF;
48917b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent        } else if (value == "tty_full") {
49017b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent            ttyMode = TTY_MODE_FULL;
49117b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent        } else if (value == "tty_vco") {
49217b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent            ttyMode = TTY_MODE_VCO;
49317b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent        } else if (value == "tty_hco") {
49417b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent            ttyMode = TTY_MODE_HCO;
49517b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent        } else {
49617b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent            return BAD_VALUE;
49717b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent        }
49817b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent
49917b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent        if (ttyMode != mTTYMode) {
50022f2554680715d1ea993409217a4a21f652ef130Steve Block            ALOGV("new tty mode %d", ttyMode);
50117b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent            mTTYMode = ttyMode;
502c08cbb26e57c8c3521391947e676cbdb6e81603bEric Laurent            doRouting();
50317b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent        }
50417b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent     }
50517b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent
5062aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
5072aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
5082aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
5092aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandString8 AudioHardware::getParameters(const String8& keys)
5102aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
511da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    AudioParameter request = AudioParameter(keys);
512da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    AudioParameter reply = AudioParameter();
513da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    String8 value;
514da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    String8 key;
515da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent
51622f2554680715d1ea993409217a4a21f652ef130Steve Block    ALOGV("getParameters() %s", keys.string());
517da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent
518da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    key = "noise_suppression";
519da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    if (request.get(key, value) == NO_ERROR) {
520da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent        switch(mNoiseSuppressionState) {
521da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent        case A1026_NS_STATE_OFF:
522da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            value = "off";
523da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            break;
524da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent        case A1026_NS_STATE_AUTO:
525da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            value = "auto";
526da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            break;
527da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent        case A1026_NS_STATE_FT:
528da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            value = "far_talk";
529da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            break;
530da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent        case A1026_NS_STATE_CT:
531da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            value = "close_talk";
532da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            break;
533da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent        }
534da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent        reply.add(key, value);
535da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    }
536da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent
537da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    return reply.toString();
5382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
5392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
5402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
5412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic unsigned calculate_audpre_table_index(unsigned index)
5422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
5432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    switch (index) {
5442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        case 48000:    return SAMP_RATE_INDX_48000;
5452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        case 44100:    return SAMP_RATE_INDX_44100;
5462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        case 32000:    return SAMP_RATE_INDX_32000;
5472aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        case 24000:    return SAMP_RATE_INDX_24000;
5482aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        case 22050:    return SAMP_RATE_INDX_22050;
5492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        case 16000:    return SAMP_RATE_INDX_16000;
5502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        case 12000:    return SAMP_RATE_INDX_12000;
5512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        case 11025:    return SAMP_RATE_INDX_11025;
5522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        case 8000:    return SAMP_RATE_INDX_8000;
5532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        default:     return -1;
5542aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
5552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
556f2236a59c89b93062490d2c236ffebe57173af6eEric Laurent
557f2236a59c89b93062490d2c236ffebe57173af6eEric Laurentsize_t AudioHardware::getBufferSize(uint32_t sampleRate, int channelCount)
558f2236a59c89b93062490d2c236ffebe57173af6eEric Laurent{
559f2236a59c89b93062490d2c236ffebe57173af6eEric Laurent    size_t bufSize;
560f2236a59c89b93062490d2c236ffebe57173af6eEric Laurent
561f2236a59c89b93062490d2c236ffebe57173af6eEric Laurent    if (sampleRate < 11025) {
562f2236a59c89b93062490d2c236ffebe57173af6eEric Laurent        bufSize = 256;
563f2236a59c89b93062490d2c236ffebe57173af6eEric Laurent    } else if (sampleRate < 22050) {
564f2236a59c89b93062490d2c236ffebe57173af6eEric Laurent        bufSize = 512;
565f2236a59c89b93062490d2c236ffebe57173af6eEric Laurent    } else if (sampleRate < 32000) {
566f2236a59c89b93062490d2c236ffebe57173af6eEric Laurent        bufSize = 768;
567f2236a59c89b93062490d2c236ffebe57173af6eEric Laurent    } else if (sampleRate < 44100) {
568f2236a59c89b93062490d2c236ffebe57173af6eEric Laurent        bufSize = 1024;
569f2236a59c89b93062490d2c236ffebe57173af6eEric Laurent    } else {
570f2236a59c89b93062490d2c236ffebe57173af6eEric Laurent        bufSize = 1536;
571f2236a59c89b93062490d2c236ffebe57173af6eEric Laurent    }
572f2236a59c89b93062490d2c236ffebe57173af6eEric Laurent
573f2236a59c89b93062490d2c236ffebe57173af6eEric Laurent    return bufSize*channelCount;
574f2236a59c89b93062490d2c236ffebe57173af6eEric Laurent}
575f2236a59c89b93062490d2c236ffebe57173af6eEric Laurent
576f2236a59c89b93062490d2c236ffebe57173af6eEric Laurent
5772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandsize_t AudioHardware::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
5782aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
5792aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (format != AudioSystem::PCM_16_BIT) {
5803fb19cd0b6534ef9d36f8ac0c5ddbdc73ed92a26Steve Block        ALOGW("getInputBufferSize bad format: %d", format);
5812aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return 0;
5822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
5832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (channelCount < 1 || channelCount > 2) {
5843fb19cd0b6534ef9d36f8ac0c5ddbdc73ed92a26Steve Block        ALOGW("getInputBufferSize bad channel count: %d", channelCount);
5852aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return 0;
5862aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
587f2236a59c89b93062490d2c236ffebe57173af6eEric Laurent    if (sampleRate < 8000 || sampleRate > 48000) {
5883fb19cd0b6534ef9d36f8ac0c5ddbdc73ed92a26Steve Block        ALOGW("getInputBufferSize bad sample rate: %d", sampleRate);
589f2236a59c89b93062490d2c236ffebe57173af6eEric Laurent        return 0;
590f2236a59c89b93062490d2c236ffebe57173af6eEric Laurent    }
5912aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
592f2236a59c89b93062490d2c236ffebe57173af6eEric Laurent    return getBufferSize(sampleRate, channelCount);
5932aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
5942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
5952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic status_t set_volume_rpc(uint32_t volume)
5962aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
5972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    int fd = -1;
5982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    fd = open("/dev/msm_audio_ctl", O_RDWR);
5992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (fd < 0) {
600c3dee7890047bad1136078f0f6e2b6d1a9a24947Steve Block        ALOGE("Cannot open msm_audio_ctl device\n");
6012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return -1;
6022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
6032aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    volume *= 20; //percentage
604f9452ed4a7c7bbde537f3f2690fc124e5a1beaffSteve Block    ALOGD("Setting in-call volume to %d\n", volume);
6052aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (ioctl(fd, AUDIO_SET_VOLUME, &volume)) {
6063fb19cd0b6534ef9d36f8ac0c5ddbdc73ed92a26Steve Block        ALOGW("Cannot set volume on current device\n");
6072aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
6082aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    close(fd);
6092aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
6102aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
6112aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
6122aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::setVoiceVolume(float v)
6132aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
6142aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (v < 0.0) {
6153fb19cd0b6534ef9d36f8ac0c5ddbdc73ed92a26Steve Block        ALOGW("setVoiceVolume(%f) under 0.0, assuming 0.0", v);
6162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        v = 0.0;
6172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else if (v > 1.0) {
6183fb19cd0b6534ef9d36f8ac0c5ddbdc73ed92a26Steve Block        ALOGW("setVoiceVolume(%f) over 1.0, assuming 1.0", v);
6192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        v = 1.0;
6202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
6212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
6223964d4ed448b00791bc1b574913be24f44b45f0fEric Laurent    int vol = lrint(v * VOICE_VOLUME_MAX);
6232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
6242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    Mutex::Autolock lock(mLock);
625ec78ad65a1110fe007c3bdaba824f66bbfe522e3Eric Laurent    if (mHACSetting && hac_enable && mCurSndDevice == (int) SND_DEVICE_HANDSET) {
626f9452ed4a7c7bbde537f3f2690fc124e5a1beaffSteve Block        ALOGD("HAC enable: Setting in-call volume to maximum.\n");
627ec78ad65a1110fe007c3bdaba824f66bbfe522e3Eric Laurent        set_volume_rpc(VOICE_VOLUME_MAX);
628ec78ad65a1110fe007c3bdaba824f66bbfe522e3Eric Laurent    } else {
6295a182ec3e8b87b6538b4b492cb993239a677915fSteve Block        ALOGI("voice volume %d (range is 0 to %d)", vol, VOICE_VOLUME_MAX);
630ec78ad65a1110fe007c3bdaba824f66bbfe522e3Eric Laurent        set_volume_rpc(vol); //always set current device
631ec78ad65a1110fe007c3bdaba824f66bbfe522e3Eric Laurent    }
6323964d4ed448b00791bc1b574913be24f44b45f0fEric Laurent    mVoiceVolume = vol;
6332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
6342aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
6352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
6362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::setMasterVolume(float v)
6372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
6385a182ec3e8b87b6538b4b492cb993239a677915fSteve Block    ALOGI("Set master volume to %f", v);
6392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // We return an error code here to let the audioflinger do in-software
6402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // volume on top of the maximum volume that we set through the SND API.
6412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // return error - software mixer will handle it
6422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return -1;
6432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
6442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
6457fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivistatic status_t do_route_audio_dev_ctrl(uint32_t device, bool inCall, uint32_t rx_acdb_id, uint32_t tx_acdb_id)
6462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
6477fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    uint32_t out_device = 0, mic_device = 0;
6487fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    uint32_t path[2];
6492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    int fd = 0;
6502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
6512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (device == SND_DEVICE_CURRENT)
6522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        goto Incall;
6532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
6542aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // hack -- kernel needs to put these in include file
655f9452ed4a7c7bbde537f3f2690fc124e5a1beaffSteve Block    ALOGD("Switching audio device to ");
6562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (device == SND_DEVICE_HANDSET) {
6572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           out_device = HANDSET_SPKR;
6582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           mic_device = HANDSET_MIC;
659f9452ed4a7c7bbde537f3f2690fc124e5a1beaffSteve Block           ALOGD("Handset");
6602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else if ((device  == SND_DEVICE_BT) || (device == SND_DEVICE_BT_EC_OFF)) {
6612aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           out_device = BT_SCO_SPKR;
6622aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           mic_device = BT_SCO_MIC;
663f9452ed4a7c7bbde537f3f2690fc124e5a1beaffSteve Block           ALOGD("BT Headset");
664da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    } else if (device == SND_DEVICE_SPEAKER ||
665da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent               device == SND_DEVICE_SPEAKER_BACK_MIC) {
6662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           out_device = SPKR_PHONE_MONO;
6672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           mic_device = SPKR_PHONE_MIC;
668f9452ed4a7c7bbde537f3f2690fc124e5a1beaffSteve Block           ALOGD("Speakerphone");
6692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else if (device == SND_DEVICE_HEADSET) {
6702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           out_device = HEADSET_SPKR_STEREO;
6712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           mic_device = HEADSET_MIC;
672f9452ed4a7c7bbde537f3f2690fc124e5a1beaffSteve Block           ALOGD("Stereo Headset");
6732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else if (device == SND_DEVICE_HEADSET_AND_SPEAKER) {
6742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           out_device = SPKR_PHONE_HEADSET_STEREO;
6752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           mic_device = HEADSET_MIC;
676f9452ed4a7c7bbde537f3f2690fc124e5a1beaffSteve Block           ALOGD("Stereo Headset + Speaker");
67758cf88a5a91d82ae2fb3e23365eaa4524a9cd089Jean-Michel Trivi    } else if (device == SND_DEVICE_HEADSET_AND_SPEAKER_BACK_MIC) {
67858cf88a5a91d82ae2fb3e23365eaa4524a9cd089Jean-Michel Trivi           out_device = SPKR_PHONE_HEADSET_STEREO;
67958cf88a5a91d82ae2fb3e23365eaa4524a9cd089Jean-Michel Trivi           mic_device = SPKR_PHONE_MIC;
680f9452ed4a7c7bbde537f3f2690fc124e5a1beaffSteve Block           ALOGD("Stereo Headset + Speaker and back mic");
6812aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else if (device == SND_DEVICE_NO_MIC_HEADSET) {
6822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           out_device = HEADSET_SPKR_STEREO;
6832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           mic_device = HANDSET_MIC;
684f9452ed4a7c7bbde537f3f2690fc124e5a1beaffSteve Block           ALOGD("No microphone Wired Headset");
685da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    } else if (device == SND_DEVICE_NO_MIC_HEADSET_BACK_MIC) {
686da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent           out_device = HEADSET_SPKR_STEREO;
687da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent           mic_device = SPKR_PHONE_MIC;
688f9452ed4a7c7bbde537f3f2690fc124e5a1beaffSteve Block           ALOGD("No microphone Wired Headset and back mic");
689da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent    } else if (device == SND_DEVICE_HANDSET_BACK_MIC) {
690da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent           out_device = HANDSET_SPKR;
691da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent           mic_device = SPKR_PHONE_MIC;
692f9452ed4a7c7bbde537f3f2690fc124e5a1beaffSteve Block           ALOGD("Handset and back mic");
6932aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else if (device == SND_DEVICE_FM_HEADSET) {
6942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           out_device = FM_HEADSET;
6952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           mic_device = HEADSET_MIC;
696f9452ed4a7c7bbde537f3f2690fc124e5a1beaffSteve Block           ALOGD("Stereo FM headset");
6972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else if (device == SND_DEVICE_FM_SPEAKER) {
6982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           out_device = FM_SPKR;
6992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           mic_device = HEADSET_MIC;
700f9452ed4a7c7bbde537f3f2690fc124e5a1beaffSteve Block           ALOGD("Stereo FM speaker");
701c42d5b9bd789034e4e10679b24a7bd38e68f4556Eric Laurent    } else if (device == SND_DEVICE_CARKIT) {
702c42d5b9bd789034e4e10679b24a7bd38e68f4556Eric Laurent           out_device = BT_SCO_SPKR;
703c42d5b9bd789034e4e10679b24a7bd38e68f4556Eric Laurent           mic_device = BT_SCO_MIC;
704f9452ed4a7c7bbde537f3f2690fc124e5a1beaffSteve Block           ALOGD("Carkit");
70517b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent    } else if (device == SND_DEVICE_TTY_FULL) {
70617b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent        out_device = TTY_HEADSET_SPKR;
70717b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent        mic_device = TTY_HEADSET_MIC;
708f9452ed4a7c7bbde537f3f2690fc124e5a1beaffSteve Block        ALOGD("TTY FULL headset");
70917b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent    } else if (device == SND_DEVICE_TTY_VCO) {
71017b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent        out_device = TTY_HEADSET_SPKR;
711b26d493deaa9897cc6f34577aa5c9c1ff0655129Eric Laurent        mic_device = SPKR_PHONE_MIC;
712f9452ed4a7c7bbde537f3f2690fc124e5a1beaffSteve Block        ALOGD("TTY VCO headset");
71317b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent    } else if (device == SND_DEVICE_TTY_HCO) {
71417b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent        out_device = SPKR_PHONE_MONO;
71517b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent        mic_device = TTY_HEADSET_MIC;
716f9452ed4a7c7bbde537f3f2690fc124e5a1beaffSteve Block        ALOGD("TTY HCO headset");
7172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else {
718c3dee7890047bad1136078f0f6e2b6d1a9a24947Steve Block        ALOGE("unknown device %d", device);
71917b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent        return -1;
7202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
7212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
7222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#if 0 //Add for FM support
7232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (out_device == FM_HEADSET ||
7242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        out_device == FM_SPKR) {
7252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (fd_fm_device < 0) {
7262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            fd_fm_device = open("/dev/msm_htc_fm", O_RDWR);
7272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            if (fd_fm_device < 0) {
728c3dee7890047bad1136078f0f6e2b6d1a9a24947Steve Block                ALOGE("Cannot open msm_htc_fm device");
7292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                return -1;
7302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            }
731f9452ed4a7c7bbde537f3f2690fc124e5a1beaffSteve Block            ALOGD("Opened msm_htc_fm for FM radio");
7322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
7332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else if (fd_fm_device >= 0) {
7342aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        close(fd_fm_device);
7352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        fd_fm_device = -1;
736f9452ed4a7c7bbde537f3f2690fc124e5a1beaffSteve Block        ALOGD("Closed msm_htc_fm after FM radio");
7372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
7382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#endif
7392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
7402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    fd = open("/dev/msm_audio_ctl", O_RDWR);
7412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (fd < 0)        {
742c3dee7890047bad1136078f0f6e2b6d1a9a24947Steve Block       ALOGE("Cannot open msm_audio_ctl");
7432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland       return -1;
7442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
7457fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    path[0] = out_device;
7467fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    path[1] = rx_acdb_id;
7477fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    if (ioctl(fd, AUDIO_SWITCH_DEVICE, &path)) {
748c3dee7890047bad1136078f0f6e2b6d1a9a24947Steve Block       ALOGE("Cannot switch audio device");
7492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland       close(fd);
7502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland       return -1;
7512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
7527fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    path[0] = mic_device;
7537fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    path[1] = tx_acdb_id;
7547fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    if (ioctl(fd, AUDIO_SWITCH_DEVICE, &path)) {
755c3dee7890047bad1136078f0f6e2b6d1a9a24947Steve Block       ALOGE("Cannot switch mic device");
7562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland       close(fd);
7572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland       return -1;
7582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
7590f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    curr_out_device = out_device;
7600f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    curr_mic_device = mic_device;
7612aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
7622aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandIncall:
7632aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (inCall == true && !voice_started) {
764f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        if (fd < 0) {
7652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            fd = open("/dev/msm_audio_ctl", O_RDWR);
7662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
7672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            if (fd < 0) {
768c3dee7890047bad1136078f0f6e2b6d1a9a24947Steve Block                ALOGE("Cannot open msm_audio_ctl");
7692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                return -1;
7702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            }
7712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
7721e6baec54e051e7359aca7521d0919c6a6a91172Eric Laurent        path[0] = rx_acdb_id;
7731e6baec54e051e7359aca7521d0919c6a6a91172Eric Laurent        path[1] = tx_acdb_id;
7741e6baec54e051e7359aca7521d0919c6a6a91172Eric Laurent        if (ioctl(fd, AUDIO_START_VOICE, &path)) {
775c3dee7890047bad1136078f0f6e2b6d1a9a24947Steve Block            ALOGE("Cannot start voice");
7761e6baec54e051e7359aca7521d0919c6a6a91172Eric Laurent            close(fd);
7771e6baec54e051e7359aca7521d0919c6a6a91172Eric Laurent            return -1;
7782aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
779f9452ed4a7c7bbde537f3f2690fc124e5a1beaffSteve Block        ALOGD("Voice Started!!");
7802aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        voice_started = 1;
7812aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
7822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    else if (inCall == false && voice_started) {
7832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (fd < 0) {
7842aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            fd = open("/dev/msm_audio_ctl", O_RDWR);
7852aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
7862aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            if (fd < 0) {
787c3dee7890047bad1136078f0f6e2b6d1a9a24947Steve Block                ALOGE("Cannot open msm_audio_ctl");
7882aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                return -1;
7892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            }
7902aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
7912aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (ioctl(fd, AUDIO_STOP_VOICE, NULL)) {
792c3dee7890047bad1136078f0f6e2b6d1a9a24947Steve Block               ALOGE("Cannot stop voice");
7932aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland               close(fd);
7942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland               return -1;
7952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
796f9452ed4a7c7bbde537f3f2690fc124e5a1beaffSteve Block        ALOGD("Voice Stopped!!");
7972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        voice_started = 0;
7982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
7992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
8002aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    close(fd);
8012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
8022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
8032aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
8042aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
8052aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland// always call with mutex held
8062aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::doAudioRouteOrMute(uint32_t device)
8072aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
8087fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    uint32_t rx_acdb_id = 0;
8097fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    uint32_t tx_acdb_id = 0;
8107fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi
811f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi    if (support_a1026 == 1)
812f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi            doAudience_A1026_Control(mMode, mRecordState, device);
813f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi
8146727fbd4be7d7cd0acfb55b7461f9d9a23225f60Eric Laurent    if (device == (uint32_t)SND_DEVICE_BT) {
8150f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        if (!mBluetoothNrec) {
8162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            device = SND_DEVICE_BT_EC_OFF;
8172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
8182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
8197fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi
8202176dbc34c87e6855a912920f6868f8d211d12b4Eric Laurent
821a526b0683dba50dac8a37ed45e3a08536044e973Jean-Michel Trivi    if (device == (int) SND_DEVICE_BT) {
822f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        if (mBluetoothIdTx != 0) {
8232d319172300af10e139818ea367c4afc14c616f5Eric Laurent            rx_acdb_id = mBluetoothIdRx;
8242d319172300af10e139818ea367c4afc14c616f5Eric Laurent            tx_acdb_id = mBluetoothIdTx;
825c9bee51bef9f5376838aa90e8c9c53f47265e54cEric Laurent        } else {
826c9bee51bef9f5376838aa90e8c9c53f47265e54cEric Laurent            /* use default BT entry defined in AudioBTID.csv */
827c9bee51bef9f5376838aa90e8c9c53f47265e54cEric Laurent            rx_acdb_id = mBTEndpoints[0].rx;
828c9bee51bef9f5376838aa90e8c9c53f47265e54cEric Laurent            tx_acdb_id = mBTEndpoints[0].tx;
829f9452ed4a7c7bbde537f3f2690fc124e5a1beaffSteve Block            ALOGD("Update ACDB ID to default BT setting\n");
830f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        }
831a526b0683dba50dac8a37ed45e3a08536044e973Jean-Michel Trivi    }  else if (device == (int) SND_DEVICE_CARKIT
832a526b0683dba50dac8a37ed45e3a08536044e973Jean-Michel Trivi                || device == (int) SND_DEVICE_BT_EC_OFF) {
833f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        if (mBluetoothIdTx != 0) {
834f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            rx_acdb_id = mBluetoothIdRx;
835f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            tx_acdb_id = mBluetoothIdTx;
836c9bee51bef9f5376838aa90e8c9c53f47265e54cEric Laurent        } else {
837c9bee51bef9f5376838aa90e8c9c53f47265e54cEric Laurent            /* use default carkit entry defined in AudioBTID.csv */
838c9bee51bef9f5376838aa90e8c9c53f47265e54cEric Laurent            rx_acdb_id = mBTEndpoints[1].rx;
839c9bee51bef9f5376838aa90e8c9c53f47265e54cEric Laurent            tx_acdb_id = mBTEndpoints[1].tx;
840f9452ed4a7c7bbde537f3f2690fc124e5a1beaffSteve Block            ALOGD("Update ACDB ID to default carkit setting");
841f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        }
8426af540e6c360750623644c6b25e3d97590990694Eric Laurent    } else if (mMode == AudioSystem::MODE_IN_CALL
8436af540e6c360750623644c6b25e3d97590990694Eric Laurent               && hac_enable && mHACSetting &&
8446af540e6c360750623644c6b25e3d97590990694Eric Laurent               device == (int) SND_DEVICE_HANDSET) {
845f9452ed4a7c7bbde537f3f2690fc124e5a1beaffSteve Block        ALOGD("Update acdb id to hac profile.");
846f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        rx_acdb_id = ACDB_ID_HAC_HANDSET_SPKR;
847f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        tx_acdb_id = ACDB_ID_HAC_HANDSET_MIC;
848f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    } else {
849f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        if (!checkOutputStandby() || mMode != AudioSystem::MODE_IN_CALL)
8507fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi            rx_acdb_id = getACDB(MOD_PLAY, device);
8517fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi        if (mRecordState)
8527fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi            tx_acdb_id = getACDB(MOD_REC, device);
8537fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    }
85422f2554680715d1ea993409217a4a21f652ef130Steve Block    ALOGV("doAudioRouteOrMute: rx acdb %d, tx acdb %d\n", rx_acdb_id, tx_acdb_id);
8557fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi
8567fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    return do_route_audio_dev_ctrl(device, mMode == AudioSystem::MODE_IN_CALL, rx_acdb_id, tx_acdb_id);
8572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
8582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
8592aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::get_mMode(void)
8602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
8612aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return mMode;
8622aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
8632aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
8642aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::get_mRoutes(void)
8652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
8662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return mRoutes[mMode];
8672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
8682aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
8692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::set_mRecordState(bool onoff)
8702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
8712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mRecordState = onoff;
8722aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return 0;
8732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
8742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
875f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchevstatus_t AudioHardware::get_batt_temp(int *batt_temp)
876f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev{
877f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    int fd, len;
878f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    const char *fn =
879ec78ad65a1110fe007c3bdaba824f66bbfe522e3Eric Laurent            "/sys/devices/platform/ds2784-battery/power_supply/battery/temp";
880f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    char get_batt_temp[6] = { 0 };
881f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev
882f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    if ((fd = open(fn, O_RDONLY)) < 0) {
883c3dee7890047bad1136078f0f6e2b6d1a9a24947Steve Block        ALOGE("%s: cannot open %s: %s\n", __FUNCTION__, fn, strerror(errno));
884f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        return UNKNOWN_ERROR;
885f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    }
886f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev
887f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    if ((len = read(fd, get_batt_temp, sizeof(get_batt_temp))) <= 1) {
888c3dee7890047bad1136078f0f6e2b6d1a9a24947Steve Block        ALOGE("read battery temp fail: %s\n", strerror(errno));
889f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        close(fd);
890f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        return BAD_VALUE;
891f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    }
892f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev
893f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    *batt_temp = strtol(get_batt_temp, NULL, 10);
894f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    close(fd);
895f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    return NO_ERROR;
896f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev}
897f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev
898d666d60c2b157bee1aaf2233c253778929bd7d49Jean-Michel Trivi/*
899d666d60c2b157bee1aaf2233c253778929bd7d49Jean-Michel Trivi * Note: upon exiting doA1026_init(), fd_a1026 will be -1
900d666d60c2b157bee1aaf2233c253778929bd7d49Jean-Michel Trivi */
9012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::doA1026_init(void)
9022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
9032aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    struct a1026img fwimg;
9042aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    char char_tmp = 0;
90508516fe50b023532d5a3010050970de28e14621bIliyan Malchev    unsigned char local_vpimg_buf[A1026_MAX_FW_SIZE], *ptr = local_vpimg_buf;
90608516fe50b023532d5a3010050970de28e14621bIliyan Malchev    int rc = 0, fw_fd = -1;
90708516fe50b023532d5a3010050970de28e14621bIliyan Malchev    ssize_t nr;
90808516fe50b023532d5a3010050970de28e14621bIliyan Malchev    size_t remaining;
90908516fe50b023532d5a3010050970de28e14621bIliyan Malchev    struct stat fw_stat;
9102aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
91108516fe50b023532d5a3010050970de28e14621bIliyan Malchev    static const char *const fn = "/system/etc/vpimg";
91208516fe50b023532d5a3010050970de28e14621bIliyan Malchev    static const char *const path = "/dev/audience_a1026";
91308516fe50b023532d5a3010050970de28e14621bIliyan Malchev
91408516fe50b023532d5a3010050970de28e14621bIliyan Malchev    if (fd_a1026 < 0)
91508516fe50b023532d5a3010050970de28e14621bIliyan Malchev        fd_a1026 = open(path, O_RDWR | O_NONBLOCK, 0);
9162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
9172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (fd_a1026 < 0) {
918c3dee7890047bad1136078f0f6e2b6d1a9a24947Steve Block        ALOGE("Cannot open %s %d\n", path, fd_a1026);
91908516fe50b023532d5a3010050970de28e14621bIliyan Malchev        support_a1026 = 0;
92008516fe50b023532d5a3010050970de28e14621bIliyan Malchev        goto open_drv_err;
9212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
9222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
92308516fe50b023532d5a3010050970de28e14621bIliyan Malchev    fw_fd = open(fn, O_RDONLY);
92408516fe50b023532d5a3010050970de28e14621bIliyan Malchev    if (fw_fd < 0) {
925c3dee7890047bad1136078f0f6e2b6d1a9a24947Steve Block        ALOGE("Fail to open %s\n", fn);
9262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        goto ld_img_error;
927637d2d047afc8033f91357725474b32b74173c65Joe Onorato    } else {
928f9452ed4a7c7bbde537f3f2690fc124e5a1beaffSteve Block        ALOGD("open %s success\n", fn);
929637d2d047afc8033f91357725474b32b74173c65Joe Onorato    }
9302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
93108516fe50b023532d5a3010050970de28e14621bIliyan Malchev    rc = fstat(fw_fd, &fw_stat);
93208516fe50b023532d5a3010050970de28e14621bIliyan Malchev    if (rc < 0) {
933c3dee7890047bad1136078f0f6e2b6d1a9a24947Steve Block        ALOGE("Cannot stat file %s: %s\n", fn, strerror(errno));
93408516fe50b023532d5a3010050970de28e14621bIliyan Malchev        goto ld_img_error;
93508516fe50b023532d5a3010050970de28e14621bIliyan Malchev    }
93608516fe50b023532d5a3010050970de28e14621bIliyan Malchev
93708516fe50b023532d5a3010050970de28e14621bIliyan Malchev    remaining = (int)fw_stat.st_size;
9382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
939f9452ed4a7c7bbde537f3f2690fc124e5a1beaffSteve Block    ALOGD("Firmware %s size %d\n", fn, remaining);
94008516fe50b023532d5a3010050970de28e14621bIliyan Malchev
94108516fe50b023532d5a3010050970de28e14621bIliyan Malchev    if (remaining > sizeof(local_vpimg_buf)) {
942c3dee7890047bad1136078f0f6e2b6d1a9a24947Steve Block        ALOGE("File %s size %d exceeds internal limit %d\n",
94308516fe50b023532d5a3010050970de28e14621bIliyan Malchev             fn, remaining, sizeof(local_vpimg_buf));
94408516fe50b023532d5a3010050970de28e14621bIliyan Malchev        goto ld_img_error;
9452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
9462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
94708516fe50b023532d5a3010050970de28e14621bIliyan Malchev    while (remaining) {
94808516fe50b023532d5a3010050970de28e14621bIliyan Malchev        nr = read(fw_fd, ptr, remaining);
94908516fe50b023532d5a3010050970de28e14621bIliyan Malchev        if (nr < 0) {
950c3dee7890047bad1136078f0f6e2b6d1a9a24947Steve Block            ALOGE("Error reading firmware: %s\n", strerror(errno));
95108516fe50b023532d5a3010050970de28e14621bIliyan Malchev            goto ld_img_error;
95208516fe50b023532d5a3010050970de28e14621bIliyan Malchev        }
95308516fe50b023532d5a3010050970de28e14621bIliyan Malchev        else if (!nr) {
95408516fe50b023532d5a3010050970de28e14621bIliyan Malchev            if (remaining)
9553fb19cd0b6534ef9d36f8ac0c5ddbdc73ed92a26Steve Block                ALOGW("EOF reading firmware %s while %d bytes remain\n",
95608516fe50b023532d5a3010050970de28e14621bIliyan Malchev                     fn, remaining);
95708516fe50b023532d5a3010050970de28e14621bIliyan Malchev            break;
95808516fe50b023532d5a3010050970de28e14621bIliyan Malchev        }
95908516fe50b023532d5a3010050970de28e14621bIliyan Malchev        remaining -= nr;
96008516fe50b023532d5a3010050970de28e14621bIliyan Malchev        ptr += nr;
96108516fe50b023532d5a3010050970de28e14621bIliyan Malchev    }
96208516fe50b023532d5a3010050970de28e14621bIliyan Malchev
96308516fe50b023532d5a3010050970de28e14621bIliyan Malchev    close (fw_fd);
96408516fe50b023532d5a3010050970de28e14621bIliyan Malchev    fw_fd = -1;
96508516fe50b023532d5a3010050970de28e14621bIliyan Malchev
9662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    fwimg.buf = local_vpimg_buf;
96708516fe50b023532d5a3010050970de28e14621bIliyan Malchev    fwimg.img_size = (int)(fw_stat.st_size - remaining);
968f9452ed4a7c7bbde537f3f2690fc124e5a1beaffSteve Block    ALOGD("Total %d bytes put to user space buffer.\n", fwimg.img_size);
9692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
9702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    rc = ioctl(fd_a1026, A1026_BOOTUP_INIT, &fwimg);
9712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (!rc) {
972f9452ed4a7c7bbde537f3f2690fc124e5a1beaffSteve Block        ALOGD("audience_a1026 init OK\n");
9732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mA1026Init = 1;
9742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else
975c3dee7890047bad1136078f0f6e2b6d1a9a24947Steve Block        ALOGE("audience_a1026 init failed\n");
9762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
9772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandld_img_error:
97808516fe50b023532d5a3010050970de28e14621bIliyan Malchev    if (fw_fd >= 0)
97908516fe50b023532d5a3010050970de28e14621bIliyan Malchev        close(fw_fd);
9802aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    close(fd_a1026);
9812aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandopen_drv_err:
9822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    fd_a1026 = -1;
9832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return rc;
9842aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
9852aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
9862aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::get_snd_dev(void)
9872aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
9882aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    Mutex::Autolock lock(mLock);
9897161d052ce69228825bd5deca3bfa4a213a99f06HK Chen    return mCurSndDevice;
9902aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
9912aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
9927fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Triviuint32_t AudioHardware::getACDB(int mode, int device)
9930f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent{
9947fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    uint32_t acdb_id = 0;
995f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    int batt_temp = 0;
9960f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    if (mMode == AudioSystem::MODE_IN_CALL) {
997f9452ed4a7c7bbde537f3f2690fc124e5a1beaffSteve Block        ALOGD("skip update ACDB due to in-call");
9980f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        return 0;
9990f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    }
10000f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent
10017fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    if (mode == MOD_PLAY) {
10027fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi        switch (device) {
10030f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            case SND_DEVICE_HEADSET:
10040f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            case SND_DEVICE_NO_MIC_HEADSET:
1005da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            case SND_DEVICE_NO_MIC_HEADSET_BACK_MIC:
10060f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            case SND_DEVICE_FM_HEADSET:
10070f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                acdb_id = ACDB_ID_HEADSET_PLAYBACK;
10080f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                break;
10090f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            case SND_DEVICE_SPEAKER:
10100f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            case SND_DEVICE_FM_SPEAKER:
1011da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            case SND_DEVICE_SPEAKER_BACK_MIC:
10120f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                acdb_id = ACDB_ID_SPKR_PLAYBACK;
1013f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev                if(alt_enable) {
1014f9452ed4a7c7bbde537f3f2690fc124e5a1beaffSteve Block                    ALOGD("Enable ALT for speaker\n");
10156727fbd4be7d7cd0acfb55b7461f9d9a23225f60Eric Laurent                    if (get_batt_temp(&batt_temp) == NO_ERROR) {
1016f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev                        if (batt_temp < 50)
1017f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev                            acdb_id = ACDB_ID_ALT_SPKR_PLAYBACK;
1018f9452ed4a7c7bbde537f3f2690fc124e5a1beaffSteve Block                        ALOGD("ALT batt temp = %d\n", batt_temp);
1019f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev                    }
1020f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev                }
10210f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                break;
10220f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            case SND_DEVICE_HEADSET_AND_SPEAKER:
102358cf88a5a91d82ae2fb3e23365eaa4524a9cd089Jean-Michel Trivi            case SND_DEVICE_HEADSET_AND_SPEAKER_BACK_MIC:
10240f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                acdb_id = ACDB_ID_HEADSET_RINGTONE_PLAYBACK;
10250f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                break;
10260f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            default:
10270f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                break;
10280f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        }
10297fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    } else if (mode == MOD_REC) {
10307fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi        switch (device) {
10310f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            case SND_DEVICE_HEADSET:
10320f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            case SND_DEVICE_FM_HEADSET:
10330f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            case SND_DEVICE_FM_SPEAKER:
103458cf88a5a91d82ae2fb3e23365eaa4524a9cd089Jean-Michel Trivi            case SND_DEVICE_HEADSET_AND_SPEAKER:
10350f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                acdb_id = ACDB_ID_EXT_MIC_REC;
10360f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                break;
10370f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            case SND_DEVICE_HANDSET:
10380f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            case SND_DEVICE_NO_MIC_HEADSET:
10390f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            case SND_DEVICE_SPEAKER:
104008516fe50b023532d5a3010050970de28e14621bIliyan Malchev                if (vr_mode_enabled == 0) {
104163af0f3cbd387e97bcaca82d1e22787c224d6430Jean-Michel Trivi                    acdb_id = ACDB_ID_INT_MIC_REC;
104263af0f3cbd387e97bcaca82d1e22787c224d6430Jean-Michel Trivi                } else {
104363af0f3cbd387e97bcaca82d1e22787c224d6430Jean-Michel Trivi                    acdb_id = ACDB_ID_INT_MIC_VR;
104463af0f3cbd387e97bcaca82d1e22787c224d6430Jean-Michel Trivi                }
104563af0f3cbd387e97bcaca82d1e22787c224d6430Jean-Michel Trivi                break;
1046da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            case SND_DEVICE_SPEAKER_BACK_MIC:
1047da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            case SND_DEVICE_NO_MIC_HEADSET_BACK_MIC:
1048da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent            case SND_DEVICE_HANDSET_BACK_MIC:
104958cf88a5a91d82ae2fb3e23365eaa4524a9cd089Jean-Michel Trivi            case SND_DEVICE_HEADSET_AND_SPEAKER_BACK_MIC:
105063af0f3cbd387e97bcaca82d1e22787c224d6430Jean-Michel Trivi                acdb_id = ACDB_ID_CAMCORDER;
10510f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                break;
10520f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            default:
10530f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                break;
10540f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        }
10550f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    }
105622f2554680715d1ea993409217a4a21f652ef130Steve Block    ALOGV("getACDB, return ID %d\n", acdb_id);
10577fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi    return acdb_id;
10580f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent}
10590f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent
1060f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchevstatus_t AudioHardware::do_tpa2018_control(int mode)
1061f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev{
1062f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    if (curr_out_device == HANDSET_SPKR ||
1063f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        curr_out_device == SPKR_PHONE_MONO ||
1064f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        curr_out_device == HEADSET_SPKR_STEREO ||
1065f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        curr_out_device == SPKR_PHONE_HEADSET_STEREO ||
1066f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        curr_out_device == FM_SPKR) {
1067f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev
1068f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev	int fd, rc;
1069f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        int retry = 3;
1070f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev
1071f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        switch (mode) {
1072f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        case AudioSystem::MODE_NORMAL:
1073f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            mode = TPA2018_MODE_PLAYBACK;
1074f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            break;
1075f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        case AudioSystem::MODE_RINGTONE:
1076f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            mode = TPA2018_MODE_RINGTONE;
1077f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            break;
1078f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        case AudioSystem::MODE_IN_CALL:
1079f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            mode = TPA2018_MODE_VOICE_CALL;
1080f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            break;
1081f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        default:
1082f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            return 0;
1083f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        }
1084f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev
1085f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        fd = open("/dev/tpa2018d1", O_RDWR);
1086f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        if (fd < 0) {
1087c3dee7890047bad1136078f0f6e2b6d1a9a24947Steve Block            ALOGE("can't open /dev/tpa2018d1 %d", fd);
1088f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            return -1;
1089f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        }
1090f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev
1091f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        do {
1092f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            rc = ioctl(fd, TPA2018_SET_MODE, &mode);
1093f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev            if (!rc)
1094f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev                break;
1095f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        } while (--retry);
1096f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev
1097f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        if (rc < 0) {
1098c3dee7890047bad1136078f0f6e2b6d1a9a24947Steve Block            ALOGE("ioctl TPA2018_SET_MODE failed: %s", strerror(errno));
1099f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        } else
1100f9452ed4a7c7bbde537f3f2690fc124e5a1beaffSteve Block            ALOGD("Update TPA2018_SET_MODE to mode %d success", mode);
1101f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev
1102f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev        close(fd);
1103f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    }
1104f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev    return 0;
1105f92ef8fe452d3f8742d3aa680d1a443f571f028dIliyan Malchev}
11067fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi
11072aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::doAudience_A1026_Control(int Mode, bool Record, uint32_t Routes)
11082aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
11092aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    int rc = 0;
11100f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    int retry = 4;
11112aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
11122aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (!mA1026Init) {
11133fb19cd0b6534ef9d36f8ac0c5ddbdc73ed92a26Steve Block        ALOGW("Audience A1026 not initialized.\n");
111411c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent        return NO_INIT;
11152aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
11162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
111711c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent    mA1026Lock.lock();
11182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (fd_a1026 < 0) {
11192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        fd_a1026 = open("/dev/audience_a1026", O_RDWR);
11202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (fd_a1026 < 0) {
1121c3dee7890047bad1136078f0f6e2b6d1a9a24947Steve Block            ALOGE("Cannot open audience_a1026 device (%d)\n", fd_a1026);
112211c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent            mA1026Lock.unlock();
11232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            return -1;
112411c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent        }
11252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
11262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
11272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if ((Mode < AudioSystem::MODE_CURRENT) || (Mode >= AudioSystem::NUM_MODES)) {
11283fb19cd0b6534ef9d36f8ac0c5ddbdc73ed92a26Steve Block        ALOGW("Illegal value: doAudience_A1026_Control(%d, %u, %u)", Mode, Record, Routes);
11292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mA1026Lock.unlock();
11302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return BAD_VALUE;
11312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
11322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
11332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (Mode == AudioSystem::MODE_IN_CALL) {
11342aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (Record == 1) {
11352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	    switch (Routes) {
11362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        case SND_DEVICE_HANDSET:
11372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        case SND_DEVICE_NO_MIC_HEADSET:
1138da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent	            //TODO: what do we do for camcorder when in call?
1139da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent	        case SND_DEVICE_NO_MIC_HEADSET_BACK_MIC:
1140da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent	        case SND_DEVICE_HANDSET_BACK_MIC:
114117b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent	        case SND_DEVICE_TTY_VCO:
11429ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	            if (enable1026) {
11434bcd5b16c66bc5c2bffe232f15f5cb83aea18318Jean-Michel Trivi                    new_pathid = A1026_PATH_INCALL_RECEIVER;
114422f2554680715d1ea993409217a4a21f652ef130Steve Block                    ALOGV("A1026 control: new path is A1026_PATH_INCALL_RECEIVER");
11459ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	            } else {
11469ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	                new_pathid = A1026_PATH_INCALL_NO_NS_RECEIVER;
114722f2554680715d1ea993409217a4a21f652ef130Steve Block	                ALOGV("A1026 control: new path is A1026_PATH_INCALL_NO_NS_RECEIVER");
11489ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	            }
11499ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	            break;
11509ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	        case SND_DEVICE_HEADSET:
11519ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	        case SND_DEVICE_HEADSET_AND_SPEAKER:
11529ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	        case SND_DEVICE_FM_HEADSET:
11539ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	        case SND_DEVICE_FM_SPEAKER:
11549ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	        case SND_DEVICE_HEADSET_AND_SPEAKER_BACK_MIC:
11554bcd5b16c66bc5c2bffe232f15f5cb83aea18318Jean-Michel Trivi	            new_pathid = A1026_PATH_INCALL_HEADSET;
115622f2554680715d1ea993409217a4a21f652ef130Steve Block	            ALOGV("A1026 control: new path is A1026_PATH_INCALL_HEADSET");
11572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            break;
11582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        case SND_DEVICE_SPEAKER:
1159da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent	            //TODO: what do we do for camcorder when in call?
1160da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent	        case SND_DEVICE_SPEAKER_BACK_MIC:
11614bcd5b16c66bc5c2bffe232f15f5cb83aea18318Jean-Michel Trivi	            new_pathid = A1026_PATH_INCALL_SPEAKER;
116222f2554680715d1ea993409217a4a21f652ef130Steve Block	            ALOGV("A1026 control: new path is A1026_PATH_INCALL_SPEAKER");
11632aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            break;
11642aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        case SND_DEVICE_BT:
11652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        case SND_DEVICE_BT_EC_OFF:
1166c42d5b9bd789034e4e10679b24a7bd38e68f4556Eric Laurent	        case SND_DEVICE_CARKIT:
11674bcd5b16c66bc5c2bffe232f15f5cb83aea18318Jean-Michel Trivi	            new_pathid = A1026_PATH_INCALL_BT;
116822f2554680715d1ea993409217a4a21f652ef130Steve Block	            ALOGV("A1026 control: new path is A1026_PATH_INCALL_BT");
11692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            break;
1170e7af7ee40e27869a0cbbe4a5c91cbe6719fdfd44Iliyan Malchev	        case SND_DEVICE_TTY_HCO:
1171e7af7ee40e27869a0cbbe4a5c91cbe6719fdfd44Iliyan Malchev	        case SND_DEVICE_TTY_FULL:
1172e7af7ee40e27869a0cbbe4a5c91cbe6719fdfd44Iliyan Malchev	            new_pathid = A1026_PATH_INCALL_TTY;
117322f2554680715d1ea993409217a4a21f652ef130Steve Block	            ALOGV("A1026 control: new path is A1026_PATH_INCALL_TTY");
1174e7af7ee40e27869a0cbbe4a5c91cbe6719fdfd44Iliyan Malchev	            break;
11752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        default:
11762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            break;
11772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            }
11782aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland       } else {
11792aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           switch (Routes) {
11802aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        case SND_DEVICE_HANDSET:
11812aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        case SND_DEVICE_NO_MIC_HEADSET:
118217b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent	        case SND_DEVICE_TTY_VCO:
11839ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	            if (enable1026) {
11849ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	                new_pathid = A1026_PATH_INCALL_RECEIVER; /* NS CT mode, Dual MIC */
118522f2554680715d1ea993409217a4a21f652ef130Steve Block                    ALOGV("A1026 control: new path is A1026_PATH_INCALL_RECEIVER");
11869ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	            } else {
11879ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	                new_pathid = A1026_PATH_INCALL_NO_NS_RECEIVER;
118822f2554680715d1ea993409217a4a21f652ef130Steve Block	                ALOGV("A1026 control: new path is A1026_PATH_INCALL_NO_NS_RECEIVER");
11899ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	            }
11909ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	            break;
11919ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	        case SND_DEVICE_HEADSET:
11929ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	        case SND_DEVICE_HEADSET_AND_SPEAKER:
11939ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	        case SND_DEVICE_FM_HEADSET:
11949ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	        case SND_DEVICE_FM_SPEAKER:
11952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            new_pathid = A1026_PATH_INCALL_HEADSET; /* NS disable, Headset MIC */
119622f2554680715d1ea993409217a4a21f652ef130Steve Block	            ALOGV("A1026 control: new path is A1026_PATH_INCALL_HEADSET");
11972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            break;
11982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        case SND_DEVICE_SPEAKER:
11992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            new_pathid = A1026_PATH_INCALL_SPEAKER; /* NS FT mode, Main MIC */
120022f2554680715d1ea993409217a4a21f652ef130Steve Block	            ALOGV("A1026 control: new path is A1026_PATH_INCALL_SPEAKER");
12012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            break;
12022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        case SND_DEVICE_BT:
12032aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        case SND_DEVICE_BT_EC_OFF:
1204c42d5b9bd789034e4e10679b24a7bd38e68f4556Eric Laurent	        case SND_DEVICE_CARKIT:
12052aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            new_pathid = A1026_PATH_INCALL_BT; /* QCOM NS, BT MIC */
120622f2554680715d1ea993409217a4a21f652ef130Steve Block	            ALOGV("A1026 control: new path is A1026_PATH_INCALL_BT");
12072aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            break;
1208e7af7ee40e27869a0cbbe4a5c91cbe6719fdfd44Iliyan Malchev	        case SND_DEVICE_TTY_HCO:
1209e7af7ee40e27869a0cbbe4a5c91cbe6719fdfd44Iliyan Malchev	        case SND_DEVICE_TTY_FULL:
1210e7af7ee40e27869a0cbbe4a5c91cbe6719fdfd44Iliyan Malchev	            new_pathid = A1026_PATH_INCALL_TTY;
121122f2554680715d1ea993409217a4a21f652ef130Steve Block	            ALOGV("A1026 control: new path is A1026_PATH_INCALL_TTY");
1212e7af7ee40e27869a0cbbe4a5c91cbe6719fdfd44Iliyan Malchev	            break;
12132aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        default:
12142aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            break;
12152aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            }
12162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland       }
12172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else if (Record == 1) {
12182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        switch (Routes) {
1219ba36d4fa33072ef14183365fffd289762c26905eJean-Michel Trivi        case SND_DEVICE_SPEAKER:
1220ba36d4fa33072ef14183365fffd289762c26905eJean-Michel Trivi            // default output is speaker, recording from phone mic, user RECEIVER configuration
1221739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        case SND_DEVICE_HANDSET:
1222739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        case SND_DEVICE_NO_MIC_HEADSET:
122308516fe50b023532d5a3010050970de28e14621bIliyan Malchev	        if (vr_mode_enabled) {
1224739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	            if (vr_uses_ns) {
12254bcd5b16c66bc5c2bffe232f15f5cb83aea18318Jean-Michel Trivi	                new_pathid = A1026_PATH_VR_NS_RECEIVER;
122622f2554680715d1ea993409217a4a21f652ef130Steve Block	                ALOGV("A1026 control: new path is A1026_PATH_VR_NS_RECEIVER");
1227739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	            } else {
12284bcd5b16c66bc5c2bffe232f15f5cb83aea18318Jean-Michel Trivi	                new_pathid = A1026_PATH_VR_NO_NS_RECEIVER;
122922f2554680715d1ea993409217a4a21f652ef130Steve Block	                ALOGV("A1026 control: new path is A1026_PATH_VR_NO_NS_RECEIVER");
1230739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	            }
1231739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	        } else {
12329ffa86825c57c8bf82669b438bd0e8feb865d4b7Jean-Michel Trivi	            new_pathid = A1026_PATH_RECORD_RECEIVER; /* INT-MIC Recording: NS disable, Main MIC */
123322f2554680715d1ea993409217a4a21f652ef130Steve Block                ALOGV("A1026 control: new path is A1026_PATH_RECORD_RECEIVER");
1234739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	        }
12352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        break;
1236739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        case SND_DEVICE_HEADSET:
1237739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        case SND_DEVICE_HEADSET_AND_SPEAKER:
1238739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        case SND_DEVICE_FM_HEADSET:
1239739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        case SND_DEVICE_FM_SPEAKER:
124008516fe50b023532d5a3010050970de28e14621bIliyan Malchev	        if (vr_mode_enabled) {
1241739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	            if (vr_uses_ns) {
12424bcd5b16c66bc5c2bffe232f15f5cb83aea18318Jean-Michel Trivi	                new_pathid = A1026_PATH_VR_NS_HEADSET;
124322f2554680715d1ea993409217a4a21f652ef130Steve Block	                ALOGV("A1026 control: new path is A1026_PATH_VR_NS_HEADSET");
1244739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	            } else {
12454bcd5b16c66bc5c2bffe232f15f5cb83aea18318Jean-Michel Trivi	                new_pathid = A1026_PATH_VR_NO_NS_HEADSET;
124622f2554680715d1ea993409217a4a21f652ef130Steve Block	                ALOGV("A1026 control: new path is A1026_PATH_VR_NO_NS_HEADSET");
1247739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	            }
1248739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	        } else {
1249739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	            new_pathid = A1026_PATH_RECORD_HEADSET; /* EXT-MIC Recording: NS disable, Headset MIC */
125022f2554680715d1ea993409217a4a21f652ef130Steve Block	            ALOGV("A1026 control: new path is A1026_PATH_RECORD_HEADSET");
1251739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	        }
1252739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	        break;
1253739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        case SND_DEVICE_SPEAKER_BACK_MIC:
1254739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        case SND_DEVICE_NO_MIC_HEADSET_BACK_MIC:
1255739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        case SND_DEVICE_HANDSET_BACK_MIC:
125658cf88a5a91d82ae2fb3e23365eaa4524a9cd089Jean-Michel Trivi        case SND_DEVICE_HEADSET_AND_SPEAKER_BACK_MIC:
1257da9d5ab10524c32d7949363a10fde1bec5fdf9faEric Laurent	        new_pathid = A1026_PATH_CAMCORDER; /* CAM-Coder: NS FT mode, Back MIC */
125822f2554680715d1ea993409217a4a21f652ef130Steve Block	        ALOGV("A1026 control: new path is A1026_PATH_CAMCORDER");
12592aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        break;
1260739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        case SND_DEVICE_BT:
1261739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        case SND_DEVICE_BT_EC_OFF:
1262c42d5b9bd789034e4e10679b24a7bd38e68f4556Eric Laurent        case SND_DEVICE_CARKIT:
126308516fe50b023532d5a3010050970de28e14621bIliyan Malchev	        if (vr_mode_enabled) {
1264739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	            if (vr_uses_ns) {
12654bcd5b16c66bc5c2bffe232f15f5cb83aea18318Jean-Michel Trivi	                new_pathid = A1026_PATH_VR_NS_BT;
126622f2554680715d1ea993409217a4a21f652ef130Steve Block	                ALOGV("A1026 control: new path is A1026_PATH_VR_NS_BT");
1267739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	            } else {
12684bcd5b16c66bc5c2bffe232f15f5cb83aea18318Jean-Michel Trivi	                new_pathid = A1026_PATH_VR_NO_NS_BT;
126922f2554680715d1ea993409217a4a21f652ef130Steve Block	                ALOGV("A1026 control: new path is A1026_PATH_VR_NO_NS_BT");
1270739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	            }
1271739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	        } else {
1272739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	            new_pathid = A1026_PATH_RECORD_BT; /* BT MIC */
127322f2554680715d1ea993409217a4a21f652ef130Steve Block	            ALOGV("A1026 control: new path is A1026_PATH_RECORD_BT");
1274739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi	        }
12752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        break;
1276739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        default:
12772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        break;
12782aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
12792aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
12802aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    else {
12812176dbc34c87e6855a912920f6868f8d211d12b4Eric Laurent        switch (Routes) {
12822176dbc34c87e6855a912920f6868f8d211d12b4Eric Laurent        case SND_DEVICE_BT:
12832176dbc34c87e6855a912920f6868f8d211d12b4Eric Laurent        case SND_DEVICE_BT_EC_OFF:
12842176dbc34c87e6855a912920f6868f8d211d12b4Eric Laurent        case SND_DEVICE_CARKIT:
12852176dbc34c87e6855a912920f6868f8d211d12b4Eric Laurent            new_pathid = A1026_PATH_RECORD_BT; /* BT MIC */
128622f2554680715d1ea993409217a4a21f652ef130Steve Block            ALOGV("A1026 control: new path is A1026_PATH_RECORD_BT");
12872176dbc34c87e6855a912920f6868f8d211d12b4Eric Laurent            break;
12882176dbc34c87e6855a912920f6868f8d211d12b4Eric Laurent        default:
12892176dbc34c87e6855a912920f6868f8d211d12b4Eric Laurent            new_pathid = A1026_PATH_SUSPEND;
12902176dbc34c87e6855a912920f6868f8d211d12b4Eric Laurent            break;
12912176dbc34c87e6855a912920f6868f8d211d12b4Eric Laurent        }
12922aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
12932aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
12942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (old_pathid != new_pathid) {
12955a182ec3e8b87b6538b4b492cb993239a677915fSteve Block        //ALOGI("A1026: do ioctl(A1026_SET_CONFIG) to %d\n", new_pathid);
12960f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        do {
12970f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            rc = ioctl(fd_a1026, A1026_SET_CONFIG, &new_pathid);
12980f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            if (!rc) {
12990f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                old_pathid = new_pathid;
13000f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent                break;
13010f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            }
13020f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        } while (--retry);
13030f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent
13040f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        if (rc < 0) {
13053fb19cd0b6534ef9d36f8ac0c5ddbdc73ed92a26Steve Block            ALOGW("A1026 do hard reset to recover from error!\n");
13060f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            rc = doA1026_init(); /* A1026 needs to do hard reset! */
13070f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            if (!rc) {
1308d666d60c2b157bee1aaf2233c253778929bd7d49Jean-Michel Trivi                /* after doA1026_init(), fd_a1026 is -1*/
1309d666d60c2b157bee1aaf2233c253778929bd7d49Jean-Michel Trivi                fd_a1026 = open("/dev/audience_a1026", O_RDWR);
1310d666d60c2b157bee1aaf2233c253778929bd7d49Jean-Michel Trivi                if (fd_a1026 < 0) {
1311c3dee7890047bad1136078f0f6e2b6d1a9a24947Steve Block                    ALOGE("A1026 Fatal Error: unable to open A1026 after hard reset\n");
1312d666d60c2b157bee1aaf2233c253778929bd7d49Jean-Michel Trivi                } else {
1313d666d60c2b157bee1aaf2233c253778929bd7d49Jean-Michel Trivi                    rc = ioctl(fd_a1026, A1026_SET_CONFIG, &new_pathid);
1314d666d60c2b157bee1aaf2233c253778929bd7d49Jean-Michel Trivi                    if (!rc) {
1315d666d60c2b157bee1aaf2233c253778929bd7d49Jean-Michel Trivi                        old_pathid = new_pathid;
1316d666d60c2b157bee1aaf2233c253778929bd7d49Jean-Michel Trivi                    } else {
1317c3dee7890047bad1136078f0f6e2b6d1a9a24947Steve Block                        ALOGE("A1026 Fatal Error: unable to A1026_SET_CONFIG after hard reset\n");
1318d666d60c2b157bee1aaf2233c253778929bd7d49Jean-Michel Trivi                    }
1319d666d60c2b157bee1aaf2233c253778929bd7d49Jean-Michel Trivi                }
13200f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent            } else
1321c3dee7890047bad1136078f0f6e2b6d1a9a24947Steve Block                ALOGE("A1026 Fatal Error: Re-init A1026 Failed\n");
13220f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent        }
13232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
13242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
1325fe306807b0fe36243d9e7eca094d5e20a0667016Jean-Michel Trivi    if (fd_a1026 >= 0) {
1326fe306807b0fe36243d9e7eca094d5e20a0667016Jean-Michel Trivi        close(fd_a1026);
1327fe306807b0fe36243d9e7eca094d5e20a0667016Jean-Michel Trivi    }
13282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    fd_a1026 = -1;
132911c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent    mA1026Lock.unlock();
13302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
13312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return rc;
13322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
13332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
13342aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
133511c6a166fa684a2e44d22a142aad106f74a9409fEric Laurentstatus_t AudioHardware::doRouting()
13362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
1337f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi    Mutex::Autolock lock(mLock);
1338f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi    uint32_t outputDevices = mOutput->devices();
13392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    status_t ret = NO_ERROR;
134011c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent    AudioStreamInMSM72xx *input = getActiveInput_l();
134111c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent    uint32_t inputDevice = (input == NULL) ? 0 : input->devices();
1342f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi    int sndDevice = -1;
13432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
134417b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent    if (mMode == AudioSystem::MODE_IN_CALL && mTTYMode != TTY_MODE_OFF) {
134517b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent        if ((outputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) ||
134617b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent            (outputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE)) {
134717b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent            switch (mTTYMode) {
134817b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent            case TTY_MODE_FULL:
134917b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent                sndDevice = SND_DEVICE_TTY_FULL;
135017b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent                break;
135117b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent            case TTY_MODE_VCO:
135217b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent                sndDevice = SND_DEVICE_TTY_VCO;
135317b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent                break;
135417b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent            case TTY_MODE_HCO:
135517b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent                sndDevice = SND_DEVICE_TTY_HCO;
135617b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent                break;
135717b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent            }
135817b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent        }
135917b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent    }
136017b4d724c2d8f3b70ae94ab523f584940d1c175aEric Laurent
1361c08cbb26e57c8c3521391947e676cbdb6e81603bEric Laurent    if (sndDevice == -1 && inputDevice != 0) {
13625a182ec3e8b87b6538b4b492cb993239a677915fSteve Block        ALOGI("do input routing device %x\n", inputDevice);
1363710f4558c4f660e59551b1ed13c5106f9e460a59Eric Laurent        if (inputDevice & AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
13645a182ec3e8b87b6538b4b492cb993239a677915fSteve Block            ALOGI("Routing audio to Bluetooth PCM\n");
1365710f4558c4f660e59551b1ed13c5106f9e460a59Eric Laurent            sndDevice = SND_DEVICE_BT;
1366710f4558c4f660e59551b1ed13c5106f9e460a59Eric Laurent        } else if (inputDevice & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT) {
13675a182ec3e8b87b6538b4b492cb993239a677915fSteve Block            ALOGI("Routing audio to Bluetooth car kit\n");
1368710f4558c4f660e59551b1ed13c5106f9e460a59Eric Laurent            sndDevice = SND_DEVICE_CARKIT;
1369710f4558c4f660e59551b1ed13c5106f9e460a59Eric Laurent        } else if (inputDevice & AudioSystem::DEVICE_IN_WIRED_HEADSET) {
1370710f4558c4f660e59551b1ed13c5106f9e460a59Eric Laurent            if ((outputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) &&
1371710f4558c4f660e59551b1ed13c5106f9e460a59Eric Laurent                    (outputDevices & AudioSystem::DEVICE_OUT_SPEAKER)) {
13725a182ec3e8b87b6538b4b492cb993239a677915fSteve Block                        ALOGI("Routing audio to Wired Headset and Speaker\n");
1373710f4558c4f660e59551b1ed13c5106f9e460a59Eric Laurent                        sndDevice = SND_DEVICE_HEADSET_AND_SPEAKER;
1374f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi            } else {
13755a182ec3e8b87b6538b4b492cb993239a677915fSteve Block                ALOGI("Routing audio to Wired Headset\n");
137611c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent                sndDevice = SND_DEVICE_HEADSET;
137711c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent            }
137811c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent        } else if (inputDevice & AudioSystem::DEVICE_IN_BACK_MIC) {
137911c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent            if (outputDevices & (AudioSystem:: DEVICE_OUT_WIRED_HEADSET) &&
138011c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent                   (outputDevices & AudioSystem:: DEVICE_OUT_SPEAKER)) {
13815a182ec3e8b87b6538b4b492cb993239a677915fSteve Block                ALOGI("Routing audio to Wired Headset and Speaker with back mic\n");
138211c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent                sndDevice = SND_DEVICE_HEADSET_AND_SPEAKER_BACK_MIC;
138311c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent            } else if (outputDevices & AudioSystem::DEVICE_OUT_SPEAKER) {
13845a182ec3e8b87b6538b4b492cb993239a677915fSteve Block                ALOGI("Routing audio to Speakerphone with back mic\n");
138511c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent                sndDevice = SND_DEVICE_SPEAKER_BACK_MIC;
138611c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent            } else if (outputDevices == AudioSystem::DEVICE_OUT_EARPIECE) {
13875a182ec3e8b87b6538b4b492cb993239a677915fSteve Block                ALOGI("Routing audio to Handset with back mic\n");
138811c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent                sndDevice = SND_DEVICE_HANDSET_BACK_MIC;
138911c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent            } else {
13905a182ec3e8b87b6538b4b492cb993239a677915fSteve Block                ALOGI("Routing audio to Headset with back mic\n");
139111c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent                sndDevice = SND_DEVICE_NO_MIC_HEADSET_BACK_MIC;
139211c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent            }
139311c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent        } else {
139411c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent            if (outputDevices & AudioSystem::DEVICE_OUT_SPEAKER) {
13955a182ec3e8b87b6538b4b492cb993239a677915fSteve Block                ALOGI("Routing audio to Speakerphone\n");
139611c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent                sndDevice = SND_DEVICE_SPEAKER;
139711c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent            } else if (outputDevices == AudioSystem::DEVICE_OUT_WIRED_HEADPHONE) {
13985a182ec3e8b87b6538b4b492cb993239a677915fSteve Block                ALOGI("Routing audio to Speakerphone\n");
139911c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent                sndDevice = SND_DEVICE_NO_MIC_HEADSET;
140011c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent            } else {
14015a182ec3e8b87b6538b4b492cb993239a677915fSteve Block                ALOGI("Routing audio to Handset\n");
140211c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent                sndDevice = SND_DEVICE_HANDSET;
1403956f7ba5ee0f087c91b5fefd2718dae30f8c1e29Eric Laurent            }
1404956f7ba5ee0f087c91b5fefd2718dae30f8c1e29Eric Laurent        }
1405f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi    }
140611c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent    // if inputDevice == 0, restore output routing
1407956f7ba5ee0f087c91b5fefd2718dae30f8c1e29Eric Laurent
1408f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi    if (sndDevice == -1) {
1409f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        if (outputDevices & (outputDevices - 1)) {
1410f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi            if ((outputDevices & AudioSystem::DEVICE_OUT_SPEAKER) == 0) {
14113fb19cd0b6534ef9d36f8ac0c5ddbdc73ed92a26Steve Block                ALOGW("Hardware does not support requested route combination (%#X),"
1412f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                        " picking closest possible route...", outputDevices);
1413956f7ba5ee0f087c91b5fefd2718dae30f8c1e29Eric Laurent            }
1414f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        }
1415956f7ba5ee0f087c91b5fefd2718dae30f8c1e29Eric Laurent
1416f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        if (outputDevices &
1417dd65e38951ed174f9d3d34886795438440f7eea0Eric Laurent                (AudioSystem::DEVICE_OUT_BLUETOOTH_SCO | AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET)) {
14185a182ec3e8b87b6538b4b492cb993239a677915fSteve Block                    ALOGI("Routing audio to Bluetooth PCM\n");
1419f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                    sndDevice = SND_DEVICE_BT;
1420f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        } else if (outputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT) {
14215a182ec3e8b87b6538b4b492cb993239a677915fSteve Block            ALOGI("Routing audio to Bluetooth PCM\n");
1422f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi            sndDevice = SND_DEVICE_CARKIT;
1423f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        } else if ((outputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) &&
1424f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                (outputDevices & AudioSystem::DEVICE_OUT_SPEAKER)) {
14255a182ec3e8b87b6538b4b492cb993239a677915fSteve Block                    ALOGI("Routing audio to Wired Headset and Speaker\n");
1426956f7ba5ee0f087c91b5fefd2718dae30f8c1e29Eric Laurent                    sndDevice = SND_DEVICE_HEADSET_AND_SPEAKER;
1427f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        } else if (outputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE) {
1428f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi            if (outputDevices & AudioSystem::DEVICE_OUT_SPEAKER) {
14295a182ec3e8b87b6538b4b492cb993239a677915fSteve Block                ALOGI("Routing audio to No microphone Wired Headset and Speaker (%d,%x)\n", mMode, outputDevices);
1430f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                sndDevice = SND_DEVICE_HEADSET_AND_SPEAKER;
1431956f7ba5ee0f087c91b5fefd2718dae30f8c1e29Eric Laurent            } else {
14325a182ec3e8b87b6538b4b492cb993239a677915fSteve Block                ALOGI("Routing audio to No microphone Wired Headset (%d,%x)\n", mMode, outputDevices);
1433f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi                sndDevice = SND_DEVICE_NO_MIC_HEADSET;
14342aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            }
1435f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        } else if (outputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) {
14365a182ec3e8b87b6538b4b492cb993239a677915fSteve Block            ALOGI("Routing audio to Wired Headset\n");
1437f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi            sndDevice = SND_DEVICE_HEADSET;
1438f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        } else if (outputDevices & AudioSystem::DEVICE_OUT_SPEAKER) {
14395a182ec3e8b87b6538b4b492cb993239a677915fSteve Block            ALOGI("Routing audio to Speakerphone\n");
1440f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi            sndDevice = SND_DEVICE_SPEAKER;
1441f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        } else {
14425a182ec3e8b87b6538b4b492cb993239a677915fSteve Block            ALOGI("Routing audio to Handset\n");
1443f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi            sndDevice = SND_DEVICE_HANDSET;
14442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
1445f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi    }
14462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
1447f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi    if ((vr_mode_change) || (sndDevice != -1 && sndDevice != mCurSndDevice)) {
1448f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        ret = doAudioRouteOrMute(sndDevice);
1449f8d3aebe4c19283eb34fb89e5932b3399d3bd753Jean-Michel Trivi        mCurSndDevice = sndDevice;
14503964d4ed448b00791bc1b574913be24f44b45f0fEric Laurent        if (mMode == AudioSystem::MODE_IN_CALL) {
1451ec78ad65a1110fe007c3bdaba824f66bbfe522e3Eric Laurent            if (mHACSetting && hac_enable && mCurSndDevice == (int) SND_DEVICE_HANDSET) {
1452f9452ed4a7c7bbde537f3f2690fc124e5a1beaffSteve Block                ALOGD("HAC enable: Setting in-call volume to maximum.\n");
1453ec78ad65a1110fe007c3bdaba824f66bbfe522e3Eric Laurent                set_volume_rpc(VOICE_VOLUME_MAX);
1454ec78ad65a1110fe007c3bdaba824f66bbfe522e3Eric Laurent            } else {
1455ec78ad65a1110fe007c3bdaba824f66bbfe522e3Eric Laurent                set_volume_rpc(mVoiceVolume);
1456ec78ad65a1110fe007c3bdaba824f66bbfe522e3Eric Laurent            }
14573964d4ed448b00791bc1b574913be24f44b45f0fEric Laurent        }
14582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
14592aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
14602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return ret;
14612aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
14622aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
14632aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::checkMicMute()
14642aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
14652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    Mutex::Autolock lock(mLock);
14662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mMode != AudioSystem::MODE_IN_CALL) {
14672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        setMicMute_nosync(true);
14682aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
14692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
14702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
14712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
14722aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
14732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::dumpInternals(int fd, const Vector<String16>& args)
14742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
14752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    const size_t SIZE = 256;
14762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    char buffer[SIZE];
14772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    String8 result;
14782aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append("AudioHardware::dumpInternals\n");
14792aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmInit: %s\n", mInit? "true": "false");
14802aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
14812aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmMicMute: %s\n", mMicMute? "true": "false");
14822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
14832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmBluetoothNrec: %s\n", mBluetoothNrec? "true": "false");
14842aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
14850f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    snprintf(buffer, SIZE, "\tmBluetoothIdtx: %d\n", mBluetoothIdTx);
14860f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    result.append(buffer);
14870f2f4d0a60cf93a7a281e217408a4249715f5748Eric Laurent    snprintf(buffer, SIZE, "\tmBluetoothIdrx: %d\n", mBluetoothIdRx);
14882aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
14892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    ::write(fd, result.string(), result.size());
14902aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
14912aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
14922aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
14932aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::dump(int fd, const Vector<String16>& args)
14942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
14952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    dumpInternals(fd, args);
14962aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    for (size_t index = 0; index < mInputs.size(); index++) {
14972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mInputs[index]->dump(fd, args);
14982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
14992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
15002aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mOutput) {
15012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mOutput->dump(fd, args);
15022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
15032aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
15042aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
15052aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
15062aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlanduint32_t AudioHardware::getInputSampleRate(uint32_t sampleRate)
15072aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
15082aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    uint32_t i;
15092aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    uint32_t prevDelta;
15102aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    uint32_t delta;
15112aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
15122aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    for (i = 0, prevDelta = 0xFFFFFFFF; i < sizeof(inputSamplingRates)/sizeof(uint32_t); i++, prevDelta = delta) {
15132aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        delta = abs(sampleRate - inputSamplingRates[i]);
15142aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (delta > prevDelta) break;
15152aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
15162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // i is always > 0 here
15172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return inputSamplingRates[i-1];
15182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
15192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
152011c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent// getActiveInput_l() must be called with mLock held
152111c6a166fa684a2e44d22a142aad106f74a9409fEric LaurentAudioHardware::AudioStreamInMSM72xx *AudioHardware::getActiveInput_l()
152211c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent{
152311c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent    for (size_t i = 0; i < mInputs.size(); i++) {
152411c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent        // return first input found not being in standby mode
152511c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent        // as only one input can be in this state
1526e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent        if (!mInputs[i]->checkStandby()) {
152711c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent            return mInputs[i];
152811c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent        }
152911c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent    }
153011c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent
153111c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent    return NULL;
153211c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent}
15332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland// ----------------------------------------------------------------------------
15342aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
15352aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandAudioHardware::AudioStreamOutMSM72xx::AudioStreamOutMSM72xx() :
1536f2236a59c89b93062490d2c236ffebe57173af6eEric Laurent    mHardware(0), mFd(-1), mStartCount(0), mRetryCount(0), mStandby(true),
1537f2236a59c89b93062490d2c236ffebe57173af6eEric Laurent    mDevices(0), mChannels(AUDIO_HW_OUT_CHANNELS), mSampleRate(AUDIO_HW_OUT_SAMPLERATE),
1538f2236a59c89b93062490d2c236ffebe57173af6eEric Laurent    mBufferSize(AUDIO_HW_OUT_BUFSZ)
15392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
15402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
15412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
15422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::AudioStreamOutMSM72xx::set(
15432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        AudioHardware* hw, uint32_t devices, int *pFormat, uint32_t *pChannels, uint32_t *pRate)
15442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
15452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    int lFormat = pFormat ? *pFormat : 0;
15462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    uint32_t lChannels = pChannels ? *pChannels : 0;
15472aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    uint32_t lRate = pRate ? *pRate : 0;
15482aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
15492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mHardware = hw;
1550f2236a59c89b93062490d2c236ffebe57173af6eEric Laurent    mDevices = devices;
15512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
15522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // fix up defaults
15532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (lFormat == 0) lFormat = format();
15542aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (lChannels == 0) lChannels = channels();
15552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (lRate == 0) lRate = sampleRate();
15562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
15572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // check values
15582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if ((lFormat != format()) ||
15592aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        (lChannels != channels()) ||
15602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        (lRate != sampleRate())) {
15612aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (pFormat) *pFormat = format();
15622aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (pChannels) *pChannels = channels();
15632aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (pRate) *pRate = sampleRate();
15642aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return BAD_VALUE;
15652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
15662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
15672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (pFormat) *pFormat = lFormat;
15682aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (pChannels) *pChannels = lChannels;
15692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (pRate) *pRate = lRate;
15702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
1571f2236a59c89b93062490d2c236ffebe57173af6eEric Laurent    mChannels = lChannels;
1572f2236a59c89b93062490d2c236ffebe57173af6eEric Laurent    mSampleRate = lRate;
1573f2236a59c89b93062490d2c236ffebe57173af6eEric Laurent    mBufferSize = hw->getBufferSize(lRate, AudioSystem::popCount(lChannels));
15742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
15752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
15762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
15772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
15782aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandAudioHardware::AudioStreamOutMSM72xx::~AudioStreamOutMSM72xx()
15792aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
15802176dbc34c87e6855a912920f6868f8d211d12b4Eric Laurent    standby();
15812aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
15822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
15832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandssize_t AudioHardware::AudioStreamOutMSM72xx::write(const void* buffer, size_t bytes)
15842aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
1585f9452ed4a7c7bbde537f3f2690fc124e5a1beaffSteve Block    // ALOGD("AudioStreamOutMSM72xx::write(%p, %u)", buffer, bytes);
15862aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    status_t status = NO_INIT;
15872aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    size_t count = bytes;
15882aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    const uint8_t* p = static_cast<const uint8_t*>(buffer);
15892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
15902aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mStandby) {
15912aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
159222f2554680715d1ea993409217a4a21f652ef130Steve Block        ALOGV("acquire output wakelock");
1593b508a4857b07898fb8322a858c4ee9624bcf1180Iliyan Malchev        acquire_wake_lock(PARTIAL_WAKE_LOCK, kOutputWakelockStr);
1594b508a4857b07898fb8322a858c4ee9624bcf1180Iliyan Malchev
15952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        // open driver
159622f2554680715d1ea993409217a4a21f652ef130Steve Block        ALOGV("open pcm_out driver");
15972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        status = ::open("/dev/msm_pcm_out", O_RDWR);
15982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (status < 0) {
15992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            if (errCount++ < 10) {
1600c3dee7890047bad1136078f0f6e2b6d1a9a24947Steve Block                ALOGE("Cannot open /dev/msm_pcm_out errno: %d", errno);
16012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            }
1602e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent            release_wake_lock(kOutputWakelockStr);
16032aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            goto Error;
16042aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
16052aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mFd = status;
1606e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent        mStandby = false;
16072aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
16082aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        // configuration
160922f2554680715d1ea993409217a4a21f652ef130Steve Block        ALOGV("get config");
16102aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        struct msm_audio_config config;
16112aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        status = ioctl(mFd, AUDIO_GET_CONFIG, &config);
16122aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (status < 0) {
1613c3dee7890047bad1136078f0f6e2b6d1a9a24947Steve Block            ALOGE("Cannot read pcm_out config");
16142aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            goto Error;
16152aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
16162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
161722f2554680715d1ea993409217a4a21f652ef130Steve Block        ALOGV("set pcm_out config");
16182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        config.channel_count = AudioSystem::popCount(channels());
1619f2236a59c89b93062490d2c236ffebe57173af6eEric Laurent        config.sample_rate = mSampleRate;
1620f2236a59c89b93062490d2c236ffebe57173af6eEric Laurent        config.buffer_size = mBufferSize;
16212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        config.buffer_count = AUDIO_HW_NUM_OUT_BUF;
16222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        config.codec_type = CODEC_TYPE_PCM;
16232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        status = ioctl(mFd, AUDIO_SET_CONFIG, &config);
16242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (status < 0) {
1625c3dee7890047bad1136078f0f6e2b6d1a9a24947Steve Block            ALOGE("Cannot set config");
16262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            goto Error;
16272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
16282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
162922f2554680715d1ea993409217a4a21f652ef130Steve Block        ALOGV("buffer_size: %u", config.buffer_size);
163022f2554680715d1ea993409217a4a21f652ef130Steve Block        ALOGV("buffer_count: %u", config.buffer_count);
163122f2554680715d1ea993409217a4a21f652ef130Steve Block        ALOGV("channel_count: %u", config.channel_count);
163222f2554680715d1ea993409217a4a21f652ef130Steve Block        ALOGV("sample_rate: %u", config.sample_rate);
16332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
16347fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi        uint32_t acdb_id = mHardware->getACDB(MOD_PLAY, mHardware->get_snd_dev());
16357fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi        status = ioctl(mFd, AUDIO_START, &acdb_id);
163631923bb6797ec304d26395acf6d946ab8e44aa6eHK Chen        if (status < 0) {
1637c3dee7890047bad1136078f0f6e2b6d1a9a24947Steve Block            ALOGE("Cannot start pcm playback");
163831923bb6797ec304d26395acf6d946ab8e44aa6eHK Chen            goto Error;
16392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
164010254cc35f5cb7ebe2c7ef452815486cb8e92a33Jean-Michel Trivi
164110254cc35f5cb7ebe2c7ef452815486cb8e92a33Jean-Michel Trivi        status = ioctl(mFd, AUDIO_SET_VOLUME, &stream_volume);
164210254cc35f5cb7ebe2c7ef452815486cb8e92a33Jean-Michel Trivi        if (status < 0) {
1643c3dee7890047bad1136078f0f6e2b6d1a9a24947Steve Block            ALOGE("Cannot start pcm playback");
164410254cc35f5cb7ebe2c7ef452815486cb8e92a33Jean-Michel Trivi            goto Error;
164510254cc35f5cb7ebe2c7ef452815486cb8e92a33Jean-Michel Trivi        }
16462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
16472aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
16482aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    while (count) {
16492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        ssize_t written = ::write(mFd, p, count);
16502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (written >= 0) {
16512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            count -= written;
16522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            p += written;
16532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        } else {
1654e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent            if (errno != EAGAIN) {
1655e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent                status = written;
1656e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent                goto Error;
1657e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent            }
16582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            mRetryCount++;
1659f9452ed4a7c7bbde537f3f2690fc124e5a1beaffSteve Block            ALOGD("EAGAIN - retry");
16602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
16612aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
16622aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
16632aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return bytes;
16642aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
16652aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandError:
1666e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent
1667e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent    standby();
1668e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent
16692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // Simulate audio output timing in case of error
1670e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent    usleep((((bytes * 1000) / frameSize()) * 1000) / sampleRate());
16712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return status;
16722aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
16732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
16742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::AudioStreamOutMSM72xx::standby()
16752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
1676e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent    if (!mStandby) {
1677f9452ed4a7c7bbde537f3f2690fc124e5a1beaffSteve Block        ALOGD("AudioHardware pcm playback is going to standby.");
1678e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent        if (mFd >= 0) {
1679e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent            ::close(mFd);
1680e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent            mFd = -1;
1681e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent        }
168222f2554680715d1ea993409217a4a21f652ef130Steve Block        ALOGV("release output wakelock");
16835d89308f2e1252eff2743bf823bf558dbb0de2faDave Sparks        release_wake_lock(kOutputWakelockStr);
1684e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent        mStandby = true;
16852aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
1686e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent    return NO_ERROR;
16872aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
16882aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
16892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::AudioStreamOutMSM72xx::dump(int fd, const Vector<String16>& args)
16902aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
16912aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    const size_t SIZE = 256;
16922aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    char buffer[SIZE];
16932aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    String8 result;
16942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append("AudioStreamOutMSM72xx::dump\n");
16952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tsample rate: %d\n", sampleRate());
16962aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
16972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize());
16982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
16992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tchannels: %d\n", channels());
17002aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
17012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tformat: %d\n", format());
17022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
17032aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmHardware: %p\n", mHardware);
17042aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
17052aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmFd: %d\n", mFd);
17062aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
17072aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmStartCount: %d\n", mStartCount);
17082aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
17092aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmRetryCount: %d\n", mRetryCount);
17102aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
17112aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmStandby: %s\n", mStandby? "true": "false");
17122aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
17132aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    ::write(fd, result.string(), result.size());
17142aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
17152aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
17162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
1717e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent
17182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandbool AudioHardware::AudioStreamOutMSM72xx::checkStandby()
17192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
17202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return mStandby;
17212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
17222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
17232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
17242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::AudioStreamOutMSM72xx::setParameters(const String8& keyValuePairs)
17252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
17262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    AudioParameter param = AudioParameter(keyValuePairs);
17272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    String8 key = String8(AudioParameter::keyRouting);
17282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    status_t status = NO_ERROR;
17292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    int device;
173022f2554680715d1ea993409217a4a21f652ef130Steve Block    ALOGV("AudioStreamOutMSM72xx::setParameters() %s", keyValuePairs.string());
17312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
17322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (param.getInt(key, device) == NO_ERROR) {
17332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mDevices = device;
173422f2554680715d1ea993409217a4a21f652ef130Steve Block        ALOGV("set output routing %x", mDevices);
173511c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent        status = mHardware->doRouting();
17362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        param.remove(key);
17372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
17382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
17392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (param.size()) {
17402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        status = BAD_VALUE;
17412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
17422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return status;
17432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
17442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
17452aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandString8 AudioHardware::AudioStreamOutMSM72xx::getParameters(const String8& keys)
17462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
17472aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    AudioParameter param = AudioParameter(keys);
17482aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    String8 value;
17492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    String8 key = String8(AudioParameter::keyRouting);
17502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
17512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (param.get(key, value) == NO_ERROR) {
175222f2554680715d1ea993409217a4a21f652ef130Steve Block        ALOGV("get routing %x", mDevices);
17532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        param.addInt(key, (int)mDevices);
17542aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
17552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
175622f2554680715d1ea993409217a4a21f652ef130Steve Block    ALOGV("AudioStreamOutMSM72xx::getParameters() %s", param.toString().string());
17572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return param.toString();
17582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
17592aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
17603b9744cccd99fd9f32ae3b99fbc8d6898b118a43Eric Laurentstatus_t AudioHardware::AudioStreamOutMSM72xx::getRenderPosition(uint32_t *dspFrames)
17613b9744cccd99fd9f32ae3b99fbc8d6898b118a43Eric Laurent{
17623b9744cccd99fd9f32ae3b99fbc8d6898b118a43Eric Laurent    //TODO: enable when supported by driver
17633b9744cccd99fd9f32ae3b99fbc8d6898b118a43Eric Laurent    return INVALID_OPERATION;
17643b9744cccd99fd9f32ae3b99fbc8d6898b118a43Eric Laurent}
17652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
17662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland// ----------------------------------------------------------------------------
17672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
17682aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandAudioHardware::AudioStreamInMSM72xx::AudioStreamInMSM72xx() :
1769e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent    mHardware(0), mFd(-1), mStandby(true), mRetryCount(0),
17702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mFormat(AUDIO_HW_IN_FORMAT), mChannels(AUDIO_HW_IN_CHANNELS),
1771f2236a59c89b93062490d2c236ffebe57173af6eEric Laurent    mSampleRate(AUDIO_HW_IN_SAMPLERATE), mBufferSize(AUDIO_HW_IN_BUFSZ),
17722aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mAcoustics((AudioSystem::audio_in_acoustics)0), mDevices(0)
17732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
17742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
17752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
17762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::AudioStreamInMSM72xx::set(
17772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        AudioHardware* hw, uint32_t devices, int *pFormat, uint32_t *pChannels, uint32_t *pRate,
17782aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        AudioSystem::audio_in_acoustics acoustic_flags)
17792aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
17802aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (pFormat == 0 || *pFormat != AUDIO_HW_IN_FORMAT) {
17812aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        *pFormat = AUDIO_HW_IN_FORMAT;
17822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return BAD_VALUE;
17832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
17842aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (pRate == 0) {
17852aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return BAD_VALUE;
17862aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
17872aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    uint32_t rate = hw->getInputSampleRate(*pRate);
17882aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (rate != *pRate) {
17892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        *pRate = rate;
17902aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return BAD_VALUE;
17912aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
17922aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
17932aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (pChannels == 0 || (*pChannels != AudioSystem::CHANNEL_IN_MONO &&
17942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        *pChannels != AudioSystem::CHANNEL_IN_STEREO)) {
17952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        *pChannels = AUDIO_HW_IN_CHANNELS;
17962aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return BAD_VALUE;
17972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
17982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
17992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mHardware = hw;
18002aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
180122f2554680715d1ea993409217a4a21f652ef130Steve Block    ALOGV("AudioStreamInMSM72xx::set(%d, %d, %u)", *pFormat, *pChannels, *pRate);
18022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mFd >= 0) {
1803c3dee7890047bad1136078f0f6e2b6d1a9a24947Steve Block        ALOGE("Audio record already open");
18042aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return -EPERM;
18052aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
18062aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
1807f2236a59c89b93062490d2c236ffebe57173af6eEric Laurent    mBufferSize = hw->getBufferSize(*pRate, AudioSystem::popCount(*pChannels));
18082aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mDevices = devices;
18092aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mFormat = AUDIO_HW_IN_FORMAT;
18102aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mChannels = *pChannels;
1811e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent    mSampleRate = *pRate;
18122aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
18132aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
18142aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
18152aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
18162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
18172aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandAudioHardware::AudioStreamInMSM72xx::~AudioStreamInMSM72xx()
18182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
181922f2554680715d1ea993409217a4a21f652ef130Steve Block    ALOGV("AudioStreamInMSM72xx destructor");
18202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    standby();
18212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
18222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
18232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandssize_t AudioHardware::AudioStreamInMSM72xx::read( void* buffer, ssize_t bytes)
18242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
182522f2554680715d1ea993409217a4a21f652ef130Steve Block//    ALOGV("AudioStreamInMSM72xx::read(%p, %ld)", buffer, bytes);
18262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (!mHardware) return -1;
18272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
18282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    size_t count = bytes;
18292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    uint8_t* p = static_cast<uint8_t*>(buffer);
1830e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent    status_t status = NO_ERROR;
18312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
1832e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent    if (mStandby) {
1833e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent        {   // scope for the lock
1834e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent            Mutex::Autolock lock(mHardware->mLock);
183522f2554680715d1ea993409217a4a21f652ef130Steve Block            ALOGV("acquire input wakelock");
1836e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent            acquire_wake_lock(PARTIAL_WAKE_LOCK, kInputWakelockStr);
1837e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent            // open audio input device
1838e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent            status = ::open("/dev/msm_pcm_in", O_RDWR);
1839e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent            if (status < 0) {
1840c3dee7890047bad1136078f0f6e2b6d1a9a24947Steve Block                ALOGE("Cannot open /dev/msm_pcm_in errno: %d", errno);
184122f2554680715d1ea993409217a4a21f652ef130Steve Block                ALOGV("release input wakelock");
1842e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent                release_wake_lock(kInputWakelockStr);
1843e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent                goto Error;
1844e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent            }
1845e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent            mFd = status;
1846e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent            mStandby = false;
1847e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent
1848e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent            // configuration
184922f2554680715d1ea993409217a4a21f652ef130Steve Block            ALOGV("get config");
1850e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent            struct msm_audio_config config;
1851e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent            status = ioctl(mFd, AUDIO_GET_CONFIG, &config);
1852e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent            if (status < 0) {
1853c3dee7890047bad1136078f0f6e2b6d1a9a24947Steve Block                ALOGE("Cannot read config");
1854e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent                goto Error;
1855e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent            }
1856e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent
185722f2554680715d1ea993409217a4a21f652ef130Steve Block            ALOGV("set config");
1858e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent            config.channel_count = AudioSystem::popCount(mChannels);
1859e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent            config.sample_rate = mSampleRate;
1860e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent            config.buffer_size = mBufferSize;
1861e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent            config.buffer_count = 2;
1862e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent            config.codec_type = CODEC_TYPE_PCM;
1863e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent            status = ioctl(mFd, AUDIO_SET_CONFIG, &config);
1864e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent            if (status < 0) {
1865c3dee7890047bad1136078f0f6e2b6d1a9a24947Steve Block                ALOGE("Cannot set config");
1866e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent                goto Error;
1867e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent            }
1868e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent
186922f2554680715d1ea993409217a4a21f652ef130Steve Block            ALOGV("buffer_size: %u", config.buffer_size);
187022f2554680715d1ea993409217a4a21f652ef130Steve Block            ALOGV("buffer_count: %u", config.buffer_count);
187122f2554680715d1ea993409217a4a21f652ef130Steve Block            ALOGV("channel_count: %u", config.channel_count);
187222f2554680715d1ea993409217a4a21f652ef130Steve Block            ALOGV("sample_rate: %u", config.sample_rate);
18732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
18742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
18752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mHardware->set_mRecordState(1);
187611c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent        // make sure a1026 config is re-applied even is input device is not changed
187711c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent        mHardware->clearCurDevice();
187811c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent        mHardware->doRouting();
187911c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent
18807fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi        uint32_t acdb_id = mHardware->getACDB(MOD_REC, mHardware->get_snd_dev());
18817fbea5ceecbfb87b9210f6e4ee08191ed1352addJean-Michel Trivi        if (ioctl(mFd, AUDIO_START, &acdb_id)) {
1882c3dee7890047bad1136078f0f6e2b6d1a9a24947Steve Block            ALOGE("Error starting record");
1883e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent            goto Error;
18842aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
18852aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
18862aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
18872aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    while (count) {
18882aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        ssize_t bytesRead = ::read(mFd, buffer, count);
18892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (bytesRead >= 0) {
18902aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            count -= bytesRead;
18912aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            p += bytesRead;
18922aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        } else {
1893e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent            if (errno != EAGAIN) {
1894e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent                status = bytesRead;
1895e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent                goto Error;
1896e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent            }
18972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            mRetryCount++;
1898f9452ed4a7c7bbde537f3f2690fc124e5a1beaffSteve Block            ALOGD("EAGAIN - retrying");
18992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
19002aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
19012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return bytes;
1902e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent
1903e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric LaurentError:
1904e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent    standby();
1905e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent
1906e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent    // Simulate audio input timing in case of error
1907e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent    usleep((((bytes * 1000) / frameSize()) * 1000) / sampleRate());
1908e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent
1909e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent    return status;
19102aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
19112aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
19122aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::AudioStreamInMSM72xx::standby()
19132aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
1914e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent    if (!mStandby) {
1915f9452ed4a7c7bbde537f3f2690fc124e5a1beaffSteve Block        ALOGD("AudioHardware PCM record is going to standby.");
19162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (mFd >= 0) {
19172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            ::close(mFd);
19182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            mFd = -1;
19192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
192022f2554680715d1ea993409217a4a21f652ef130Steve Block        ALOGV("release input wakelock");
19212176dbc34c87e6855a912920f6868f8d211d12b4Eric Laurent        release_wake_lock(kInputWakelockStr);
192211c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent
1923e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent        mStandby = true;
192411c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent
1925e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent        if (!mHardware) return -1;
1926e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent
1927e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent        mHardware->set_mRecordState(0);
1928e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent        // make sure a1026 config is re-applied even is input device is not changed
1929e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent        mHardware->clearCurDevice();
1930e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent        mHardware->doRouting();
1931e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent    }
193211c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent
19332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
19342aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
19352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
1936e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurentbool AudioHardware::AudioStreamInMSM72xx::checkStandby()
1937e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent{
1938e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent    return mStandby;
1939e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent}
1940e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent
19412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::AudioStreamInMSM72xx::dump(int fd, const Vector<String16>& args)
19422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
19432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    const size_t SIZE = 256;
19442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    char buffer[SIZE];
19452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    String8 result;
19462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append("AudioStreamInMSM72xx::dump\n");
19472aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tsample rate: %d\n", sampleRate());
19482aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
19492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize());
19502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
19512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tchannels: %d\n", channels());
19522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
19532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tformat: %d\n", format());
19542aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
19552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmHardware: %p\n", mHardware);
19562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
19572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmFd count: %d\n", mFd);
19582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
1959e784e44a0402aa4e9489e0b9f2f3d3685cf76a93Eric Laurent    snprintf(buffer, SIZE, "\tmStandby: %d\n", mStandby);
19602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
19612aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmRetryCount: %d\n", mRetryCount);
19622aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
19632aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    ::write(fd, result.string(), result.size());
19642aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
19652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
19662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
19672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::AudioStreamInMSM72xx::setParameters(const String8& keyValuePairs)
19682aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
19692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    AudioParameter param = AudioParameter(keyValuePairs);
19702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    status_t status = NO_ERROR;
19712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    int device;
19721119793f2bc460d6417fedb54c7a51c48ded56deJean-Michel Trivi    String8 key = String8(AudioParameter::keyInputSource);
19731119793f2bc460d6417fedb54c7a51c48ded56deJean-Michel Trivi    int source;
197422f2554680715d1ea993409217a4a21f652ef130Steve Block    ALOGV("AudioStreamInMSM72xx::setParameters() %s", keyValuePairs.string());
19752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
19761119793f2bc460d6417fedb54c7a51c48ded56deJean-Michel Trivi    // reading input source for voice recognition mode parameter
19771119793f2bc460d6417fedb54c7a51c48ded56deJean-Michel Trivi    if (param.getInt(key, source) == NO_ERROR) {
197822f2554680715d1ea993409217a4a21f652ef130Steve Block        ALOGV("set input source %d", source);
19791119793f2bc460d6417fedb54c7a51c48ded56deJean-Michel Trivi        int uses_vr = (source == AUDIO_SOURCE_VOICE_RECOGNITION);
19801119793f2bc460d6417fedb54c7a51c48ded56deJean-Michel Trivi        vr_mode_change = (vr_mode_enabled != uses_vr);
19811119793f2bc460d6417fedb54c7a51c48ded56deJean-Michel Trivi        vr_mode_enabled = uses_vr;
1982739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi        param.remove(key);
1983739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    }
1984739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi
1985739de5f36523862a7caa15590bd6b680b6cd2854Jean-Michel Trivi    // reading routing parameter
1986255bdedb2d7ebf4b14690776ff652df1de97fe95Eric Laurent    key = String8(AudioParameter::keyRouting);
19872aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (param.getInt(key, device) == NO_ERROR) {
198822f2554680715d1ea993409217a4a21f652ef130Steve Block        ALOGV("set input routing %x", device);
19892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (device & (device - 1)) {
19902aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            status = BAD_VALUE;
19912aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        } else {
19922aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            mDevices = device;
199311c6a166fa684a2e44d22a142aad106f74a9409fEric Laurent            status = mHardware->doRouting();
19942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
19952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        param.remove(key);
19962aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
19972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
19982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (param.size()) {
19992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        status = BAD_VALUE;
20002aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
20012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return status;
20022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
20032aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
20042aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandString8 AudioHardware::AudioStreamInMSM72xx::getParameters(const String8& keys)
20052aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
20062aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    AudioParameter param = AudioParameter(keys);
20072aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    String8 value;
20082aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    String8 key = String8(AudioParameter::keyRouting);
20092aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
20102aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (param.get(key, value) == NO_ERROR) {
201122f2554680715d1ea993409217a4a21f652ef130Steve Block        ALOGV("get routing %x", mDevices);
20122aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        param.addInt(key, (int)mDevices);
20132aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
20142aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
201522f2554680715d1ea993409217a4a21f652ef130Steve Block    ALOGV("AudioStreamInMSM72xx::getParameters() %s", param.toString().string());
20162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return param.toString();
20172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
20182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
20192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland// ----------------------------------------------------------------------------
20202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
20212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandextern "C" AudioHardwareInterface* createAudioHardware(void) {
20222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return new AudioHardware();
20232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
20242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
20252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}; // namespace android
2026