AudioHardware.cpp revision 63ca66ea9da5ea61806ee547f3aa1c498ac235fe
1a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland/*
2a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland** Copyright 2008, Google Inc.
3a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland**
47510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project** Licensed under the Apache License, Version 2.0 (the "License");
57510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project** you may not use this file except in compliance with the License.
67510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project** You may obtain a copy of the License at
7a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland**
87510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project**     http://www.apache.org/licenses/LICENSE-2.0
9a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland**
107510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project** Unless required by applicable law or agreed to in writing, software
117510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project** distributed under the License is distributed on an "AS IS" BASIS,
127510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project** See the License for the specific language governing permissions and
14a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland** limitations under the License.
15a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland*/
16a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
17a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland#include <math.h>
18a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
197510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project//#define LOG_NDEBUG 0
20a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland#define LOG_TAG "AudioHardwareMSM72XX"
21a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland#include <utils/Log.h>
22a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland#include <utils/String8.h>
23a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
24a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland#include <stdio.h>
25a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland#include <unistd.h>
26a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland#include <sys/ioctl.h>
27a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland#include <sys/types.h>
28a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland#include <sys/stat.h>
29a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland#include <dlfcn.h>
30a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland#include <fcntl.h>
31a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
32a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland// hardware specific functions
33a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
34a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland#include "AudioHardware.h"
359e8b6821afad923dcc616768f7582545c90a0bc6Dave Sparks#include <media/AudioRecord.h>
36a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
37a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland#define LOG_SND_RPC 0  // Set to 1 to log sound RPC's
38a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
39a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandnamespace android {
407510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Projectstatic int audpre_index, tx_iir_index;
417510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Projectstatic void * acoustic;
427510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Projectconst uint32_t AudioHardware::inputSamplingRates[] = {
437510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000
447510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project};
45a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland// ----------------------------------------------------------------------------
46a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
47a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian SwetlandAudioHardware::AudioHardware() :
487510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    mInit(false), mMicMute(true), mBluetoothNrec(true), mBluetoothId(0),
492735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    mOutput(0), mSndEndpoints(NULL), mCurSndDevice(-1),
50a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    SND_DEVICE_CURRENT(-1),
51a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    SND_DEVICE_HANDSET(-1),
527510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    SND_DEVICE_SPEAKER(-1),
53a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    SND_DEVICE_HEADSET(-1),
542735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    SND_DEVICE_BT(-1),
552735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    SND_DEVICE_CARKIT(-1),
562735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    SND_DEVICE_TTY_FULL(-1),
572735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    SND_DEVICE_TTY_VCO(-1),
582735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    SND_DEVICE_TTY_HCO(-1),
592735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    SND_DEVICE_NO_MIC_HEADSET(-1),
602735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    SND_DEVICE_FM_HEADSET(-1),
612735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    SND_DEVICE_HEADSET_AND_SPEAKER(-1),
622735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    SND_DEVICE_FM_SPEAKER(-1),
632735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    SND_DEVICE_BT_EC_OFF(-1)
64a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
65a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
667510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    int (*snd_get_num)();
677510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    int (*snd_get_endpoint)(int, msm_snd_endpoint *);
687510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    int (*set_acoustic_parameters)();
697510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project
707510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    struct msm_snd_endpoint *ept;
717510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project
727510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    acoustic = ::dlopen("/system/lib/libhtc_acoustic.so", RTLD_NOW);
737510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    if (acoustic == NULL ) {
747510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        LOGE("Could not open libhtc_acoustic.so");
75d498a9ce9863bd979d3403473568c6e1e38b7daeBrian Swetland        /* this is not really an error on non-htc devices... */
76d498a9ce9863bd979d3403473568c6e1e38b7daeBrian Swetland        mNumSndEndpoints = 0;
7735f70b5d158659c59981365ecd8e2acfb09b3181Brian Swetland        mInit = true;
787510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        return;
797510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    }
807510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project
817510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    set_acoustic_parameters = (int (*)(void))::dlsym(acoustic, "set_acoustic_parameters");
827510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    if ((*set_acoustic_parameters) == 0 ) {
837510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        LOGE("Could not open set_acoustic_parameters()");
843ccfb0bb4f6f8c18d5b66b5568a9aa1d969a598aIliyan Malchev        return;
853ccfb0bb4f6f8c18d5b66b5568a9aa1d969a598aIliyan Malchev    }
863ccfb0bb4f6f8c18d5b66b5568a9aa1d969a598aIliyan Malchev
877510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    int rc = set_acoustic_parameters();
887510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    if (rc < 0) {
897510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        LOGE("Could not set acoustic parameters to share memory: %d", rc);
907510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project//        return;
917510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    }
927510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project
937510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    snd_get_num = (int (*)(void))::dlsym(acoustic, "snd_get_num_endpoints");
947510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    if ((*snd_get_num) == 0 ) {
957510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        LOGE("Could not open snd_get_num()");
967510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project//        return;
977510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    }
987510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project
997510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    mNumSndEndpoints = snd_get_num();
1007510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    LOGD("mNumSndEndpoints = %d", mNumSndEndpoints);
1017510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    mSndEndpoints = new msm_snd_endpoint[mNumSndEndpoints];
1027510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    mInit = true;
1037510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    LOGV("constructed %d SND endpoints)", mNumSndEndpoints);
1047510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    ept = mSndEndpoints;
1057510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    snd_get_endpoint = (int (*)(int, msm_snd_endpoint *))::dlsym(acoustic, "snd_get_endpoint");
1067510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    if ((*snd_get_endpoint) == 0 ) {
1077510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        LOGE("Could not open snd_get_endpoint()");
1087510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        return;
1097510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    }
1107510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project
1117510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    for (int cnt = 0; cnt < mNumSndEndpoints; cnt++, ept++) {
1127510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        ept->id = cnt;
1137510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        snd_get_endpoint(cnt, ept);
1147510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project#define CHECK_FOR(desc) \
1157510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        if (!strcmp(ept->name, #desc)) { \
1167510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project            SND_DEVICE_##desc = ept->id; \
1177510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project            LOGD("BT MATCH " #desc); \
1187510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        } else
1197510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        CHECK_FOR(CURRENT)
1207510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        CHECK_FOR(HANDSET)
1217510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        CHECK_FOR(SPEAKER)
1227510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        CHECK_FOR(BT)
1237510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        CHECK_FOR(BT_EC_OFF)
1247510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        CHECK_FOR(HEADSET)
1252735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        CHECK_FOR(CARKIT)
1262735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        CHECK_FOR(TTY_FULL)
1272735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        CHECK_FOR(TTY_VCO)
1282735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        CHECK_FOR(TTY_HCO)
1292735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        CHECK_FOR(NO_MIC_HEADSET)
1302735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        CHECK_FOR(FM_HEADSET)
1312735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        CHECK_FOR(FM_SPEAKER)
1327510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        CHECK_FOR(HEADSET_AND_SPEAKER) {}
133a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland#undef CHECK_FOR
134a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
135a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
136a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
137a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian SwetlandAudioHardware::~AudioHardware()
138a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
1392735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    for (size_t index = 0; index < mInputs.size(); index++) {
1402735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        closeInputStream((AudioStreamIn*)mInputs[index]);
1412735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    }
1422735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    mInputs.clear();
1432735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    closeOutputStream((AudioStreamOut*)mOutput);
144a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    delete [] mSndEndpoints;
145d498a9ce9863bd979d3403473568c6e1e38b7daeBrian Swetland    if (acoustic) {
146d498a9ce9863bd979d3403473568c6e1e38b7daeBrian Swetland        ::dlclose(acoustic);
147d498a9ce9863bd979d3403473568c6e1e38b7daeBrian Swetland        acoustic = 0;
148d498a9ce9863bd979d3403473568c6e1e38b7daeBrian Swetland    }
149a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    mInit = false;
150a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
151a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
152a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatus_t AudioHardware::initCheck()
153a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
154a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    return mInit ? NO_ERROR : NO_INIT;
155a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
156a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
157a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian SwetlandAudioStreamOut* AudioHardware::openOutputStream(
1582735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status)
159a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
1602735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    { // scope for the lock
1612735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        Mutex::Autolock lock(mLock);
162a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
1632735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        // only one output stream allowed
1642735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        if (mOutput) {
1652735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent            if (status) {
1662735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent                *status = INVALID_OPERATION;
1672735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent            }
1682735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent            return 0;
1697510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        }
170a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
1712735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        // create new output stream
1722735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        AudioStreamOutMSM72xx* out = new AudioStreamOutMSM72xx();
1732735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        status_t lStatus = out->set(this, devices, format, channels, sampleRate);
1742735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        if (status) {
1752735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent            *status = lStatus;
1762735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        }
1772735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        if (lStatus == NO_ERROR) {
1782735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent            mOutput = out;
1792735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        } else {
1802735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent            delete out;
1812735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        }
182a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
183a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    return mOutput;
184a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
185a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
1862735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurentvoid AudioHardware::closeOutputStream(AudioStreamOut* out) {
187a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    Mutex::Autolock lock(mLock);
1882735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    if (mOutput == 0 || mOutput != out) {
189a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        LOGW("Attempt to close invalid output stream");
190a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
191a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    else {
1922735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        delete mOutput;
193a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        mOutput = 0;
194a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
195a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
196a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
197a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian SwetlandAudioStreamIn* AudioHardware::openInputStream(
1982735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status,
1992735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        AudioSystem::audio_in_acoustics acoustic_flags)
200a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
2019e8b6821afad923dcc616768f7582545c90a0bc6Dave Sparks    // check for valid input source
2022735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    if (!AudioSystem::isInputDevice((AudioSystem::audio_devices)devices)) {
2039e8b6821afad923dcc616768f7582545c90a0bc6Dave Sparks        return 0;
2049e8b6821afad923dcc616768f7582545c90a0bc6Dave Sparks    }
2059e8b6821afad923dcc616768f7582545c90a0bc6Dave Sparks
2067510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    mLock.lock();
207a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
208a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    AudioStreamInMSM72xx* in = new AudioStreamInMSM72xx();
2092735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    status_t lStatus = in->set(this, devices, format, channels, sampleRate, acoustic_flags);
2107510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    if (status) {
2117510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        *status = lStatus;
2127510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    }
2137510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    if (lStatus != NO_ERROR) {
2147510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        mLock.unlock();
215a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        delete in;
216a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        return 0;
217a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
218a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
2192735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    mInputs.add(in);
2207510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    mLock.unlock();
2217510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project
2222735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    return in;
223a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
224a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
2252735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurentvoid AudioHardware::closeInputStream(AudioStreamIn* in) {
226a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    Mutex::Autolock lock(mLock);
2272735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent
2282735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    ssize_t index = mInputs.indexOf((AudioStreamInMSM72xx *)in);
2292735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    if (index < 0) {
230a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        LOGW("Attempt to close invalid input stream");
2312735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    } else {
2322735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        mLock.unlock();
2332735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        delete mInputs[index];
2342735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        mLock.lock();
2352735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        mInputs.removeAt(index);
236a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
237a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
238a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
23963ca66ea9da5ea61806ee547f3aa1c498ac235feEric Laurentstatus_t AudioHardware::setMode(int mode)
24063ca66ea9da5ea61806ee547f3aa1c498ac235feEric Laurent{
24163ca66ea9da5ea61806ee547f3aa1c498ac235feEric Laurent    status_t status = AudioHardwareBase::setMode(mode);
24263ca66ea9da5ea61806ee547f3aa1c498ac235feEric Laurent    if (status == NO_ERROR) {
24363ca66ea9da5ea61806ee547f3aa1c498ac235feEric Laurent        // make sure that doAudioRouteOrMute() is called by doRouting()
24463ca66ea9da5ea61806ee547f3aa1c498ac235feEric Laurent        // even if the new device selected is the same as current one.
24563ca66ea9da5ea61806ee547f3aa1c498ac235feEric Laurent        mCurSndDevice = -1;
24663ca66ea9da5ea61806ee547f3aa1c498ac235feEric Laurent    }
24763ca66ea9da5ea61806ee547f3aa1c498ac235feEric Laurent    return status;
24863ca66ea9da5ea61806ee547f3aa1c498ac235feEric Laurent}
24963ca66ea9da5ea61806ee547f3aa1c498ac235feEric Laurent
2507510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Projectbool AudioHardware::checkOutputStandby()
251a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
2527510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    if (mOutput)
2537510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        if (!mOutput->checkStandby())
2547510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project            return false;
255a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
2567510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    return true;
257a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
258a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
259a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatus_t AudioHardware::setMicMute(bool state)
260a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
261a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    Mutex::Autolock lock(mLock);
262a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    return setMicMute_nosync(state);
263a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
264a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
265a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland// always call with mutex held
266a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatus_t AudioHardware::setMicMute_nosync(bool state)
267a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
268a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    if (mMicMute != state) {
269a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        mMicMute = state;
270a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        return doAudioRouteOrMute(SND_DEVICE_CURRENT);
271a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
272a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    return NO_ERROR;
273a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
274a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
275a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatus_t AudioHardware::getMicMute(bool* state)
276a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
277a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    *state = mMicMute;
278a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    return NO_ERROR;
279a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
280a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
2812735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurentstatus_t AudioHardware::setParameters(const String8& keyValuePairs)
282a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
2832735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    AudioParameter param = AudioParameter(keyValuePairs);
2842735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    String8 value;
2852735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    String8 key;
286a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    const char BT_NREC_KEY[] = "bt_headset_nrec";
287a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    const char BT_NAME_KEY[] = "bt_headset_name";
288a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    const char BT_NREC_VALUE_ON[] = "on";
289a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
2902735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent
2912735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    LOGV("setParameters() %s", keyValuePairs.string());
2922735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent
2932735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    if (keyValuePairs.length() == 0) return BAD_VALUE;
2942735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent
2952735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    key = String8(BT_NREC_KEY);
2962735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    if (param.get(key, value) == NO_ERROR) {
2972735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        if (value == BT_NREC_VALUE_ON) {
298a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            mBluetoothNrec = true;
299a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        } else {
300a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            mBluetoothNrec = false;
301a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            LOGI("Turning noise reduction and echo cancellation off for BT "
302a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland                 "headset");
303a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        }
3042735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    }
3052735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    key = String8(BT_NAME_KEY);
3062735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    if (param.get(key, value) == NO_ERROR) {
307a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        mBluetoothId = 0;
3087510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        for (int i = 0; i < mNumSndEndpoints; i++) {
3092735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent            if (!strcasecmp(value.string(), mSndEndpoints[i].name)) {
3107510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project                mBluetoothId = mSndEndpoints[i].id;
3112735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent                LOGI("Using custom acoustic parameters for %s", value.string());
312a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland                break;
313a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            }
314a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        }
315a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        if (mBluetoothId == 0) {
316a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            LOGI("Using default acoustic parameters "
3172735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent                 "(%s not in acoustic database)", value.string());
3182735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent            doRouting(NULL);
319a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        }
320a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
321a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    return NO_ERROR;
322a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
3232735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent
3242735e3b55bdaf33cfd0dbaa1b914231243933e92Eric LaurentString8 AudioHardware::getParameters(const String8& keys)
3252735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent{
326ba77ed6e3c6006d2797867f14ffd01e99cafc03bEric Laurent    AudioParameter param = AudioParameter(keys);
327ba77ed6e3c6006d2797867f14ffd01e99cafc03bEric Laurent    return param.toString();
3282735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent}
3292735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent
3302735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent
3317510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Projectstatic unsigned calculate_audpre_table_index(unsigned index)
332a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
3337510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    switch (index) {
3347510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        case 48000:    return SAMP_RATE_INDX_48000;
3357510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        case 44100:    return SAMP_RATE_INDX_44100;
3367510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        case 32000:    return SAMP_RATE_INDX_32000;
3377510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        case 24000:    return SAMP_RATE_INDX_24000;
3387510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        case 22050:    return SAMP_RATE_INDX_22050;
3397510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        case 16000:    return SAMP_RATE_INDX_16000;
3407510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        case 12000:    return SAMP_RATE_INDX_12000;
3417510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        case 11025:    return SAMP_RATE_INDX_11025;
3427510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        case 8000:    return SAMP_RATE_INDX_8000;
3437510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        default:     return -1;
344a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
345a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
3467510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Projectsize_t AudioHardware::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
347a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
3487510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    if (format != AudioSystem::PCM_16_BIT) {
3497510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        LOGW("getInputBufferSize bad format: %d", format);
3507510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        return 0;
351a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
3527510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    if (channelCount < 1 || channelCount > 2) {
3537510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        LOGW("getInputBufferSize bad channel count: %d", channelCount);
3547510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        return 0;
355a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
356a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
3577510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    return 2048*channelCount;
358a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
359a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
360a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatic status_t set_volume_rpc(uint32_t device,
361a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland                               uint32_t method,
362a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland                               uint32_t volume)
363a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
364a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    int fd;
365a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland#if LOG_SND_RPC
366a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    LOGD("rpc_snd_set_volume(%d, %d, %d)\n", device, method, volume);
367a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland#endif
368a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
369a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    if (device == -1UL) return NO_ERROR;
370a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
371a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    fd = open("/dev/msm_snd", O_RDWR);
372a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    if (fd < 0) {
373a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        LOGE("Can not open snd device");
374a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        return -EPERM;
375a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
376a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    /* rpc_snd_set_volume(
377a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland     *     device,            # Any hardware device enum, including
378a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland     *                        # SND_DEVICE_CURRENT
379a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland     *     method,            # must be SND_METHOD_VOICE to do anything useful
380a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland     *     volume,            # integer volume level, in range [0,5].
381a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland     *                        # note that 0 is audible (not quite muted)
382a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland     *  )
383a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland     * rpc_snd_set_volume only works for in-call sound volume.
384a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland     */
3857510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project     struct msm_snd_volume_config args;
3867510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project     args.device = device;
3877510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project     args.method = method;
3887510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project     args.volume = volume;
389a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
3907510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project     if (ioctl(fd, SND_SET_VOLUME, &args) < 0) {
3917510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project         LOGE("snd_set_volume error.");
3927510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project         close(fd);
3937510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project         return -EIO;
3947510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project     }
3957510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project     close(fd);
3967510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project     return NO_ERROR;
397a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
398a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
399a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatus_t AudioHardware::setVoiceVolume(float v)
400a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
401a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    if (v < 0.0) {
402a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        LOGW("setVoiceVolume(%f) under 0.0, assuming 0.0\n", v);
403a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        v = 0.0;
404a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    } else if (v > 1.0) {
405a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        LOGW("setVoiceVolume(%f) over 1.0, assuming 1.0\n", v);
406a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        v = 1.0;
407a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
408a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
409a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    int vol = lrint(v * 5.0);
410a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    LOGD("setVoiceVolume(%f)\n", v);
411a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    LOGI("Setting in-call volume to %d (available range is 0 to 5)\n", vol);
412a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
413d066973de83218a24c773e5de04d10ed2d730873Eric Laurent    Mutex::Autolock lock(mLock);
414a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    set_volume_rpc(SND_DEVICE_CURRENT, SND_METHOD_VOICE, vol);
415a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    return NO_ERROR;
416a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
417a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
418a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatus_t AudioHardware::setMasterVolume(float v)
419a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
420a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    Mutex::Autolock lock(mLock);
421a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    int vol = ceil(v * 5.0);
422a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    LOGI("Set master volume to %d.\n", vol);
4232735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    /*
424a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    set_volume_rpc(SND_DEVICE_HANDSET, SND_METHOD_VOICE, vol);
425a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    set_volume_rpc(SND_DEVICE_SPEAKER, SND_METHOD_VOICE, vol);
426a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    set_volume_rpc(SND_DEVICE_BT,      SND_METHOD_VOICE, vol);
427a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    set_volume_rpc(SND_DEVICE_HEADSET, SND_METHOD_VOICE, vol);
4282735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    */
429a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    // We return an error code here to let the audioflinger do in-software
430a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    // volume on top of the maximum volume that we set through the SND API.
431a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    // return error - software mixer will handle it
432a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    return -1;
433a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
434a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
435a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatic status_t do_route_audio_rpc(uint32_t device,
436a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland                                   bool ear_mute, bool mic_mute)
437a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
438a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    if (device == -1UL)
439a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        return NO_ERROR;
440a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
441a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    int fd;
442a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland#if LOG_SND_RPC
443a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    LOGD("rpc_snd_set_device(%d, %d, %d)\n", device, ear_mute, mic_mute);
444a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland#endif
445a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
446a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    fd = open("/dev/msm_snd", O_RDWR);
447a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    if (fd < 0) {
448a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        LOGE("Can not open snd device");
449a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        return -EPERM;
450a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
451a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    // RPC call to switch audio path
452a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    /* rpc_snd_set_device(
453a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland     *     device,            # Hardware device enum to use
454a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland     *     ear_mute,          # Set mute for outgoing voice audio
455a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland     *                        # this should only be unmuted when in-call
456a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland     *     mic_mute,          # Set mute for incoming voice audio
457a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland     *                        # this should only be unmuted when in-call or
458a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland     *                        # recording.
459a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland     *  )
460a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland     */
4613ccfb0bb4f6f8c18d5b66b5568a9aa1d969a598aIliyan Malchev    struct msm_snd_device_config args;
462a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    args.device = device;
463a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    args.ear_mute = ear_mute ? SND_MUTE_MUTED : SND_MUTE_UNMUTED;
464a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    args.mic_mute = mic_mute ? SND_MUTE_MUTED : SND_MUTE_UNMUTED;
465a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
466a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    if (ioctl(fd, SND_SET_DEVICE, &args) < 0) {
467a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        LOGE("snd_set_device error.");
468a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        close(fd);
469a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        return -EIO;
470a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
471a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
472a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    close(fd);
473a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    return NO_ERROR;
474a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
475a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
476a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland// always call with mutex held
477a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatus_t AudioHardware::doAudioRouteOrMute(uint32_t device)
478a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
47916327daa90dffd97f03d24c59ec0a4d38aa94b90Eric Laurent    if (device == (uint32_t)SND_DEVICE_BT || device == (uint32_t)SND_DEVICE_CARKIT) {
480a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        if (mBluetoothId) {
481a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            device = mBluetoothId;
482a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        } else if (!mBluetoothNrec) {
483a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            device = SND_DEVICE_BT_EC_OFF;
484a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        }
485a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
4862735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    LOGV("doAudioRouteOrMute() device %x, mMode %d, mMicMute %d", device, mMode, mMicMute);
487a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    return do_route_audio_rpc(device,
4887510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project                              mMode != AudioSystem::MODE_IN_CALL, mMicMute);
489a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
490a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
4912735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurentstatus_t AudioHardware::doRouting(AudioStreamInMSM72xx *input)
492a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
493d498a9ce9863bd979d3403473568c6e1e38b7daeBrian Swetland    /* currently this code doesn't work without the htc libacoustic */
494d498a9ce9863bd979d3403473568c6e1e38b7daeBrian Swetland    if (!acoustic)
495d498a9ce9863bd979d3403473568c6e1e38b7daeBrian Swetland        return 0;
496d498a9ce9863bd979d3403473568c6e1e38b7daeBrian Swetland
497a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    Mutex::Autolock lock(mLock);
4982735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    uint32_t outputDevices = mOutput->devices();
4992735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    status_t ret = NO_ERROR;
5007510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    int (*msm72xx_enable_audpp)(int);
5017510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    msm72xx_enable_audpp = (int (*)(int))::dlsym(acoustic, "msm72xx_enable_audpp");
5022735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    int audProcess = (ADRC_DISABLE | EQ_DISABLE | RX_IIR_DISABLE);
5032735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    int sndDevice = -1;
5042735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent
5052735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    if (input != NULL) {
5062735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        uint32_t inputDevice = input->devices();
5072735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        LOGI("do input routing device %x\n", inputDevice);
5082735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        if (inputDevice != 0) {
5092735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent            if (inputDevice & AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
5102735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent                LOGI("Routing audio to Bluetooth PCM\n");
5112735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent                sndDevice = SND_DEVICE_BT;
5122735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent            } else if (inputDevice & AudioSystem::DEVICE_IN_WIRED_HEADSET) {
5132735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent                if ((outputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) &&
5142735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent                    (outputDevices & AudioSystem::DEVICE_OUT_SPEAKER)) {
5152735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent                    LOGI("Routing audio to Wired Headset and Speaker\n");
5162735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent                    sndDevice = SND_DEVICE_HEADSET_AND_SPEAKER;
5172735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent                    audProcess = (ADRC_ENABLE | EQ_ENABLE | RX_IIR_ENABLE);
5182735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent                } else {
5192735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent                    LOGI("Routing audio to Wired Headset\n");
5202735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent                    sndDevice = SND_DEVICE_HEADSET;
5212735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent                }
5222735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent            } else {
5232735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent                if (outputDevices & AudioSystem::DEVICE_OUT_SPEAKER) {
5242735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent                    LOGI("Routing audio to Speakerphone\n");
5252735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent                    sndDevice = SND_DEVICE_SPEAKER;
5262735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent                    audProcess = (ADRC_ENABLE | EQ_ENABLE | RX_IIR_ENABLE);
5272735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent                } else {
5282735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent                    LOGI("Routing audio to Handset\n");
5292735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent                    sndDevice = SND_DEVICE_HANDSET;
5302735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent                }
5312735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent            }
5322735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        }
5332735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        // if inputDevice == 0, restore output routing
5342735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    }
5352735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent
5362735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    if (sndDevice == -1) {
5372735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        if (outputDevices & (outputDevices - 1)) {
5382735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent            if ((outputDevices & AudioSystem::DEVICE_OUT_SPEAKER) == 0) {
5392735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent                LOGW("Hardware does not support requested route combination (%#X),"
5402735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent                     " picking closest possible route...", outputDevices);
5412735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent            }
5422735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        }
5432735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent
5442735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        if (outputDevices & AudioSystem::DEVICE_OUT_TTY) {
5452735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent                LOGI("Routing audio to TTY\n");
5462735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent                sndDevice = SND_DEVICE_TTY_FULL;
54716327daa90dffd97f03d24c59ec0a4d38aa94b90Eric Laurent        } else if (outputDevices &
54816327daa90dffd97f03d24c59ec0a4d38aa94b90Eric Laurent                   (AudioSystem::DEVICE_OUT_BLUETOOTH_SCO | AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_HEADSET)) {
5492735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent            LOGI("Routing audio to Bluetooth PCM\n");
5502735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent            sndDevice = SND_DEVICE_BT;
55116327daa90dffd97f03d24c59ec0a4d38aa94b90Eric Laurent        } else if (outputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT) {
55216327daa90dffd97f03d24c59ec0a4d38aa94b90Eric Laurent            LOGI("Routing audio to Bluetooth PCM\n");
55316327daa90dffd97f03d24c59ec0a4d38aa94b90Eric Laurent            sndDevice = SND_DEVICE_CARKIT;
5542735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        } else if ((outputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) &&
5552735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent                   (outputDevices & AudioSystem::DEVICE_OUT_SPEAKER)) {
5562735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent            LOGI("Routing audio to Wired Headset and Speaker\n");
5572735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent            sndDevice = SND_DEVICE_HEADSET_AND_SPEAKER;
5582735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent            audProcess = (ADRC_ENABLE | EQ_ENABLE | RX_IIR_ENABLE);
5592735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        } else if (outputDevices & AudioSystem::DEVICE_OUT_FM_SPEAKER) {
5602735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent            LOGI("Routing audio to FM Speakerphone (%d,%x)\n", mMode, outputDevices);
5612735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent            sndDevice = SND_DEVICE_FM_SPEAKER;
5622735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent            audProcess = (ADRC_ENABLE | EQ_ENABLE | RX_IIR_DISABLE);
5632735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        } else if (outputDevices & AudioSystem::DEVICE_OUT_FM_HEADPHONE) {
5642735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent            if (outputDevices & AudioSystem::DEVICE_OUT_SPEAKER) {
5652735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent                LOGI("Routing audio to FM Headset and Speaker (%d,%x)\n", mMode, outputDevices);
5662735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent                sndDevice = SND_DEVICE_HEADSET_AND_SPEAKER;
5672735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent                audProcess = (ADRC_ENABLE | EQ_ENABLE | RX_IIR_ENABLE);
5682735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent            } else {
5692735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent                LOGI("Routing audio to FM Headset (%d,%x)\n", mMode, outputDevices);
57016327daa90dffd97f03d24c59ec0a4d38aa94b90Eric Laurent                sndDevice = SND_DEVICE_FM_HEADSET;
5712735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent            }
5722735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        } else if (outputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADPHONE) {
5732735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent            if (outputDevices & AudioSystem::DEVICE_OUT_SPEAKER) {
5742735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent                LOGI("Routing audio to No microphone Wired Headset and Speaker (%d,%x)\n", mMode, outputDevices);
5752735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent                sndDevice = SND_DEVICE_HEADSET_AND_SPEAKER;
5762735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent                audProcess = (ADRC_ENABLE | EQ_ENABLE | RX_IIR_ENABLE);
5772735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent            } else {
5782735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent                LOGI("Routing audio to No microphone Wired Headset (%d,%x)\n", mMode, outputDevices);
5792735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent                sndDevice = SND_DEVICE_NO_MIC_HEADSET;
5802735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent            }
5812735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        } else if (outputDevices & AudioSystem::DEVICE_OUT_WIRED_HEADSET) {
5822735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent            LOGI("Routing audio to Wired Headset\n");
5832735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent            sndDevice = SND_DEVICE_HEADSET;
5842735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        } else if (outputDevices & AudioSystem::DEVICE_OUT_SPEAKER) {
5852735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent            LOGI("Routing audio to Speakerphone\n");
5862735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent            sndDevice = SND_DEVICE_SPEAKER;
5872735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent            audProcess = (ADRC_ENABLE | EQ_ENABLE | RX_IIR_ENABLE);
5882735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        } else {
5892735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent            LOGI("Routing audio to Handset\n");
5902735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent            sndDevice = SND_DEVICE_HANDSET;
5912735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        }
5922735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    }
5932735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent
5942735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    if (sndDevice != -1 && sndDevice != mCurSndDevice) {
5952735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        ret = doAudioRouteOrMute(sndDevice);
5962735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        if ((*msm72xx_enable_audpp) == 0 ) {
5972735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent            LOGE("Could not open msm72xx_enable_audpp()");
5982735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        } else {
5992735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent            msm72xx_enable_audpp(audProcess);
6002735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        }
6012735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        mCurSndDevice = sndDevice;
602a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
603a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
604a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    return ret;
605a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
606a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
607a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatus_t AudioHardware::checkMicMute()
608a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
609a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    Mutex::Autolock lock(mLock);
610a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    if (mMode != AudioSystem::MODE_IN_CALL) {
611a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        setMicMute_nosync(true);
612a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
6137510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project
614a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    return NO_ERROR;
615a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
616a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
617a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatus_t AudioHardware::dumpInternals(int fd, const Vector<String16>& args)
618a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
619a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    const size_t SIZE = 256;
620a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    char buffer[SIZE];
621a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    String8 result;
622a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    result.append("AudioHardware::dumpInternals\n");
623a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    snprintf(buffer, SIZE, "\tmInit: %s\n", mInit? "true": "false");
624a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    result.append(buffer);
625a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    snprintf(buffer, SIZE, "\tmMicMute: %s\n", mMicMute? "true": "false");
626a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    result.append(buffer);
627a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    snprintf(buffer, SIZE, "\tmBluetoothNrec: %s\n", mBluetoothNrec? "true": "false");
628a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    result.append(buffer);
629a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    snprintf(buffer, SIZE, "\tmBluetoothId: %d\n", mBluetoothId);
630a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    result.append(buffer);
631a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    ::write(fd, result.string(), result.size());
632a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    return NO_ERROR;
633a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
634a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
635a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatus_t AudioHardware::dump(int fd, const Vector<String16>& args)
636a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
637a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    dumpInternals(fd, args);
6382735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    for (size_t index = 0; index < mInputs.size(); index++) {
6392735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        mInputs[index]->dump(fd, args);
640a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
6412735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent
642a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    if (mOutput) {
643a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        mOutput->dump(fd, args);
644a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
645a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    return NO_ERROR;
646a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
647a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
6482735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurentuint32_t AudioHardware::getInputSampleRate(uint32_t sampleRate)
6497510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project{
6502735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    uint32_t i;
6512735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    uint32_t prevDelta;
6522735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    uint32_t delta;
6532735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent
6542735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    for (i = 0, prevDelta = 0xFFFFFFFF; i < sizeof(inputSamplingRates)/sizeof(uint32_t); i++, prevDelta = delta) {
6552735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        delta = abs(sampleRate - inputSamplingRates[i]);
6562735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        if (delta > prevDelta) break;
6577510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    }
6582735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    // i is always > 0 here
6592735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    return inputSamplingRates[i-1];
6607510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project}
6617510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project
662a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland// ----------------------------------------------------------------------------
663a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
664a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian SwetlandAudioHardware::AudioStreamOutMSM72xx::AudioStreamOutMSM72xx() :
6652735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    mHardware(0), mFd(-1), mStartCount(0), mRetryCount(0), mStandby(true), mDevices(0)
666a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
667a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
668a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
669a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatus_t AudioHardware::AudioStreamOutMSM72xx::set(
6702735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        AudioHardware* hw, uint32_t devices, int *pFormat, uint32_t *pChannels, uint32_t *pRate)
671a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
6722735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    int lFormat = pFormat ? *pFormat : 0;
6732735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    uint32_t lChannels = pChannels ? *pChannels : 0;
6742735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    uint32_t lRate = pRate ? *pRate : 0;
6752735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent
6762735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    mHardware = hw;
6772735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent
678a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    // fix up defaults
6792735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    if (lFormat == 0) lFormat = format();
6802735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    if (lChannels == 0) lChannels = channels();
6812735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    if (lRate == 0) lRate = sampleRate();
682a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
683a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    // check values
6842735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    if ((lFormat != format()) ||
6852735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        (lChannels != channels()) ||
6862735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        (lRate != sampleRate())) {
6872735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        if (pFormat) *pFormat = format();
6882735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        if (pChannels) *pChannels = channels();
6892735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        if (pRate) *pRate = sampleRate();
690a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        return BAD_VALUE;
6912735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    }
692a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
6932735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    if (pFormat) *pFormat = lFormat;
6942735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    if (pChannels) *pChannels = lChannels;
6952735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    if (pRate) *pRate = lRate;
6962735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent
6972735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    mDevices = devices;
698a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
699a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    return NO_ERROR;
700a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
701a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
702a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian SwetlandAudioHardware::AudioStreamOutMSM72xx::~AudioStreamOutMSM72xx()
703a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
7047510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    if (mFd > 0) close(mFd);
705a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
706a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
707a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandssize_t AudioHardware::AudioStreamOutMSM72xx::write(const void* buffer, size_t bytes)
708a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
709a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    // LOGD("AudioStreamOutMSM72xx::write(%p, %u)", buffer, bytes);
710a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    status_t status = NO_INIT;
711a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    size_t count = bytes;
712a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    const uint8_t* p = static_cast<const uint8_t*>(buffer);
713a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
7147510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    if (mStandby) {
715a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
716a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        // open driver
717a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        LOGV("open driver");
718a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        status = ::open("/dev/msm_pcm_out", O_RDWR);
719a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        if (status < 0) {
7207510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project            LOGE("Cannot open /dev/msm_pcm_out errno: %d", errno);
721a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            goto Error;
722a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        }
723a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        mFd = status;
724a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
725a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        // configuration
726a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        LOGV("get config");
727a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        struct msm_audio_config config;
728a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        status = ioctl(mFd, AUDIO_GET_CONFIG, &config);
729a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        if (status < 0) {
730a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            LOGE("Cannot read config");
731a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            goto Error;
732a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        }
733a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
734a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        LOGV("set config");
7352735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        config.channel_count = AudioSystem::popCount(channels());
736a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        config.sample_rate = sampleRate();
737a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        config.buffer_size = bufferSize();
7387510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        config.buffer_count = AUDIO_HW_NUM_OUT_BUF;
739a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        config.codec_type = CODEC_TYPE_PCM;
740a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        status = ioctl(mFd, AUDIO_SET_CONFIG, &config);
741a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        if (status < 0) {
742a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            LOGE("Cannot set config");
743a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            goto Error;
744a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        }
745a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
746a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        LOGV("buffer_size: %u", config.buffer_size);
747a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        LOGV("buffer_count: %u", config.buffer_count);
748a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        LOGV("channel_count: %u", config.channel_count);
749a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        LOGV("sample_rate: %u", config.sample_rate);
750a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
751a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        // fill 2 buffers before AUDIO_START
7527510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        mStartCount = AUDIO_HW_NUM_OUT_BUF;
7537510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        mStandby = false;
754a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
755a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
756a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    while (count) {
757a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        ssize_t written = ::write(mFd, p, count);
758a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        if (written >= 0) {
759a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            count -= written;
760a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            p += written;
761a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        } else {
762a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            if (errno != EAGAIN) return written;
763a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            mRetryCount++;
764a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            LOGW("EAGAIN - retry");
765a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        }
766a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
767a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
768a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    // start audio after we fill 2 buffers
769a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    if (mStartCount) {
770a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        if (--mStartCount == 0) {
771a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            ioctl(mFd, AUDIO_START, 0);
772a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        }
773a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
774a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    return bytes;
775a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
776a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian SwetlandError:
777a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    if (mFd > 0) {
778a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        ::close(mFd);
779a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        mFd = -1;
780a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
781a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    // Simulate audio output timing in case of error
7827510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    usleep(bytes * 1000000 / frameSize() / sampleRate());
783a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
784a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    return status;
785a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
786a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
787a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatus_t AudioHardware::AudioStreamOutMSM72xx::standby()
788a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
789a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    status_t status = NO_ERROR;
7907510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    if (!mStandby && mFd > 0) {
791a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        ::close(mFd);
792a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        mFd = -1;
793a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
7947510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    mStandby = true;
795a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    return status;
796a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
797a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
798a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatus_t AudioHardware::AudioStreamOutMSM72xx::dump(int fd, const Vector<String16>& args)
799a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
800a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    const size_t SIZE = 256;
801a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    char buffer[SIZE];
802a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    String8 result;
803a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    result.append("AudioStreamOutMSM72xx::dump\n");
804a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    snprintf(buffer, SIZE, "\tsample rate: %d\n", sampleRate());
805a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    result.append(buffer);
806a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize());
807a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    result.append(buffer);
8082735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    snprintf(buffer, SIZE, "\tchannels: %d\n", channels());
809a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    result.append(buffer);
810a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    snprintf(buffer, SIZE, "\tformat: %d\n", format());
811a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    result.append(buffer);
812a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    snprintf(buffer, SIZE, "\tmHardware: %p\n", mHardware);
813a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    result.append(buffer);
814a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    snprintf(buffer, SIZE, "\tmFd: %d\n", mFd);
815a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    result.append(buffer);
816a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    snprintf(buffer, SIZE, "\tmStartCount: %d\n", mStartCount);
817a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    result.append(buffer);
818a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    snprintf(buffer, SIZE, "\tmRetryCount: %d\n", mRetryCount);
819a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    result.append(buffer);
8207510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    snprintf(buffer, SIZE, "\tmStandby: %s\n", mStandby? "true": "false");
8217510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    result.append(buffer);
822a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    ::write(fd, result.string(), result.size());
823a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    return NO_ERROR;
824a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
825a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
8267510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Projectbool AudioHardware::AudioStreamOutMSM72xx::checkStandby()
8277510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project{
8287510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    return mStandby;
8297510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project}
8307510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project
8312735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent
8322735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurentstatus_t AudioHardware::AudioStreamOutMSM72xx::setParameters(const String8& keyValuePairs)
8332735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent{
8342735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    AudioParameter param = AudioParameter(keyValuePairs);
8352735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    String8 key = String8(AudioParameter::keyRouting);
8362735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    status_t status = NO_ERROR;
8372735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    int device;
8382735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    LOGV("AudioStreamOutMSM72xx::setParameters() %s", keyValuePairs.string());
8392735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent
8402735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    if (param.getInt(key, device) == NO_ERROR) {
8412735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        mDevices = device;
8422735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        LOGV("set output routing %x", mDevices);
8432735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        status = mHardware->doRouting(NULL);
8442735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        param.remove(key);
8452735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    }
8462735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent
8472735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    if (param.size()) {
8482735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        status = BAD_VALUE;
8492735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    }
8502735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    return status;
8512735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent}
8522735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent
8532735e3b55bdaf33cfd0dbaa1b914231243933e92Eric LaurentString8 AudioHardware::AudioStreamOutMSM72xx::getParameters(const String8& keys)
8542735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent{
8552735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    AudioParameter param = AudioParameter(keys);
8562735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    String8 value;
8572735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    String8 key = String8(AudioParameter::keyRouting);
8582735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent
8592735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    if (param.get(key, value) == NO_ERROR) {
8602735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        LOGV("get routing %x", mDevices);
8612735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        param.addInt(key, (int)mDevices);
8622735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    }
8632735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent
8642735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    LOGV("AudioStreamOutMSM72xx::getParameters() %s", param.toString().string());
8652735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    return param.toString();
8662735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent}
8672735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent
8682735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent
869a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland// ----------------------------------------------------------------------------
870a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
871a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian SwetlandAudioHardware::AudioStreamInMSM72xx::AudioStreamInMSM72xx() :
8727510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    mHardware(0), mFd(-1), mState(AUDIO_INPUT_CLOSED), mRetryCount(0),
8732735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    mFormat(AUDIO_HW_IN_FORMAT), mChannels(AUDIO_HW_IN_CHANNELS),
8747510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    mSampleRate(AUDIO_HW_IN_SAMPLERATE), mBufferSize(AUDIO_HW_IN_BUFFERSIZE),
8752735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    mAcoustics((AudioSystem::audio_in_acoustics)0), mDevices(0)
876a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
877a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
878a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
879a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatus_t AudioHardware::AudioStreamInMSM72xx::set(
8802735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        AudioHardware* hw, uint32_t devices, int *pFormat, uint32_t *pChannels, uint32_t *pRate,
8817510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        AudioSystem::audio_in_acoustics acoustic_flags)
882a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
8832735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    if (pFormat == 0 || *pFormat != AUDIO_HW_IN_FORMAT) {
8842735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        *pFormat = AUDIO_HW_IN_FORMAT;
8852735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        return BAD_VALUE;
8862735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    }
8872735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    if (pRate == 0) {
8882735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        return BAD_VALUE;
8892735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    }
8902735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    uint32_t rate = hw->getInputSampleRate(*pRate);
8912735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    if (rate != *pRate) {
8922735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        *pRate = rate;
8932735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        return BAD_VALUE;
8942735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    }
8952735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent
8962735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    if (pChannels == 0 || (*pChannels != AudioSystem::CHANNEL_IN_MONO &&
8972735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        *pChannels != AudioSystem::CHANNEL_IN_STEREO)) {
8982735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        *pChannels = AUDIO_HW_IN_CHANNELS;
8992735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        return BAD_VALUE;
9002735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    }
9012735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent
9022735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    mHardware = hw;
9032735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent
9042735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    LOGV("AudioStreamInMSM72xx::set(%d, %d, %u)", *pFormat, *pChannels, *pRate);
905a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    if (mFd >= 0) {
906a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        LOGE("Audio record already open");
907a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        return -EPERM;
908a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
909a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
910a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    // open audio input device
911a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    status_t status = ::open("/dev/msm_pcm_in", O_RDWR);
912a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    if (status < 0) {
9137510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        LOGE("Cannot open /dev/msm_pcm_in errno: %d", errno);
914a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        goto Error;
915a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
916a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    mFd = status;
917a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
918a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    // configuration
919a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    LOGV("get config");
920a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    struct msm_audio_config config;
921a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    status = ioctl(mFd, AUDIO_GET_CONFIG, &config);
922a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    if (status < 0) {
923a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        LOGE("Cannot read config");
924a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        goto Error;
925a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
926a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
927a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    LOGV("set config");
9282735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    config.channel_count = AudioSystem::popCount(*pChannels);
9292735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    config.sample_rate = *pRate;
930a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    config.buffer_size = bufferSize();
931a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    config.buffer_count = 2;
932a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    config.codec_type = CODEC_TYPE_PCM;
933a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    status = ioctl(mFd, AUDIO_SET_CONFIG, &config);
934a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    if (status < 0) {
935a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        LOGE("Cannot set config");
9362735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        if (ioctl(mFd, AUDIO_GET_CONFIG, &config) == 0) {
9372735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent            if (config.channel_count == 1) {
9382735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent                *pChannels = AudioSystem::CHANNEL_IN_MONO;
9392735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent            } else {
9402735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent                *pChannels = AudioSystem::CHANNEL_IN_STEREO;
9412735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent            }
9422735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent            *pRate = config.sample_rate;
9432735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        }
944a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        goto Error;
945a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
946a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
947a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    LOGV("confirm config");
948a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    status = ioctl(mFd, AUDIO_GET_CONFIG, &config);
949a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    if (status < 0) {
950a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        LOGE("Cannot read config");
951a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        goto Error;
952a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
953a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    LOGV("buffer_size: %u", config.buffer_size);
954a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    LOGV("buffer_count: %u", config.buffer_count);
955a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    LOGV("channel_count: %u", config.channel_count);
956a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    LOGV("sample_rate: %u", config.sample_rate);
957a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
9582735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    mDevices = devices;
9592735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    mFormat = AUDIO_HW_IN_FORMAT;
9602735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    mChannels = *pChannels;
9617510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    mSampleRate = config.sample_rate;
9627510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    mBufferSize = config.buffer_size;
9637510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project
9642735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    //mHardware->setMicMute_nosync(false);
9657510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    mState = AUDIO_INPUT_OPENED;
966d498a9ce9863bd979d3403473568c6e1e38b7daeBrian Swetland
967d498a9ce9863bd979d3403473568c6e1e38b7daeBrian Swetland    if (!acoustic)
968d498a9ce9863bd979d3403473568c6e1e38b7daeBrian Swetland        return NO_ERROR;
969d498a9ce9863bd979d3403473568c6e1e38b7daeBrian Swetland
9702735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    audpre_index = calculate_audpre_table_index(mSampleRate);
9717510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    tx_iir_index = (audpre_index * 2) + (hw->checkOutputStandby() ? 0 : 1);
9727510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    LOGD("audpre_index = %d, tx_iir_index = %d\n", audpre_index, tx_iir_index);
9737510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project
9747510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    /**
9757510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project     * If audio-preprocessing failed, we should not block record.
9767510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project     */
9777510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    int (*msm72xx_set_audpre_params)(int, int);
9787510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    msm72xx_set_audpre_params = (int (*)(int, int))::dlsym(acoustic, "msm72xx_set_audpre_params");
9797510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    status = msm72xx_set_audpre_params(audpre_index, tx_iir_index);
9807510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    if (status < 0)
9817510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        LOGE("Cannot set audpre parameters");
9827510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project
9837510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    int (*msm72xx_enable_audpre)(int, int, int);
9847510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    msm72xx_enable_audpre = (int (*)(int, int, int))::dlsym(acoustic, "msm72xx_enable_audpre");
9857510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    mAcoustics = acoustic_flags;
9867510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    status = msm72xx_enable_audpre((int)acoustic_flags, audpre_index, tx_iir_index);
9877510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    if (status < 0)
9887510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        LOGE("Cannot enable audpre");
9897510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project
990a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    return NO_ERROR;
991a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
992a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian SwetlandError:
993a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    if (mFd > 0) {
994a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        ::close(mFd);
995a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        mFd = -1;
996a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
997a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    return status;
998a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
999a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
1000a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian SwetlandAudioHardware::AudioStreamInMSM72xx::~AudioStreamInMSM72xx()
1001a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
10027510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    LOGV("AudioStreamInMSM72xx destructor");
10032735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    standby();
1004a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
1005a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
1006a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandssize_t AudioHardware::AudioStreamInMSM72xx::read( void* buffer, ssize_t bytes)
1007a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
1008d066973de83218a24c773e5de04d10ed2d730873Eric Laurent    LOGV("AudioStreamInMSM72xx::read(%p, %ld)", buffer, bytes);
10097510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    if (!mHardware) return -1;
1010a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
1011a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    size_t count = bytes;
1012a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    uint8_t* p = static_cast<uint8_t*>(buffer);
1013a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
10147510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    if (mState < AUDIO_INPUT_OPENED) {
1015d066973de83218a24c773e5de04d10ed2d730873Eric Laurent        Mutex::Autolock lock(mHardware->mLock);
10162735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        if (set(mHardware, mDevices, &mFormat, &mChannels, &mSampleRate, mAcoustics) != NO_ERROR) {
10177510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project            return -1;
10187510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        }
10197510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    }
10202735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent
10217510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    if (mState < AUDIO_INPUT_STARTED) {
1022a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        if (ioctl(mFd, AUDIO_START, 0)) {
1023a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            LOGE("Error starting record");
1024a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            return -1;
1025a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        }
10267510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        mState = AUDIO_INPUT_STARTED;
1027a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
1028a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
1029a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    while (count) {
1030a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        ssize_t bytesRead = ::read(mFd, buffer, count);
1031a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        if (bytesRead >= 0) {
1032a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            count -= bytesRead;
1033a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            p += bytesRead;
1034a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        } else {
1035a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            if (errno != EAGAIN) return bytesRead;
1036a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            mRetryCount++;
1037a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            LOGW("EAGAIN - retrying");
1038a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        }
1039a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
1040a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    return bytes;
1041a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
1042a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
10437510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Projectstatus_t AudioHardware::AudioStreamInMSM72xx::standby()
10447510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project{
10457510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    if (!mHardware) return -1;
10467510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    if (mState > AUDIO_INPUT_CLOSED) {
10477510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        if (mFd > 0) {
10487510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project            ::close(mFd);
10497510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project            mFd = -1;
10507510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        }
10512735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        //mHardware->checkMicMute();
10527510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        mState = AUDIO_INPUT_CLOSED;
10537510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    }
10547510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    return NO_ERROR;
10557510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project}
10567510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project
1057a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatus_t AudioHardware::AudioStreamInMSM72xx::dump(int fd, const Vector<String16>& args)
1058a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
1059a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    const size_t SIZE = 256;
1060a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    char buffer[SIZE];
1061a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    String8 result;
1062a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    result.append("AudioStreamInMSM72xx::dump\n");
1063a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    snprintf(buffer, SIZE, "\tsample rate: %d\n", sampleRate());
1064a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    result.append(buffer);
1065a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize());
1066a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    result.append(buffer);
10672735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    snprintf(buffer, SIZE, "\tchannels: %d\n", channels());
1068a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    result.append(buffer);
1069a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    snprintf(buffer, SIZE, "\tformat: %d\n", format());
1070a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    result.append(buffer);
1071a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    snprintf(buffer, SIZE, "\tmHardware: %p\n", mHardware);
1072a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    result.append(buffer);
1073a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    snprintf(buffer, SIZE, "\tmFd count: %d\n", mFd);
1074a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    result.append(buffer);
10757510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    snprintf(buffer, SIZE, "\tmState: %d\n", mState);
1076a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    result.append(buffer);
1077a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    snprintf(buffer, SIZE, "\tmRetryCount: %d\n", mRetryCount);
1078a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    result.append(buffer);
1079a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    ::write(fd, result.string(), result.size());
1080a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    return NO_ERROR;
1081a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
1082a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
10832735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurentstatus_t AudioHardware::AudioStreamInMSM72xx::setParameters(const String8& keyValuePairs)
10842735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent{
10852735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    AudioParameter param = AudioParameter(keyValuePairs);
10862735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    String8 key = String8(AudioParameter::keyRouting);
10872735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    status_t status = NO_ERROR;
10882735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    int device;
10892735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    LOGV("AudioStreamInMSM72xx::setParameters() %s", keyValuePairs.string());
10902735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent
10912735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    if (param.getInt(key, device) == NO_ERROR) {
10922735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        LOGV("set input routing %x", device);
10932735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        if (device & (device - 1)) {
10942735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent            status = BAD_VALUE;
10952735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        } else {
10962735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent            mDevices = device;
10972735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent            status = mHardware->doRouting(this);
10982735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        }
10992735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        param.remove(key);
11002735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    }
11012735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent
11022735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    if (param.size()) {
11032735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        status = BAD_VALUE;
11042735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    }
11052735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    return status;
11062735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent}
11072735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent
11082735e3b55bdaf33cfd0dbaa1b914231243933e92Eric LaurentString8 AudioHardware::AudioStreamInMSM72xx::getParameters(const String8& keys)
11092735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent{
11102735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    AudioParameter param = AudioParameter(keys);
11112735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    String8 value;
11122735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    String8 key = String8(AudioParameter::keyRouting);
11132735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent
11142735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    if (param.get(key, value) == NO_ERROR) {
11152735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        LOGV("get routing %x", mDevices);
11162735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent        param.addInt(key, (int)mDevices);
11172735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    }
11182735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent
11192735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    LOGV("AudioStreamInMSM72xx::getParameters() %s", param.toString().string());
11202735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent    return param.toString();
11212735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent}
11222735e3b55bdaf33cfd0dbaa1b914231243933e92Eric Laurent
1123a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland// ----------------------------------------------------------------------------
1124a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
1125a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandextern "C" AudioHardwareInterface* createAudioHardware(void) {
1126a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    return new AudioHardware();
1127a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
1128a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
1129a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}; // namespace android
1130