AudioHardware.cpp revision 7161d052ce69228825bd5deca3bfa4a213a99f06
12aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland/*
22aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland** Copyright 2008, Google Inc.
32aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland**
42aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland** Licensed under the Apache License, Version 2.0 (the "License");
52aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland** you may not use this file except in compliance with the License.
62aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland** You may obtain a copy of the License at
72aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland**
82aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland**     http://www.apache.org/licenses/LICENSE-2.0
92aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland**
102aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland** Unless required by applicable law or agreed to in writing, software
112aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland** distributed under the License is distributed on an "AS IS" BASIS,
122aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
132aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland** See the License for the specific language governing permissions and
142aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland** limitations under the License.
152aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland*/
162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#include <math.h>
182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland//#define LOG_NDEBUG 0
202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#define LOG_TAG "AudioHardwareQSD"
212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#include <utils/Log.h>
222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#include <utils/String8.h>
232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#include <stdio.h>
252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#include <unistd.h>
262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#include <sys/ioctl.h>
272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#include <sys/types.h>
282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#include <sys/stat.h>
292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#include <dlfcn.h>
302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#include <fcntl.h>
312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland// hardware specific functions
332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
342aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#include "AudioHardware.h"
352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#include <media/AudioRecord.h>
362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandextern "C" {
382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#include "msm_audio.h"
392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#include "a1026.h"
402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandenum audio_routes {
432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    ROUTE_EARPIECE       = (1 << 0),
442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    ROUTE_SPEAKER        = (1 << 1),
452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    ROUTE_BLUETOOTH_SCO  = (1 << 2),
462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    ROUTE_HEADSET        = (1 << 3),
472aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    ROUTE_BLUETOOTH_A2DP = (1 << 4),
482aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    ROUTE_NO_MIC_HEADSET = (1 << 5),
492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    ROUTE_TTY            = (1 << 6),
502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    ROUTE_FM_HEADSET     = (1 << 7),
512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    ROUTE_FM_SPEAKER     = (1 << 8),
522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    ROUTE_ALL            = -1UL,
532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland};
542aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#define LOG_SND_RPC 0  // Set to 1 to log sound RPC's
562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#define TX_PATH (1)
572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_CURRENT = 256;
592aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_HANDSET = 0;
602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_SPEAKER = 1;
612aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_BT = 3;
622aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_CARKIT = 4;
632aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_BT_EC_OFF = 45;
642aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_HEADSET = 2;
652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_HEADSET_AND_SPEAKER = 10;
662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_FM_HEADSET = 9;
672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_FM_SPEAKER = 11;
682aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_NO_MIC_HEADSET = 8;
692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic const uint32_t SND_DEVICE_TTY_FULL = 5;
702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandnamespace android {
712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic int support_a1026 = 1;
722aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic int fd_a1026 = -1;
732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic int old_pathid = -1;
742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic int new_pathid = -1;
752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic int cur_rx_device = 0;
762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic int cur_tx_device = 0;
772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic int voice_started = 0;
782aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic int fd_fm_device = -1;
792aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandint errCount = 0;
802aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandconst uint32_t AudioHardware::inputSamplingRates[] = {
812aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000
822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland};
832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland// ----------------------------------------------------------------------------
842aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
852aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandAudioHardware::AudioHardware() :
862aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mInit(false), mMicMute(true), mBluetoothNrec(true), mBluetoothId(0),
872aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mA1026Init(false),
882aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mOutput(0)
892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
902aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    doA1026_init();
912aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mInit = true;
922aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
932aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
942aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandAudioHardware::~AudioHardware()
952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
962aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    for (size_t index = 0; index < mInputs.size(); index++) {
972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        closeInputStream((AudioStreamIn*)mInputs[index]);
982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mInputs.clear();
1002aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    closeOutputStream((AudioStreamOut*)mOutput);
1012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mInit = false;
1022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
1032aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
1042aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::initCheck()
1052aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
1062aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return mInit ? NO_ERROR : NO_INIT;
1072aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
1082aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
1092aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandAudioStreamOut* AudioHardware::openOutputStream(
1102aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status)
1112aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
1122aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    { // scope for the lock
1132aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        Mutex::Autolock lock(mLock);
1142aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
1152aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        // only one output stream allowed
1162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (mOutput) {
1172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            if (status) {
1182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                *status = INVALID_OPERATION;
1192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            }
1202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            return 0;
1212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
1222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
1232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        // create new output stream
1242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        AudioStreamOutMSM72xx* out = new AudioStreamOutMSM72xx();
1252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        status_t lStatus = out->set(this, devices, format, channels, sampleRate);
1262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (status) {
1272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            *status = lStatus;
1282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
1292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (lStatus == NO_ERROR) {
1302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            mOutput = out;
1312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        } else {
1322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            delete out;
1332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
1342aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
1352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return mOutput;
1362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
1372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
1382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandvoid AudioHardware::closeOutputStream(AudioStreamOut* out) {
1392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    Mutex::Autolock lock(mLock);
1402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mOutput == 0 || mOutput != out) {
1412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGW("Attempt to close invalid output stream");
1422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
1432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    else {
1442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        delete mOutput;
1452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mOutput = 0;
1462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
1472aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
1482aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
1492aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandAudioStreamIn* AudioHardware::openInputStream(
1502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status,
1512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        AudioSystem::audio_in_acoustics acoustic_flags)
1522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
1532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // check for valid input source
1542aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (!AudioSystem::isInputDevice((AudioSystem::audio_devices)devices)) {
1552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return 0;
1562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
1572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
1582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mLock.lock();
1592aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
1602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    AudioStreamInMSM72xx* in = new AudioStreamInMSM72xx();
1612aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    status_t lStatus = in->set(this, devices, format, channels, sampleRate, acoustic_flags);
1622aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (status) {
1632aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        *status = lStatus;
1642aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
1652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (lStatus != NO_ERROR) {
1662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mLock.unlock();
1672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        delete in;
1682aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return 0;
1692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
1702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
1712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mInputs.add(in);
1722aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mLock.unlock();
1732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
1742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return in;
1752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
1762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
1772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandvoid AudioHardware::closeInputStream(AudioStreamIn* in) {
1782aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    Mutex::Autolock lock(mLock);
1792aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
1802aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    ssize_t index = mInputs.indexOf((AudioStreamInMSM72xx *)in);
1812aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (index < 0) {
1822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGW("Attempt to close invalid input stream");
1832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else {
1842aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mLock.unlock();
1852aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        delete mInputs[index];
1862aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mLock.lock();
1872aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mInputs.removeAt(index);
1882aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
1892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
1902aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
1912aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::setMode(int mode)
1922aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
1932aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    status_t status = AudioHardwareBase::setMode(mode);
1942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (status == NO_ERROR) {
1952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        // make sure that doAudioRouteOrMute() is called by doRouting()
1962aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        // even if the new device selected is the same as current one.
1972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mCurSndDevice = -1;
1982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
1992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return status;
2002aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
2012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandbool AudioHardware::checkOutputStandby()
2032aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
2042aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mOutput)
2052aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (!mOutput->checkStandby())
2062aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            return false;
2072aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2082aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return true;
2092aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
2102aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic status_t set_mic_mute(bool mute)
2112aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
2122aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    int fd = -1, arg;
2132aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    struct msm_mute_info info;
2142aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    fd = open("/dev/msm_audio_ctl", O_RDWR);
2152aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (fd < 0) {
2162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGE("Cannot open msm_audio_ctl device\n");
2172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return -1;
2182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
2192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGD("Setting mic mute to %d\n", mute);
2202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    info.path = TX_PATH;
2212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    info.mute = mute;
2222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (ioctl(fd, AUDIO_SET_MUTE, &info)) {
2232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGE("Cannot set mic mute on current device\n");
2242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        close(fd);
2252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return -1;
2262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
2272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    close(fd);
2282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
2292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
2302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::setMicMute(bool state)
2322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
2332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    Mutex::Autolock lock(mLock);
2342aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return setMicMute_nosync(state);
2352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
2362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland// always call with mutex held
2382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::setMicMute_nosync(bool state)
2392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
2402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mMicMute != state) {
2412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mMicMute = state;
2422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return set_mic_mute(mMicMute); //always set current TX device
2432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
2442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
2452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
2462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2472aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::getMicMute(bool* state)
2482aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
2492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    *state = mMicMute;
2502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
2512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
2522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::setParameters(const String8& keyValuePairs)
2542aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
2552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    AudioParameter param = AudioParameter(keyValuePairs);
2562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    String8 value;
2572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    String8 key;
2582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    const char BT_NREC_KEY[] = "bt_headset_nrec";
2592aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    const char BT_NAME_KEY[] = "bt_headset_name";
2602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    const char BT_NREC_VALUE_ON[] = "on";
2612aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2622aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2632aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("setParameters() %s", keyValuePairs.string());
2642aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (keyValuePairs.length() == 0) return BAD_VALUE;
2662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    key = String8(BT_NREC_KEY);
2682aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (param.get(key, value) == NO_ERROR) {
2692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (value == BT_NREC_VALUE_ON) {
2702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            mBluetoothNrec = true;
2712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        } else {
2722aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            mBluetoothNrec = false;
2732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            LOGI("Turning noise reduction and echo cancellation off for BT "
2742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                 "headset");
2752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
2762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
2772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    key = String8(BT_NAME_KEY);
2782aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (param.get(key, value) == NO_ERROR) {
2792aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mBluetoothId = 0;
2802aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#if 0
2812aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        for (int i = 0; i < mNumSndEndpoints; i++) {
2822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            if (!strcasecmp(value.string(), mSndEndpoints[i].name)) {
2832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                mBluetoothId = mSndEndpoints[i].id;
2842aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                LOGI("Using custom acoustic parameters for %s", value.string());
2852aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                break;
2862aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            }
2872aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
2882aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#endif
2892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (mBluetoothId == 0) {
2902aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            LOGI("Using default acoustic parameters "
2912aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                 "(%s not in acoustic database)", value.string());
2922aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            doRouting(NULL);
2932aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
2942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
2952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
2962aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
2972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
2982aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandString8 AudioHardware::getParameters(const String8& keys)
2992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
3002aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    AudioParameter param = AudioParameter(keys);
3012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return param.toString();
3022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
3032aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
3042aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
3052aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic unsigned calculate_audpre_table_index(unsigned index)
3062aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
3072aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    switch (index) {
3082aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        case 48000:    return SAMP_RATE_INDX_48000;
3092aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        case 44100:    return SAMP_RATE_INDX_44100;
3102aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        case 32000:    return SAMP_RATE_INDX_32000;
3112aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        case 24000:    return SAMP_RATE_INDX_24000;
3122aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        case 22050:    return SAMP_RATE_INDX_22050;
3132aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        case 16000:    return SAMP_RATE_INDX_16000;
3142aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        case 12000:    return SAMP_RATE_INDX_12000;
3152aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        case 11025:    return SAMP_RATE_INDX_11025;
3162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        case 8000:    return SAMP_RATE_INDX_8000;
3172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        default:     return -1;
3182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
3192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
3202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandsize_t AudioHardware::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
3212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
3222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (format != AudioSystem::PCM_16_BIT) {
3232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGW("getInputBufferSize bad format: %d", format);
3242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return 0;
3252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
3262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (channelCount < 1 || channelCount > 2) {
3272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGW("getInputBufferSize bad channel count: %d", channelCount);
3282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return 0;
3292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
3302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
3312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return 2048*channelCount;
3322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
3332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
3342aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic status_t set_volume_rpc(uint32_t volume)
3352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
3362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    int fd = -1;
3372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    fd = open("/dev/msm_audio_ctl", O_RDWR);
3382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (fd < 0) {
3392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGE("Cannot open msm_audio_ctl device\n");
3402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return -1;
3412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
3422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    volume *= 20; //percentage
3432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGD("Setting in-call volume to %d\n", volume);
3442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (ioctl(fd, AUDIO_SET_VOLUME, &volume)) {
3452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGW("Cannot set volume on current device\n");
3462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
3472aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    close(fd);
3482aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
3492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
3502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
3512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::setVoiceVolume(float v)
3522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
3532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (v < 0.0) {
3542aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGW("setVoiceVolume(%f) under 0.0, assuming 0.0\n", v);
3552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        v = 0.0;
3562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else if (v > 1.0) {
3572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGW("setVoiceVolume(%f) over 1.0, assuming 1.0\n", v);
3582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        v = 1.0;
3592aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
3602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
3612aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    int vol = lrint(v * 5.0);
3622aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGD("setVoiceVolume(%f)\n", v);
3632aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGI("Setting in-call volume to %d (available range is 0 to 5)\n", vol);
3642aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
3652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    Mutex::Autolock lock(mLock);
3662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    set_volume_rpc(vol); //always set current device
3672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
3682aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
3692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
3702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::setMasterVolume(float v)
3712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
3722aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    Mutex::Autolock lock(mLock);
3732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    int vol = ceil(v * 5.0);
3742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGI("Set master volume to %d.\n", vol);
3752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // We return an error code here to let the audioflinger do in-software
3762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // volume on top of the maximum volume that we set through the SND API.
3772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // return error - software mixer will handle it
3782aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return -1;
3792aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
3802aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
3812aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatic status_t do_route_audio_dev_ctrl(uint32_t device, bool inCall)
3822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
3832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    int out_device = 0, mic_device = 0;
3842aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    int fd = 0;
3852aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
3862aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (device == SND_DEVICE_CURRENT)
3872aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        goto Incall;
3882aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
3892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // hack -- kernel needs to put these in include file
3902aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGD("Switching audio device to ");
3912aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (device == SND_DEVICE_HANDSET) {
3922aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           out_device = HANDSET_SPKR;
3932aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           mic_device = HANDSET_MIC;
3942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           LOGD("Handset");
3952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else if ((device  == SND_DEVICE_BT) || (device == SND_DEVICE_BT_EC_OFF)) {
3962aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           out_device = BT_SCO_SPKR;
3972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           mic_device = BT_SCO_MIC;
3982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           LOGD("BT Headset");
3992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else if (device == SND_DEVICE_SPEAKER) {
4002aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           out_device = SPKR_PHONE_MONO;
4012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           mic_device = SPKR_PHONE_MIC;
4022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           LOGD("Speakerphone");
4032aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else if (device == SND_DEVICE_HEADSET) {
4042aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           out_device = HEADSET_SPKR_STEREO;
4052aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           mic_device = HEADSET_MIC;
4062aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           LOGD("Stereo Headset");
4072aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else if (device == SND_DEVICE_HEADSET_AND_SPEAKER) {
4082aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           out_device = SPKR_PHONE_HEADSET_STEREO;
4092aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           mic_device = HEADSET_MIC;
4102aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           LOGD("Stereo Headset + Speaker");
4112aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else if (device == SND_DEVICE_NO_MIC_HEADSET) {
4122aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           out_device = HEADSET_SPKR_STEREO;
4132aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           mic_device = HANDSET_MIC;
4142aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           LOGD("No microphone Wired Headset");
4152aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else if (device == SND_DEVICE_FM_HEADSET) {
4162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           out_device = FM_HEADSET;
4172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           mic_device = HEADSET_MIC;
4182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           LOGD("Stereo FM headset");
4192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else if (device == SND_DEVICE_FM_SPEAKER) {
4202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           out_device = FM_SPKR;
4212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           mic_device = HEADSET_MIC;
4222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           LOGD("Stereo FM speaker");
4232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else {
4242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           LOGE("unknown device %d", device);
4252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           return -1;
4262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
4272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
4282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#if 0 //Add for FM support
4292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (out_device == FM_HEADSET ||
4302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        out_device == FM_SPKR) {
4312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (fd_fm_device < 0) {
4322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            fd_fm_device = open("/dev/msm_htc_fm", O_RDWR);
4332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            if (fd_fm_device < 0) {
4342aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                LOGE("Cannot open msm_htc_fm device");
4352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                return -1;
4362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            }
4372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            LOGD("Opened msm_htc_fm for FM radio");
4382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
4392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else if (fd_fm_device >= 0) {
4402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        close(fd_fm_device);
4412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        fd_fm_device = -1;
4422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGD("Closed msm_htc_fm after FM radio");
4432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
4442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland#endif
4452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
4462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    fd = open("/dev/msm_audio_ctl", O_RDWR);
4472aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (fd < 0)        {
4482aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland       LOGE("Cannot open msm_audio_ctl");
4492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland       return -1;
4502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
4512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
4522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (ioctl(fd, AUDIO_SWITCH_DEVICE, &out_device)) {
4532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland       LOGE("Cannot switch audio device");
4542aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland       close(fd);
4552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland       return -1;
4562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
4572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (ioctl(fd, AUDIO_SWITCH_DEVICE, &mic_device)) {
4582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland       LOGE("Cannot switch mic device");
4592aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland       close(fd);
4602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland       return -1;
4612aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
4622aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
4632aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandIncall:
4642aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (inCall == true && !voice_started) {
4652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	if (fd < 0) {
4662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            fd = open("/dev/msm_audio_ctl", O_RDWR);
4672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
4682aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            if (fd < 0) {
4692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                LOGE("Cannot open msm_audio_ctl");
4702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                return -1;
4712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            }
4722aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
4732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (ioctl(fd, AUDIO_START_VOICE, NULL)) {
4742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland               LOGE("Cannot start voice");
4752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland               close(fd);
4762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland               return -1;
4772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
4782aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGD("Voice Started!!");
4792aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        voice_started = 1;
4802aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
4812aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    else if (inCall == false && voice_started) {
4822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (fd < 0) {
4832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            fd = open("/dev/msm_audio_ctl", O_RDWR);
4842aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
4852aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            if (fd < 0) {
4862aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                LOGE("Cannot open msm_audio_ctl");
4872aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                return -1;
4882aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            }
4892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
4902aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (ioctl(fd, AUDIO_STOP_VOICE, NULL)) {
4912aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland               LOGE("Cannot stop voice");
4922aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland               close(fd);
4932aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland               return -1;
4942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
4952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGD("Voice Stopped!!");
4962aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        voice_started = 0;
4972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
4982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
4992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    close(fd);
5002aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
5012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
5022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
5032aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
5042aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland// always call with mutex held
5052aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::doAudioRouteOrMute(uint32_t device)
5062aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
5072aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (support_a1026 == 1)
5082aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        doAudience_A1026_Control(mMode, mRecordState, device);
5092aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
5102aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (device == (uint32_t)SND_DEVICE_BT || device == (uint32_t)SND_DEVICE_CARKIT) {
5112aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (mBluetoothId) {
5122aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            device = mBluetoothId;
5132aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        } else if (!mBluetoothNrec) {
5142aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            device = SND_DEVICE_BT_EC_OFF;
5152aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
5162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
5172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return do_route_audio_dev_ctrl(device, mMode == AudioSystem::MODE_IN_CALL);
5182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
5192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
5202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::get_mMode(void)
5212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
5222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return mMode;
5232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
5242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
5252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::get_mRoutes(void)
5262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
5272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return mRoutes[mMode];
5282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
5292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
5302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::set_mRecordState(bool onoff)
5312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
5322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mRecordState = onoff;
5332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return 0;
5342aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
5352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
5362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::doA1026_init(void)
5372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
5382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    struct a1026img fwimg;
5392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    char *fn = NULL, *path = NULL;
5402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    char char_tmp = 0;
5412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    int rc = 0, count = 0;
5422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    unsigned char local_vpimg_buf[32*1024];
5432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    FILE *fp;
5442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
5452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    fn = "/system/etc/vpimg";
5462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    path = "/dev/audience_a1026";
5472aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
5482aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (fd_a1026 < 0) {
5492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        fd_a1026 = open(path, O_RDWR|O_NONBLOCK, 0);
5502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	if (fd_a1026 < 0) {
5512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland		LOGE("Cannot open %s %d\n", path, fd_a1026);
5522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland		support_a1026 = 0;
5532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland		goto open_drv_err;
5542aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	}
5552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
5562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
5572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    fp = fopen(fn, "rb");
5582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (!fp) {
5592aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGE("Fail to open %s\n", fn);
5602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        goto ld_img_error;
5612aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else LOGI("open %s success\n", fn);
5622aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
5632aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    memset(local_vpimg_buf, 0, sizeof(local_vpimg_buf));
5642aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
5652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    while(!feof(fp)) {
5662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        fread(&char_tmp, sizeof(unsigned char), 1, fp);
5672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        local_vpimg_buf[count++] = char_tmp;
5682aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
5692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    fclose(fp);
5702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
5712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGI("Total %d bytes put to user space buffer.\n", --count);
5722aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    fwimg.buf = local_vpimg_buf;
5732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    fwimg.img_size = count;
5742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
5752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    rc = ioctl(fd_a1026, A1026_BOOTUP_INIT, &fwimg);
5762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (!rc) {
5772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGI("audience_a1026 init OK\n");
5782aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mA1026Init = 1;
5792aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else
5802aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGE("audience_a1026 init failed\n");
5812aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
5822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandld_img_error:
5832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    close(fd_a1026);
5842aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandopen_drv_err:
5852aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    fd_a1026 = -1;
5862aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return rc;
5872aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
5882aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
5892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::get_snd_dev(void)
5907161d052ce69228825bd5deca3bfa4a213a99f06HK Chen
5912aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
5922aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    Mutex::Autolock lock(mLock);
5937161d052ce69228825bd5deca3bfa4a213a99f06HK Chen    return mCurSndDevice;
5942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
5952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
5962aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::doAudience_A1026_Control(int Mode, bool Record, uint32_t Routes)
5972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
5982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    int rc = 0;
5992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
6002aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (!mA1026Init) {
6012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	LOGW("Audience A1026 not initialized.\n");
6022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	return NO_INIT;
6032aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
6042aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
6052aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (fd_a1026 < 0) {
6062aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        fd_a1026 = open("/dev/audience_a1026", O_RDWR);
6072aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (fd_a1026 < 0) {
6082aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            LOGE("Cannot open audience_a1026 device (%d)\n", fd_a1026);
6092aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            return -1;
6102aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	}
6112aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
6122aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
6132aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mA1026Lock.lock();
6142aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
6152aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if ((Mode < AudioSystem::MODE_CURRENT) || (Mode >= AudioSystem::NUM_MODES)) {
6162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGW("Illegal value: doAudience_A1026_Control(%d, %u, %u)", Mode, Record, Routes);
6172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mA1026Lock.unlock();
6182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return BAD_VALUE;
6192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
6202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
6212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (Mode == AudioSystem::MODE_IN_CALL) {
6222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (Record == 1) {
6232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	    switch (Routes) {
6242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        case SND_DEVICE_HANDSET:
6252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        case SND_DEVICE_NO_MIC_HEADSET:
6262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                    new_pathid = A1026_PATH_INCALL_VR_RECEIVER;
6272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                    break;
6282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                case SND_DEVICE_HEADSET:
6292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                case SND_DEVICE_HEADSET_AND_SPEAKER:
6302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                case SND_DEVICE_FM_HEADSET:
6312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                case SND_DEVICE_FM_SPEAKER:
6322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            new_pathid = A1026_PATH_INCALL_VR_HEADSET;
6332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            break;
6342aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        case SND_DEVICE_SPEAKER:
6352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            new_pathid = A1026_PATH_INCALL_VR_SPEAKER;
6362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            break;
6372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        case SND_DEVICE_BT:
6382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        case SND_DEVICE_BT_EC_OFF:
6392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            new_pathid = A1026_PATH_INCALL_VR_BT;
6402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            break;
6412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        default:
6422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            break;
6432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            }
6442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland       } else {
6452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland           switch (Routes) {
6462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        case SND_DEVICE_HANDSET:
6472aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        case SND_DEVICE_NO_MIC_HEADSET:
6482aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                    new_pathid = A1026_PATH_INCALL_RECEIVER; /* NS CT mode, Dual MIC */
6492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                    break;
6502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                case SND_DEVICE_HEADSET:
6512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                case SND_DEVICE_HEADSET_AND_SPEAKER:
6522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                case SND_DEVICE_FM_HEADSET:
6532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                case SND_DEVICE_FM_SPEAKER:
6542aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            new_pathid = A1026_PATH_INCALL_HEADSET; /* NS disable, Headset MIC */
6552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            break;
6562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        case SND_DEVICE_SPEAKER:
6572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            new_pathid = A1026_PATH_INCALL_SPEAKER; /* NS FT mode, Main MIC */
6582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            break;
6592aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        case SND_DEVICE_BT:
6602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        case SND_DEVICE_BT_EC_OFF:
6612aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            new_pathid = A1026_PATH_INCALL_BT; /* QCOM NS, BT MIC */
6622aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            break;
6632aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        default:
6642aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	            break;
6652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            }
6662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland       }
6672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    } else if (Record == 1) {
6682aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        switch (Routes) {
6692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            case SND_DEVICE_HANDSET:
6702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	    case SND_DEVICE_NO_MIC_HEADSET:
6712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                new_pathid = A1026_PATH_RECORD_RECEIVER; /* INT-MIC Recording: NS disable, Main MIC */
6722aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                break;
6732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            case SND_DEVICE_HEADSET:
6742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            case SND_DEVICE_HEADSET_AND_SPEAKER:
6752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            case SND_DEVICE_FM_HEADSET:
6762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            case SND_DEVICE_FM_SPEAKER:
6772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        new_pathid = A1026_PATH_RECORD_HEADSET; /* EXT-MIC Recording: NS disable, Headset MIC */
6782aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        break;
6792aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	    case SND_DEVICE_SPEAKER:
6802aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        new_pathid = A1026_PATH_RECORD_SPEAKER; /* CAM-Coder: NS FT mode, Main MIC */
6812aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        break;
6822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	    case SND_DEVICE_BT:
6832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	    case SND_DEVICE_BT_EC_OFF:
6842aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        new_pathid = A1026_PATH_RECORD_BT; /* BT MIC */
6852aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        break;
6862aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	    default:
6872aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	        break;
6882aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
6892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
6902aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    else {
6912aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        new_pathid = A1026_PATH_SUSPEND;
6922aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
6932aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
6942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (old_pathid != new_pathid) {
6952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        //LOGI("A1026: do ioctl(A1026_SET_CONFIG) to %d\n", new_pathid);
6962aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	rc = ioctl(fd_a1026, A1026_SET_CONFIG, &new_pathid);
6972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	if (!rc)
6982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland		old_pathid = new_pathid;
6992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	else
7002aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland	    goto Error;
7012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
7022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
7032aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandError:
7042aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mA1026Lock.unlock();
7052aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    close(fd_a1026);
7062aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    fd_a1026 = -1;
7072aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
7082aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return rc;
7092aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
7102aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
7112aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
7122aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::doRouting(AudioStreamInMSM72xx *input)
7132aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
7142aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    Mutex::Autolock lock(mLock);
7152aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    uint32_t outputDevices = mOutput->devices();
7162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    status_t ret = NO_ERROR;
7172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    int audProcess = (ADRC_DISABLE | EQ_DISABLE | RX_IIR_DISABLE);
7182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    int sndDevice = -1;
7192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
7202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (input != NULL) {
7212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        uint32_t inputDevice = input->devices();
7222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGI("do input routing device %x\n", inputDevice);
7232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (inputDevice != 0) {
7242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            if (inputDevice & AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
7252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                LOGI("Routing audio to Bluetooth PCM\n");
7262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                sndDevice = SND_DEVICE_BT;
7272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            } else if (inputDevice & AudioSystem::DEVICE_IN_WIRED_HEADSET) {
7282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                if ((outputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) &&
7292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                    (outputDevices & AudioSystem::DEVICE_OUT_SPEAKER)) {
7302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                    LOGI("Routing audio to Wired Headset and Speaker\n");
7312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                    sndDevice = SND_DEVICE_HEADSET_AND_SPEAKER;
7322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                    audProcess = (ADRC_ENABLE | EQ_ENABLE | RX_IIR_ENABLE);
7332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                } else {
7342aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                    LOGI("Routing audio to Wired Headset\n");
7352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                    sndDevice = SND_DEVICE_HEADSET;
7362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                }
7372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            } else {
7382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                if (outputDevices & AudioSystem::DEVICE_OUT_SPEAKER) {
7392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                    LOGI("Routing audio to Speakerphone\n");
7402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                    sndDevice = SND_DEVICE_SPEAKER;
7412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                    audProcess = (ADRC_ENABLE | EQ_ENABLE | RX_IIR_ENABLE);
7422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                } else {
7432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                    LOGI("Routing audio to Handset\n");
7442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                    sndDevice = SND_DEVICE_HANDSET;
7452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                }
7462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            }
7472aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
7482aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        // if inputDevice == 0, restore output routing
7492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
7502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
7512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (sndDevice == -1) {
7522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (outputDevices & (outputDevices - 1)) {
7532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            if ((outputDevices & AudioSystem::DEVICE_OUT_SPEAKER) == 0) {
7542aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                LOGW("Hardware does not support requested route combination (%#X),"
7552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                     " picking closest possible route...", outputDevices);
7562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            }
7572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
7582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
7592aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (outputDevices & AudioSystem::DEVICE_OUT_TTY) {
7602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                LOGI("Routing audio to TTY\n");
7612aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                sndDevice = SND_DEVICE_TTY_FULL;
7622aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        } else if (outputDevices &
7632aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                   (AudioSystem::DEVICE_OUT_BLUETOOTH_SCO | AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET)) {
7642aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            LOGI("Routing audio to Bluetooth PCM\n");
7652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            sndDevice = SND_DEVICE_BT;
7662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        } else if (outputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT) {
7672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            LOGI("Routing audio to Bluetooth PCM\n");
7682aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            sndDevice = SND_DEVICE_CARKIT;
7692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        } else if ((outputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) &&
7702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                   (outputDevices & AudioSystem::DEVICE_OUT_SPEAKER)) {
7712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            LOGI("Routing audio to Wired Headset and Speaker\n");
7722aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            sndDevice = SND_DEVICE_HEADSET_AND_SPEAKER;
7732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            audProcess = (ADRC_ENABLE | EQ_ENABLE | RX_IIR_ENABLE);
7742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        } else if (outputDevices & AudioSystem::DEVICE_OUT_FM_SPEAKER) {
7752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            LOGI("Routing audio to FM Speakerphone (%d,%x)\n", mMode, outputDevices);
7762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            sndDevice = SND_DEVICE_FM_SPEAKER;
7772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            audProcess = (ADRC_ENABLE | EQ_ENABLE | RX_IIR_DISABLE);
7782aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        } else if (outputDevices & AudioSystem::DEVICE_OUT_FM_HEADPHONE) {
7792aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            if (outputDevices & AudioSystem::DEVICE_OUT_SPEAKER) {
7802aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                LOGI("Routing audio to FM Headset and Speaker (%d,%x)\n", mMode, outputDevices);
7812aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                sndDevice = SND_DEVICE_HEADSET_AND_SPEAKER;
7822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                audProcess = (ADRC_ENABLE | EQ_ENABLE | RX_IIR_ENABLE);
7832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            } else {
7842aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                LOGI("Routing audio to FM Headset (%d,%x)\n", mMode, outputDevices);
7852aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                sndDevice = SND_DEVICE_FM_HEADSET;
7862aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            }
7872aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        } else if (outputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE) {
7882aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            if (outputDevices & AudioSystem::DEVICE_OUT_SPEAKER) {
7892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                LOGI("Routing audio to No microphone Wired Headset and Speaker (%d,%x)\n", mMode, outputDevices);
7902aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                sndDevice = SND_DEVICE_HEADSET_AND_SPEAKER;
7912aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                audProcess = (ADRC_ENABLE | EQ_ENABLE | RX_IIR_ENABLE);
7922aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            } else {
7932aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                LOGI("Routing audio to No microphone Wired Headset (%d,%x)\n", mMode, outputDevices);
7942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                sndDevice = SND_DEVICE_NO_MIC_HEADSET;
7952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            }
7962aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        } else if (outputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) {
7972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            LOGI("Routing audio to Wired Headset\n");
7982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            sndDevice = SND_DEVICE_HEADSET;
7992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        } else if (outputDevices & AudioSystem::DEVICE_OUT_SPEAKER) {
8002aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            LOGI("Routing audio to Speakerphone\n");
8012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            sndDevice = SND_DEVICE_SPEAKER;
8022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            audProcess = (ADRC_ENABLE | EQ_ENABLE | RX_IIR_ENABLE);
8032aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        } else {
8042aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            LOGI("Routing audio to Handset\n");
8052aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            sndDevice = SND_DEVICE_HANDSET;
8062aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
8072aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
8082aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
8092aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (sndDevice != -1 && sndDevice != mCurSndDevice) {
8102aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        ret = doAudioRouteOrMute(sndDevice);
8112aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mCurSndDevice = sndDevice;
8122aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
8132aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
8142aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return ret;
8152aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
8162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
8172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::checkMicMute()
8182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
8192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    Mutex::Autolock lock(mLock);
8202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mMode != AudioSystem::MODE_IN_CALL) {
8212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        setMicMute_nosync(true);
8222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
8232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
8242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
8252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
8262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
8272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::dumpInternals(int fd, const Vector<String16>& args)
8282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
8292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    const size_t SIZE = 256;
8302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    char buffer[SIZE];
8312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    String8 result;
8322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append("AudioHardware::dumpInternals\n");
8332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmInit: %s\n", mInit? "true": "false");
8342aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
8352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmMicMute: %s\n", mMicMute? "true": "false");
8362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
8372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmBluetoothNrec: %s\n", mBluetoothNrec? "true": "false");
8382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
8392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmBluetoothId: %d\n", mBluetoothId);
8402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
8412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    ::write(fd, result.string(), result.size());
8422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
8432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
8442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
8452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::dump(int fd, const Vector<String16>& args)
8462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
8472aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    dumpInternals(fd, args);
8482aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    for (size_t index = 0; index < mInputs.size(); index++) {
8492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mInputs[index]->dump(fd, args);
8502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
8512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
8522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mOutput) {
8532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mOutput->dump(fd, args);
8542aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
8552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
8562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
8572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
8582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlanduint32_t AudioHardware::getInputSampleRate(uint32_t sampleRate)
8592aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
8602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    uint32_t i;
8612aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    uint32_t prevDelta;
8622aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    uint32_t delta;
8632aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
8642aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    for (i = 0, prevDelta = 0xFFFFFFFF; i < sizeof(inputSamplingRates)/sizeof(uint32_t); i++, prevDelta = delta) {
8652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        delta = abs(sampleRate - inputSamplingRates[i]);
8662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (delta > prevDelta) break;
8672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
8682aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // i is always > 0 here
8692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return inputSamplingRates[i-1];
8702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
8712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
8722aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland// ----------------------------------------------------------------------------
8732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
8742aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandAudioHardware::AudioStreamOutMSM72xx::AudioStreamOutMSM72xx() :
8752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mHardware(0), mFd(-1), mStartCount(0), mRetryCount(0), mStandby(true), mDevices(0)
8762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
8772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
8782aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
8792aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::AudioStreamOutMSM72xx::set(
8802aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        AudioHardware* hw, uint32_t devices, int *pFormat, uint32_t *pChannels, uint32_t *pRate)
8812aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
8822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    int lFormat = pFormat ? *pFormat : 0;
8832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    uint32_t lChannels = pChannels ? *pChannels : 0;
8842aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    uint32_t lRate = pRate ? *pRate : 0;
8852aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
8862aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mHardware = hw;
8872aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
8882aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // fix up defaults
8892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (lFormat == 0) lFormat = format();
8902aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (lChannels == 0) lChannels = channels();
8912aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (lRate == 0) lRate = sampleRate();
8922aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
8932aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // check values
8942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if ((lFormat != format()) ||
8952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        (lChannels != channels()) ||
8962aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        (lRate != sampleRate())) {
8972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (pFormat) *pFormat = format();
8982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (pChannels) *pChannels = channels();
8992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (pRate) *pRate = sampleRate();
9002aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return BAD_VALUE;
9012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
9022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
9032aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (pFormat) *pFormat = lFormat;
9042aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (pChannels) *pChannels = lChannels;
9052aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (pRate) *pRate = lRate;
9062aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
9072aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mDevices = devices;
9082aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
9092aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
9102aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
9112aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
9122aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandAudioHardware::AudioStreamOutMSM72xx::~AudioStreamOutMSM72xx()
9132aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
9142aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mFd >= 0) close(mFd);
9152aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
9162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
9172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandssize_t AudioHardware::AudioStreamOutMSM72xx::write(const void* buffer, size_t bytes)
9182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
9192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // LOGD("AudioStreamOutMSM72xx::write(%p, %u)", buffer, bytes);
9202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    status_t status = NO_INIT;
9212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    size_t count = bytes;
9222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    const uint8_t* p = static_cast<const uint8_t*>(buffer);
9232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
9242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mStandby) {
9252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
9262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        // open driver
9272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGV("open pcm_out driver");
9282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        status = ::open("/dev/msm_pcm_out", O_RDWR);
9292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (status < 0) {
9302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            if (errCount++ < 10) {
9312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                LOGE("Cannot open /dev/msm_pcm_out errno: %d", errno);
9322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            }
9332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            goto Error;
9342aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
9352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mFd = status;
9362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
9372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        // configuration
9382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGV("get config");
9392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        struct msm_audio_config config;
9402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        status = ioctl(mFd, AUDIO_GET_CONFIG, &config);
9412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (status < 0) {
9422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            LOGE("Cannot read pcm_out config");
9432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            goto Error;
9442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
9452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
9462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGV("set pcm_out config");
9472aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        config.channel_count = AudioSystem::popCount(channels());
9482aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        config.sample_rate = sampleRate();
9492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        config.buffer_size = bufferSize();
9502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        config.buffer_count = AUDIO_HW_NUM_OUT_BUF;
9512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        config.codec_type = CODEC_TYPE_PCM;
9522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        status = ioctl(mFd, AUDIO_SET_CONFIG, &config);
9532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (status < 0) {
9542aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            LOGE("Cannot set config");
9552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            goto Error;
9562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
9572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
9582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGV("buffer_size: %u", config.buffer_size);
9592aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGV("buffer_count: %u", config.buffer_count);
9602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGV("channel_count: %u", config.channel_count);
9612aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGV("sample_rate: %u", config.sample_rate);
9622aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
96331923bb6797ec304d26395acf6d946ab8e44aa6eHK Chen        status = ioctl(mFd, AUDIO_START, 0);
96431923bb6797ec304d26395acf6d946ab8e44aa6eHK Chen        if (status < 0) {
96531923bb6797ec304d26395acf6d946ab8e44aa6eHK Chen            LOGE("Cannot start pcm playback");
96631923bb6797ec304d26395acf6d946ab8e44aa6eHK Chen            goto Error;
9672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
96831923bb6797ec304d26395acf6d946ab8e44aa6eHK Chen        mStandby = false;
9692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
9702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
9712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    while (count) {
9722aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        ssize_t written = ::write(mFd, p, count);
9732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (written >= 0) {
9742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            count -= written;
9752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            p += written;
9762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        } else {
9772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            if (errno != EAGAIN) return written;
9782aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            mRetryCount++;
9792aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            LOGW("EAGAIN - retry");
9802aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
9812aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
9822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
9832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return bytes;
9842aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
9852aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandError:
9862aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mFd >= 0) {
9872aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        ::close(mFd);
9882aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mFd = -1;
9892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
9902aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // Simulate audio output timing in case of error
9912aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    usleep(bytes * 1000000 / frameSize() / sampleRate());
9922aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
9932aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return status;
9942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
9952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
9962aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::AudioStreamOutMSM72xx::standby()
9972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
9982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    status_t status = NO_ERROR;
9992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (!mStandby && mFd >= 0) {
10002aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        ::close(mFd);
10012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mFd = -1;
10022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
10032aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mStandby = true;
10042aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGI("AudioHardware pcm playback is going to standby.");
10052aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return status;
10062aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
10072aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
10082aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::AudioStreamOutMSM72xx::dump(int fd, const Vector<String16>& args)
10092aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
10102aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    const size_t SIZE = 256;
10112aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    char buffer[SIZE];
10122aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    String8 result;
10132aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append("AudioStreamOutMSM72xx::dump\n");
10142aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tsample rate: %d\n", sampleRate());
10152aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
10162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize());
10172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
10182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tchannels: %d\n", channels());
10192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
10202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tformat: %d\n", format());
10212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
10222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmHardware: %p\n", mHardware);
10232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
10242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmFd: %d\n", mFd);
10252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
10262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmStartCount: %d\n", mStartCount);
10272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
10282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmRetryCount: %d\n", mRetryCount);
10292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
10302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmStandby: %s\n", mStandby? "true": "false");
10312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
10322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    ::write(fd, result.string(), result.size());
10332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
10342aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
10352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
10362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandbool AudioHardware::AudioStreamOutMSM72xx::checkStandby()
10372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
10382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return mStandby;
10392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
10402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
10412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
10422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::AudioStreamOutMSM72xx::setParameters(const String8& keyValuePairs)
10432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
10442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    AudioParameter param = AudioParameter(keyValuePairs);
10452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    String8 key = String8(AudioParameter::keyRouting);
10462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    status_t status = NO_ERROR;
10472aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    int device;
10482aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("AudioStreamOutMSM72xx::setParameters() %s", keyValuePairs.string());
10492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
10502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (param.getInt(key, device) == NO_ERROR) {
10512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mDevices = device;
10522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGV("set output routing %x", mDevices);
10532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        status = mHardware->doRouting(NULL);
10542aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        param.remove(key);
10552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
10562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
10572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (param.size()) {
10582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        status = BAD_VALUE;
10592aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
10602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return status;
10612aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
10622aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
10632aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandString8 AudioHardware::AudioStreamOutMSM72xx::getParameters(const String8& keys)
10642aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
10652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    AudioParameter param = AudioParameter(keys);
10662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    String8 value;
10672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    String8 key = String8(AudioParameter::keyRouting);
10682aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
10692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (param.get(key, value) == NO_ERROR) {
10702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGV("get routing %x", mDevices);
10712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        param.addInt(key, (int)mDevices);
10722aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
10732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
10742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("AudioStreamOutMSM72xx::getParameters() %s", param.toString().string());
10752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return param.toString();
10762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
10772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
10782aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
10792aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland// ----------------------------------------------------------------------------
10802aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
10812aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandAudioHardware::AudioStreamInMSM72xx::AudioStreamInMSM72xx() :
10822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mHardware(0), mFd(-1), mState(AUDIO_INPUT_CLOSED), mRetryCount(0),
10832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mFormat(AUDIO_HW_IN_FORMAT), mChannels(AUDIO_HW_IN_CHANNELS),
10842aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mSampleRate(AUDIO_HW_IN_SAMPLERATE), mBufferSize(AUDIO_HW_IN_BUFFERSIZE),
10852aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mAcoustics((AudioSystem::audio_in_acoustics)0), mDevices(0)
10862aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
10872aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
10882aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
10892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::AudioStreamInMSM72xx::set(
10902aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        AudioHardware* hw, uint32_t devices, int *pFormat, uint32_t *pChannels, uint32_t *pRate,
10912aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        AudioSystem::audio_in_acoustics acoustic_flags)
10922aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
10932aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (pFormat == 0 || *pFormat != AUDIO_HW_IN_FORMAT) {
10942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        *pFormat = AUDIO_HW_IN_FORMAT;
10952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return BAD_VALUE;
10962aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
10972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (pRate == 0) {
10982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return BAD_VALUE;
10992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
11002aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    uint32_t rate = hw->getInputSampleRate(*pRate);
11012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (rate != *pRate) {
11022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        *pRate = rate;
11032aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return BAD_VALUE;
11042aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
11052aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
11062aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (pChannels == 0 || (*pChannels != AudioSystem::CHANNEL_IN_MONO &&
11072aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        *pChannels != AudioSystem::CHANNEL_IN_STEREO)) {
11082aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        *pChannels = AUDIO_HW_IN_CHANNELS;
11092aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return BAD_VALUE;
11102aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
11112aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
11122aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mHardware = hw;
11132aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
11142aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("AudioStreamInMSM72xx::set(%d, %d, %u)", *pFormat, *pChannels, *pRate);
11152aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mFd >= 0) {
11162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGE("Audio record already open");
11172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        return -EPERM;
11182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
11192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
11202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // open audio input device
11212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    status_t status = ::open("/dev/msm_pcm_in", O_RDWR);
11222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (status < 0) {
11232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGE("Cannot open /dev/msm_pcm_in errno: %d", errno);
11242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        goto Error;
11252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
11262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mFd = status;
11272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
11282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    // configuration
11292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("get config");
11302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    struct msm_audio_config config;
11312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    status = ioctl(mFd, AUDIO_GET_CONFIG, &config);
11322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (status < 0) {
11332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGE("Cannot read config");
11342aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        goto Error;
11352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
11362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
11372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("set config");
11382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    config.channel_count = AudioSystem::popCount(*pChannels);
11392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    config.sample_rate = *pRate;
11402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    config.buffer_size = bufferSize();
11412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    config.buffer_count = 2;
11422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    config.codec_type = CODEC_TYPE_PCM;
11432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    status = ioctl(mFd, AUDIO_SET_CONFIG, &config);
11442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (status < 0) {
11452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGE("Cannot set config");
11462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (ioctl(mFd, AUDIO_GET_CONFIG, &config) == 0) {
11472aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            if (config.channel_count == 1) {
11482aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                *pChannels = AudioSystem::CHANNEL_IN_MONO;
11492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            } else {
11502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland                *pChannels = AudioSystem::CHANNEL_IN_STEREO;
11512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            }
11522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            *pRate = config.sample_rate;
11532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
11542aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        goto Error;
11552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
11562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
11572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("confirm config");
11582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    status = ioctl(mFd, AUDIO_GET_CONFIG, &config);
11592aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (status < 0) {
11602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGE("Cannot read config");
11612aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        goto Error;
11622aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
11632aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("buffer_size: %u", config.buffer_size);
11642aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("buffer_count: %u", config.buffer_count);
11652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("channel_count: %u", config.channel_count);
11662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("sample_rate: %u", config.sample_rate);
11672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
11682aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mDevices = devices;
11692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mFormat = AUDIO_HW_IN_FORMAT;
11702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mChannels = *pChannels;
11712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mSampleRate = config.sample_rate;
11722aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mBufferSize = config.buffer_size;
11732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
11742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    //mHardware->setMicMute_nosync(false);
11752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    mState = AUDIO_INPUT_OPENED;
11762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
11772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
11782aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
11792aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandError:
11802aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mFd >= 0) {
11812aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        ::close(mFd);
11822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mFd = -1;
11832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
11842aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return status;
11852aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
11862aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
11872aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandAudioHardware::AudioStreamInMSM72xx::~AudioStreamInMSM72xx()
11882aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
11892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("AudioStreamInMSM72xx destructor");
11902aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    standby();
11912aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
11922aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
11932aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandssize_t AudioHardware::AudioStreamInMSM72xx::read( void* buffer, ssize_t bytes)
11942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
11952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("AudioStreamInMSM72xx::read(%p, %ld)", buffer, bytes);
11962aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (!mHardware) return -1;
11972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
11982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    size_t count = bytes;
11992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    uint8_t* p = static_cast<uint8_t*>(buffer);
12002aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
12012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mState < AUDIO_INPUT_OPENED) {
12022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        Mutex::Autolock lock(mHardware->mLock);
12032aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (set(mHardware, mDevices, &mFormat, &mChannels, &mSampleRate, mAcoustics) != NO_ERROR) {
12042aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            return -1;
12052aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
12062aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
12072aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
12082aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (support_a1026 == 1) {
12092aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (mHardware) {
12102aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mHardware->set_mRecordState(1);
12112aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mHardware->doAudience_A1026_Control(mHardware->get_mMode(), 1, mHardware->get_snd_dev());
12122aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
12132aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
12142aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
12152aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mState < AUDIO_INPUT_STARTED) {
12162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (ioctl(mFd, AUDIO_START, 0)) {
12172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            LOGE("Error starting record");
12182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            return -1;
12192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
12202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGI("AUDIO_START: start kernel pcm_in driver.");
12212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mState = AUDIO_INPUT_STARTED;
12222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
12232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
12242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    while (count) {
12252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        ssize_t bytesRead = ::read(mFd, buffer, count);
12262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (bytesRead >= 0) {
12272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            count -= bytesRead;
12282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            p += bytesRead;
12292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        } else {
12302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            if (errno != EAGAIN) return bytesRead;
12312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            mRetryCount++;
12322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            LOGW("EAGAIN - retrying");
12332aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
12342aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
12352aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return bytes;
12362aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
12372aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
12382aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::AudioStreamInMSM72xx::standby()
12392aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
12402aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (support_a1026 == 1) {
12412aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (mHardware) {
12422aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mHardware->set_mRecordState(0);
12432aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mHardware->doAudience_A1026_Control(mHardware->get_mMode(), 0, mHardware->get_snd_dev());
12442aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
12452aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
12462aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
12472aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (!mHardware) return -1;
12482aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (mState > AUDIO_INPUT_CLOSED) {
12492aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (mFd >= 0) {
12502aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            ::close(mFd);
12512aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            mFd = -1;
12522aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
12532aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        //mHardware->checkMicMute();
12542aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        mState = AUDIO_INPUT_CLOSED;
12552aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
12562aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGI("AudioHardware PCM record is going to standby.");
12572aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
12582aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
12592aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
12602aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::AudioStreamInMSM72xx::dump(int fd, const Vector<String16>& args)
12612aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
12622aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    const size_t SIZE = 256;
12632aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    char buffer[SIZE];
12642aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    String8 result;
12652aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append("AudioStreamInMSM72xx::dump\n");
12662aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tsample rate: %d\n", sampleRate());
12672aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
12682aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize());
12692aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
12702aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tchannels: %d\n", channels());
12712aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
12722aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tformat: %d\n", format());
12732aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
12742aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmHardware: %p\n", mHardware);
12752aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
12762aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmFd count: %d\n", mFd);
12772aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
12782aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmState: %d\n", mState);
12792aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
12802aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    snprintf(buffer, SIZE, "\tmRetryCount: %d\n", mRetryCount);
12812aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    result.append(buffer);
12822aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    ::write(fd, result.string(), result.size());
12832aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return NO_ERROR;
12842aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
12852aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
12862aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandstatus_t AudioHardware::AudioStreamInMSM72xx::setParameters(const String8& keyValuePairs)
12872aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
12882aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    AudioParameter param = AudioParameter(keyValuePairs);
12892aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    String8 key = String8(AudioParameter::keyRouting);
12902aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    status_t status = NO_ERROR;
12912aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    int device;
12922aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("AudioStreamInMSM72xx::setParameters() %s", keyValuePairs.string());
12932aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
12942aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (param.getInt(key, device) == NO_ERROR) {
12952aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGV("set input routing %x", device);
12962aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        if (device & (device - 1)) {
12972aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            status = BAD_VALUE;
12982aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        } else {
12992aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            mDevices = device;
13002aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland            status = mHardware->doRouting(this);
13012aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        }
13022aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        param.remove(key);
13032aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
13042aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
13052aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (param.size()) {
13062aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        status = BAD_VALUE;
13072aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
13082aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return status;
13092aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
13102aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
13112aec439308494aa1607e7c1bb32e99863fe32dc6Brian SwetlandString8 AudioHardware::AudioStreamInMSM72xx::getParameters(const String8& keys)
13122aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland{
13132aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    AudioParameter param = AudioParameter(keys);
13142aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    String8 value;
13152aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    String8 key = String8(AudioParameter::keyRouting);
13162aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
13172aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    if (param.get(key, value) == NO_ERROR) {
13182aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        LOGV("get routing %x", mDevices);
13192aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland        param.addInt(key, (int)mDevices);
13202aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    }
13212aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
13222aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    LOGV("AudioStreamInMSM72xx::getParameters() %s", param.toString().string());
13232aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return param.toString();
13242aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
13252aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
13262aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland// ----------------------------------------------------------------------------
13272aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
13282aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetlandextern "C" AudioHardwareInterface* createAudioHardware(void) {
13292aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland    return new AudioHardware();
13302aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}
13312aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland
13322aec439308494aa1607e7c1bb32e99863fe32dc6Brian Swetland}; // namespace android
1333