AudioHardware.cpp revision 9e8b6821afad923dcc616768f7582545c90a0bc6
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),
497510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    mOutput(0), mInput(0), mSndEndpoints(NULL),
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_BT(-1),
54a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    SND_DEVICE_BT_EC_OFF(-1),
55a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    SND_DEVICE_HEADSET(-1),
56a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    SND_DEVICE_HEADSET_AND_SPEAKER(-1)
57a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
58a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
597510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    int (*snd_get_num)();
607510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    int (*snd_get_endpoint)(int, msm_snd_endpoint *);
617510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    int (*set_acoustic_parameters)();
627510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project
637510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    struct msm_snd_endpoint *ept;
647510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project
657510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    acoustic = ::dlopen("/system/lib/libhtc_acoustic.so", RTLD_NOW);
667510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    if (acoustic == NULL ) {
677510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        LOGE("Could not open libhtc_acoustic.so");
687510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        return;
697510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    }
707510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project
717510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    set_acoustic_parameters = (int (*)(void))::dlsym(acoustic, "set_acoustic_parameters");
727510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    if ((*set_acoustic_parameters) == 0 ) {
737510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        LOGE("Could not open set_acoustic_parameters()");
743ccfb0bb4f6f8c18d5b66b5568a9aa1d969a598aIliyan Malchev        return;
753ccfb0bb4f6f8c18d5b66b5568a9aa1d969a598aIliyan Malchev    }
763ccfb0bb4f6f8c18d5b66b5568a9aa1d969a598aIliyan Malchev
777510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    int rc = set_acoustic_parameters();
787510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    if (rc < 0) {
797510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        LOGE("Could not set acoustic parameters to share memory: %d", rc);
807510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project//        return;
817510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    }
827510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project
837510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    snd_get_num = (int (*)(void))::dlsym(acoustic, "snd_get_num_endpoints");
847510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    if ((*snd_get_num) == 0 ) {
857510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        LOGE("Could not open snd_get_num()");
867510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project//        return;
877510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    }
887510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project
897510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    mNumSndEndpoints = snd_get_num();
907510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    LOGD("mNumSndEndpoints = %d", mNumSndEndpoints);
917510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    mSndEndpoints = new msm_snd_endpoint[mNumSndEndpoints];
927510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    mInit = true;
937510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    LOGV("constructed %d SND endpoints)", mNumSndEndpoints);
947510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    ept = mSndEndpoints;
957510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    snd_get_endpoint = (int (*)(int, msm_snd_endpoint *))::dlsym(acoustic, "snd_get_endpoint");
967510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    if ((*snd_get_endpoint) == 0 ) {
977510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        LOGE("Could not open snd_get_endpoint()");
987510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        return;
997510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    }
1007510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project
1017510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    for (int cnt = 0; cnt < mNumSndEndpoints; cnt++, ept++) {
1027510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        ept->id = cnt;
1037510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        snd_get_endpoint(cnt, ept);
1047510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project#define CHECK_FOR(desc) \
1057510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        if (!strcmp(ept->name, #desc)) { \
1067510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project            SND_DEVICE_##desc = ept->id; \
1077510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project            LOGD("BT MATCH " #desc); \
1087510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        } else
1097510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        CHECK_FOR(CURRENT)
1107510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        CHECK_FOR(HANDSET)
1117510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        CHECK_FOR(SPEAKER)
1127510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        CHECK_FOR(BT)
1137510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        CHECK_FOR(BT_EC_OFF)
1147510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        CHECK_FOR(HEADSET)
1157510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        CHECK_FOR(HEADSET_AND_SPEAKER) {}
116a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland#undef CHECK_FOR
117a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
118a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
119a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
120a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian SwetlandAudioHardware::~AudioHardware()
121a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
122a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    delete mInput;
123a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    delete mOutput;
124a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    delete [] mSndEndpoints;
1257510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    ::dlclose(acoustic);
126a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    mInit = false;
127a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
128a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
129a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatus_t AudioHardware::initCheck()
130a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
131a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    return mInit ? NO_ERROR : NO_INIT;
132a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
133a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
134a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian SwetlandAudioStreamOut* AudioHardware::openOutputStream(
1357510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        int format, int channelCount, uint32_t sampleRate, status_t *status)
136a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
137a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    Mutex::Autolock lock(mLock);
138a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
139a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    // only one output stream allowed
1407510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    if (mOutput) {
1417510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        if (status) {
1427510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project            *status = INVALID_OPERATION;
1437510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        }
1447510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        return 0;
1457510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    }
146a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
147a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    // create new output stream
148a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    AudioStreamOutMSM72xx* out = new AudioStreamOutMSM72xx();
1497510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    status_t lStatus = out->set(this, format, channelCount, sampleRate);
1507510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    if (status) {
1517510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        *status = lStatus;
1527510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    }
1537510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    if (lStatus == NO_ERROR) {
154a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        mOutput = out;
155a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    } else {
156a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        delete out;
157a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
158a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    return mOutput;
159a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
160a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
161a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandvoid AudioHardware::closeOutputStream(AudioStreamOutMSM72xx* out) {
162a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    Mutex::Autolock lock(mLock);
163a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    if (mOutput != out) {
164a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        LOGW("Attempt to close invalid output stream");
165a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
166a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    else {
167a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        mOutput = 0;
168a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
169a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
170a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
171a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian SwetlandAudioStreamIn* AudioHardware::openInputStream(
1729e8b6821afad923dcc616768f7582545c90a0bc6Dave Sparks        int inputSource, int format, int channelCount, uint32_t sampleRate,
1739e8b6821afad923dcc616768f7582545c90a0bc6Dave Sparks        status_t *status, AudioSystem::audio_in_acoustics acoustic_flags)
174a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
1759e8b6821afad923dcc616768f7582545c90a0bc6Dave Sparks    // check for valid input source
1769e8b6821afad923dcc616768f7582545c90a0bc6Dave Sparks    if ((inputSource != AudioRecord::DEFAULT_INPUT) &&
1779e8b6821afad923dcc616768f7582545c90a0bc6Dave Sparks            (inputSource != AudioRecord::MIC_INPUT)) {
1789e8b6821afad923dcc616768f7582545c90a0bc6Dave Sparks        return 0;
1799e8b6821afad923dcc616768f7582545c90a0bc6Dave Sparks    }
1809e8b6821afad923dcc616768f7582545c90a0bc6Dave Sparks
1817510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    mLock.lock();
182a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    // input stream already open?
1837510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    if (mInput) {
1847510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        if (status) {
1857510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project            *status = INVALID_OPERATION;
1867510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        }
1877510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        mLock.unlock();
1887510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        return 0;
1897510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    }
190a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
191a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    AudioStreamInMSM72xx* in = new AudioStreamInMSM72xx();
1927510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    status_t lStatus = in->set(this, format, channelCount, sampleRate, acoustic_flags);
1937510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    if (status) {
1947510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        *status = lStatus;
1957510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    }
1967510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    if (lStatus != NO_ERROR) {
1977510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        mLock.unlock();
198a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        delete in;
199a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        return 0;
200a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
201a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
202a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    mInput = in;
2037510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    mLock.unlock();
2047510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project
205a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    return mInput;
206a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
207a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
2089e8b6821afad923dcc616768f7582545c90a0bc6Dave Sparks// DEPRECATED
2099e8b6821afad923dcc616768f7582545c90a0bc6Dave SparksAudioStreamIn* AudioHardware::openInputStream(
2109e8b6821afad923dcc616768f7582545c90a0bc6Dave Sparks        int format, int channelCount, uint32_t sampleRate, status_t *status,
2119e8b6821afad923dcc616768f7582545c90a0bc6Dave Sparks        AudioSystem::audio_in_acoustics acoustic_flags)
2129e8b6821afad923dcc616768f7582545c90a0bc6Dave Sparks{
2139e8b6821afad923dcc616768f7582545c90a0bc6Dave Sparks    return openInputStream(AudioRecord::DEFAULT_INPUT, format, channelCount,
2149e8b6821afad923dcc616768f7582545c90a0bc6Dave Sparks            sampleRate, status, acoustic_flags);
2159e8b6821afad923dcc616768f7582545c90a0bc6Dave Sparks}
2169e8b6821afad923dcc616768f7582545c90a0bc6Dave Sparks
217a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandvoid AudioHardware::closeInputStream(AudioStreamInMSM72xx* in) {
218a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    Mutex::Autolock lock(mLock);
219a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    if (mInput != in) {
220a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        LOGW("Attempt to close invalid input stream");
221a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
222a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    else {
223a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        mInput = 0;
224a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
225a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
226a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
2277510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Projectbool AudioHardware::checkOutputStandby()
228a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
2297510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    if (mOutput)
2307510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        if (!mOutput->checkStandby())
2317510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project            return false;
232a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
2337510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    return true;
234a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
235a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
236a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatus_t AudioHardware::setMicMute(bool state)
237a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
238a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    Mutex::Autolock lock(mLock);
239a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    return setMicMute_nosync(state);
240a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
241a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
242a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland// always call with mutex held
243a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatus_t AudioHardware::setMicMute_nosync(bool state)
244a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
245a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    if (mMicMute != state) {
246a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        mMicMute = state;
247a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        return doAudioRouteOrMute(SND_DEVICE_CURRENT);
248a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
249a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    return NO_ERROR;
250a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
251a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
252a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatus_t AudioHardware::getMicMute(bool* state)
253a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
254a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    *state = mMicMute;
255a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    return NO_ERROR;
256a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
257a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
258a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatus_t AudioHardware::setParameter(const char *key, const char *value)
259a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
260a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    LOGV("%s key = %s value = %s\n", __FUNCTION__, key, value);
261a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
262a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    if (key == NULL || value == NULL) {
263a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        LOGE("%s called with null argument, ignoring (key = %s, value = %s",
264a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland             __FUNCTION__, key, value);
265a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        return BAD_VALUE;
266a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
267a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
268a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    const char BT_NREC_KEY[] = "bt_headset_nrec";
269a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    const char BT_NAME_KEY[] = "bt_headset_name";
270a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    const char BT_NREC_VALUE_ON[] = "on";
271a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
272a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    if (!strncmp(key, BT_NREC_KEY, sizeof(BT_NREC_KEY))) {
273a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        if (!strncmp(value, BT_NREC_VALUE_ON, sizeof(BT_NREC_VALUE_ON))) {
274a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            mBluetoothNrec = true;
275a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        } else {
276a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            mBluetoothNrec = false;
277a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            LOGI("Turning noise reduction and echo cancellation off for BT "
278a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland                 "headset");
279a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        }
280a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        doRouting();
281a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    } else if (!strncmp(key, BT_NAME_KEY, sizeof(BT_NAME_KEY))) {
282a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        mBluetoothId = 0;
2837510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        for (int i = 0; i < mNumSndEndpoints; i++) {
2847510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project            if (!strcasecmp(value, mSndEndpoints[i].name)) {
2857510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project                mBluetoothId = mSndEndpoints[i].id;
286a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland                LOGI("Using custom acoustic parameters for %s", value);
287a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland                break;
288a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            }
289a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        }
290a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        if (mBluetoothId == 0) {
291a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            LOGI("Using default acoustic parameters "
292a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland                 "(%s not in acoustic database)", value);
293a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            doRouting();
294a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        }
295a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
296a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
297a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    return NO_ERROR;
298a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
2997510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Projectstatic unsigned calculate_audpre_table_index(unsigned index)
300a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
3017510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    switch (index) {
3027510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        case 48000:    return SAMP_RATE_INDX_48000;
3037510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        case 44100:    return SAMP_RATE_INDX_44100;
3047510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        case 32000:    return SAMP_RATE_INDX_32000;
3057510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        case 24000:    return SAMP_RATE_INDX_24000;
3067510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        case 22050:    return SAMP_RATE_INDX_22050;
3077510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        case 16000:    return SAMP_RATE_INDX_16000;
3087510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        case 12000:    return SAMP_RATE_INDX_12000;
3097510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        case 11025:    return SAMP_RATE_INDX_11025;
3107510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        case 8000:    return SAMP_RATE_INDX_8000;
3117510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        default:     return -1;
312a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
313a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
3147510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Projectsize_t AudioHardware::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
315a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
3167510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    if (checkInputSampleRate(sampleRate) != NO_ERROR) {
3177510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        LOGW("getInputBufferSize bad sampling rate: %d", sampleRate);
3187510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        return 0;
319a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
3207510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    if (format != AudioSystem::PCM_16_BIT) {
3217510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        LOGW("getInputBufferSize bad format: %d", format);
3227510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        return 0;
323a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
3247510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    if (channelCount < 1 || channelCount > 2) {
3257510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        LOGW("getInputBufferSize bad channel count: %d", channelCount);
3267510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        return 0;
327a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
328a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
3297510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    return 2048*channelCount;
330a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
331a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
332a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatic status_t set_volume_rpc(uint32_t device,
333a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland                               uint32_t method,
334a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland                               uint32_t volume)
335a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
336a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    int fd;
337a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland#if LOG_SND_RPC
338a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    LOGD("rpc_snd_set_volume(%d, %d, %d)\n", device, method, volume);
339a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland#endif
340a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
341a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    if (device == -1UL) return NO_ERROR;
342a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
343a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    fd = open("/dev/msm_snd", O_RDWR);
344a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    if (fd < 0) {
345a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        LOGE("Can not open snd device");
346a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        return -EPERM;
347a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
348a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    /* rpc_snd_set_volume(
349a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland     *     device,            # Any hardware device enum, including
350a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland     *                        # SND_DEVICE_CURRENT
351a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland     *     method,            # must be SND_METHOD_VOICE to do anything useful
352a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland     *     volume,            # integer volume level, in range [0,5].
353a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland     *                        # note that 0 is audible (not quite muted)
354a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland     *  )
355a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland     * rpc_snd_set_volume only works for in-call sound volume.
356a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland     */
3577510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project     struct msm_snd_volume_config args;
3587510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project     args.device = device;
3597510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project     args.method = method;
3607510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project     args.volume = volume;
361a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
3627510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project     if (ioctl(fd, SND_SET_VOLUME, &args) < 0) {
3637510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project         LOGE("snd_set_volume error.");
3647510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project         close(fd);
3657510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project         return -EIO;
3667510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project     }
3677510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project     close(fd);
3687510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project     return NO_ERROR;
369a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
370a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
371a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatus_t AudioHardware::setVoiceVolume(float v)
372a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
373a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    if (v < 0.0) {
374a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        LOGW("setVoiceVolume(%f) under 0.0, assuming 0.0\n", v);
375a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        v = 0.0;
376a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    } else if (v > 1.0) {
377a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        LOGW("setVoiceVolume(%f) over 1.0, assuming 1.0\n", v);
378a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        v = 1.0;
379a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
380a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
381a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    int vol = lrint(v * 5.0);
382a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    LOGD("setVoiceVolume(%f)\n", v);
383a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    LOGI("Setting in-call volume to %d (available range is 0 to 5)\n", vol);
384a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
385d066973de83218a24c773e5de04d10ed2d730873Eric Laurent    Mutex::Autolock lock(mLock);
386a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    set_volume_rpc(SND_DEVICE_CURRENT, SND_METHOD_VOICE, vol);
387a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    return NO_ERROR;
388a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
389a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
390a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatus_t AudioHardware::setMasterVolume(float v)
391a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
392a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    Mutex::Autolock lock(mLock);
393a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    int vol = ceil(v * 5.0);
394a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    LOGI("Set master volume to %d.\n", vol);
395a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    set_volume_rpc(SND_DEVICE_HANDSET, SND_METHOD_VOICE, vol);
396a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    set_volume_rpc(SND_DEVICE_SPEAKER, SND_METHOD_VOICE, vol);
397a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    set_volume_rpc(SND_DEVICE_BT,      SND_METHOD_VOICE, vol);
398a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    set_volume_rpc(SND_DEVICE_HEADSET, SND_METHOD_VOICE, vol);
399a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    // We return an error code here to let the audioflinger do in-software
400a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    // volume on top of the maximum volume that we set through the SND API.
401a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    // return error - software mixer will handle it
402a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    return -1;
403a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
404a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
405a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatic status_t do_route_audio_rpc(uint32_t device,
406a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland                                   bool ear_mute, bool mic_mute)
407a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
408a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    if (device == -1UL)
409a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        return NO_ERROR;
410a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
411a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    int fd;
412a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland#if LOG_SND_RPC
413a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    LOGD("rpc_snd_set_device(%d, %d, %d)\n", device, ear_mute, mic_mute);
414a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland#endif
415a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
416a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    fd = open("/dev/msm_snd", O_RDWR);
417a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    if (fd < 0) {
418a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        LOGE("Can not open snd device");
419a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        return -EPERM;
420a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
421a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    // RPC call to switch audio path
422a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    /* rpc_snd_set_device(
423a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland     *     device,            # Hardware device enum to use
424a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland     *     ear_mute,          # Set mute for outgoing voice audio
425a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland     *                        # this should only be unmuted when in-call
426a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland     *     mic_mute,          # Set mute for incoming voice audio
427a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland     *                        # this should only be unmuted when in-call or
428a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland     *                        # recording.
429a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland     *  )
430a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland     */
4313ccfb0bb4f6f8c18d5b66b5568a9aa1d969a598aIliyan Malchev    struct msm_snd_device_config args;
432a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    args.device = device;
433a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    args.ear_mute = ear_mute ? SND_MUTE_MUTED : SND_MUTE_UNMUTED;
434a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    args.mic_mute = mic_mute ? SND_MUTE_MUTED : SND_MUTE_UNMUTED;
435a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
436a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    if (ioctl(fd, SND_SET_DEVICE, &args) < 0) {
437a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        LOGE("snd_set_device error.");
438a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        close(fd);
439a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        return -EIO;
440a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
441a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
442a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    close(fd);
443a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    return NO_ERROR;
444a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
445a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
446a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland// always call with mutex held
447a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatus_t AudioHardware::doAudioRouteOrMute(uint32_t device)
448a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
449a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    if (device == (uint32_t)SND_DEVICE_BT) {
450a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        if (mBluetoothId) {
451a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            device = mBluetoothId;
452a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        } else if (!mBluetoothNrec) {
453a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            device = SND_DEVICE_BT_EC_OFF;
454a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        }
455a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
456a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    return do_route_audio_rpc(device,
4577510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project                              mMode != AudioSystem::MODE_IN_CALL, mMicMute);
458a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
459a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
460a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatic int count_bits(uint32_t vector)
461a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
462a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    int bits;
463a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    for (bits = 0; vector; bits++) {
464a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        vector &= vector - 1;
465a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
466a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    return bits;
467a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
468a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
469a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatus_t AudioHardware::doRouting()
470a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
471a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    Mutex::Autolock lock(mLock);
472a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    uint32_t routes = mRoutes[mMode];
473a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    if (count_bits(routes) > 1) {
474a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        if (routes !=
4757510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project            (AudioSystem::ROUTE_HEADSET | AudioSystem::ROUTE_SPEAKER)) {
476a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            LOGW("Hardware does not support requested route combination (%#X),"
477a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland                 " picking closest possible route...", routes);
478a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        }
479a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
4807510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    int (*msm72xx_enable_audpp)(int);
4817510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    msm72xx_enable_audpp = (int (*)(int))::dlsym(acoustic, "msm72xx_enable_audpp");
482a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    status_t ret = NO_ERROR;
4837510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    if (routes & AudioSystem::ROUTE_BLUETOOTH_SCO) {
484a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        LOGI("Routing audio to Bluetooth PCM\n");
485a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        ret = doAudioRouteOrMute(SND_DEVICE_BT);
4867510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        msm72xx_enable_audpp(ADRC_DISABLE | EQ_DISABLE | RX_IIR_DISABLE);
487a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    } else if ((routes & AudioSystem::ROUTE_HEADSET) &&
488a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland               (routes & AudioSystem::ROUTE_SPEAKER)) {
489a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        LOGI("Routing audio to Wired Headset and Speaker\n");
490a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        ret = doAudioRouteOrMute(SND_DEVICE_HEADSET_AND_SPEAKER);
4917510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        msm72xx_enable_audpp(ADRC_ENABLE | EQ_ENABLE | RX_IIR_ENABLE);
492a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    } else if (routes & AudioSystem::ROUTE_HEADSET) {
493a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        LOGI("Routing audio to Wired Headset\n");
494a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        ret = doAudioRouteOrMute(SND_DEVICE_HEADSET);
4957510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        msm72xx_enable_audpp(ADRC_DISABLE | EQ_DISABLE | RX_IIR_DISABLE);
496a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    } else if (routes & AudioSystem::ROUTE_SPEAKER) {
497a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        LOGI("Routing audio to Speakerphone\n");
498a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        ret = doAudioRouteOrMute(SND_DEVICE_SPEAKER);
4997510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        msm72xx_enable_audpp(ADRC_ENABLE | EQ_ENABLE | RX_IIR_ENABLE);
500a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    } else {
501a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        LOGI("Routing audio to Handset\n");
502a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        ret = doAudioRouteOrMute(SND_DEVICE_HANDSET);
5037510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        msm72xx_enable_audpp(ADRC_DISABLE | EQ_DISABLE | RX_IIR_DISABLE);
504a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
505a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
506a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    return ret;
507a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
508a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
509a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatus_t AudioHardware::checkMicMute()
510a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
511a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    Mutex::Autolock lock(mLock);
512a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    if (mMode != AudioSystem::MODE_IN_CALL) {
513a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        setMicMute_nosync(true);
514a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
5157510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project
516a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    return NO_ERROR;
517a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
518a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
519a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatus_t AudioHardware::dumpInternals(int fd, const Vector<String16>& args)
520a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
521a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    const size_t SIZE = 256;
522a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    char buffer[SIZE];
523a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    String8 result;
524a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    result.append("AudioHardware::dumpInternals\n");
525a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    snprintf(buffer, SIZE, "\tmInit: %s\n", mInit? "true": "false");
526a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    result.append(buffer);
527a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    snprintf(buffer, SIZE, "\tmMicMute: %s\n", mMicMute? "true": "false");
528a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    result.append(buffer);
529a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    snprintf(buffer, SIZE, "\tmBluetoothNrec: %s\n", mBluetoothNrec? "true": "false");
530a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    result.append(buffer);
531a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    snprintf(buffer, SIZE, "\tmBluetoothId: %d\n", mBluetoothId);
532a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    result.append(buffer);
533a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    ::write(fd, result.string(), result.size());
534a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    return NO_ERROR;
535a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
536a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
537a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatus_t AudioHardware::dump(int fd, const Vector<String16>& args)
538a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
539a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    dumpInternals(fd, args);
540a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    if (mInput) {
541a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        mInput->dump(fd, args);
542a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
543a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    if (mOutput) {
544a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        mOutput->dump(fd, args);
545a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
546a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    return NO_ERROR;
547a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
548a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
5497510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Projectstatus_t AudioHardware::checkInputSampleRate(uint32_t sampleRate)
5507510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project{
5517510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    for (uint32_t i = 0; i < sizeof(inputSamplingRates)/sizeof(uint32_t); i++) {
5527510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        if (sampleRate == inputSamplingRates[i]) {
5537510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project            return NO_ERROR;
5547510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        }
5557510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    }
5567510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    return BAD_VALUE;
5577510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project}
5587510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project
559a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland// ----------------------------------------------------------------------------
560a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
561a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian SwetlandAudioHardware::AudioStreamOutMSM72xx::AudioStreamOutMSM72xx() :
5627510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    mHardware(0), mFd(-1), mStartCount(0), mRetryCount(0), mStandby(true)
563a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
564a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
565a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
566a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatus_t AudioHardware::AudioStreamOutMSM72xx::set(
567a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        AudioHardware* hw, int format, int channels, uint32_t rate)
568a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
569a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    // fix up defaults
570a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    if (format == 0) format = AudioSystem::PCM_16_BIT;
571a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    if (channels == 0) channels = channelCount();
572a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    if (rate == 0) rate = sampleRate();
573a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
574a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    // check values
575a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    if ((format != AudioSystem::PCM_16_BIT) ||
576a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            (channels != channelCount()) ||
577a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            (rate != sampleRate()))
578a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        return BAD_VALUE;
579a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
580a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    mHardware = hw;
581a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
582a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    return NO_ERROR;
583a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
584a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
585a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian SwetlandAudioHardware::AudioStreamOutMSM72xx::~AudioStreamOutMSM72xx()
586a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
5877510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    if (mFd > 0) close(mFd);
588a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    mHardware->closeOutputStream(this);
589a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
590a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
591a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandssize_t AudioHardware::AudioStreamOutMSM72xx::write(const void* buffer, size_t bytes)
592a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
593a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    // LOGD("AudioStreamOutMSM72xx::write(%p, %u)", buffer, bytes);
594a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    status_t status = NO_INIT;
595a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    size_t count = bytes;
596a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    const uint8_t* p = static_cast<const uint8_t*>(buffer);
597a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
5987510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    if (mStandby) {
599a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
600a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        // open driver
601a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        LOGV("open driver");
602a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        status = ::open("/dev/msm_pcm_out", O_RDWR);
603a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        if (status < 0) {
6047510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project            LOGE("Cannot open /dev/msm_pcm_out errno: %d", errno);
605a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            goto Error;
606a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        }
607a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        mFd = status;
608a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
609a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        // configuration
610a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        LOGV("get config");
611a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        struct msm_audio_config config;
612a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        status = ioctl(mFd, AUDIO_GET_CONFIG, &config);
613a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        if (status < 0) {
614a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            LOGE("Cannot read config");
615a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            goto Error;
616a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        }
617a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
618a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        LOGV("set config");
619a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        config.channel_count = channelCount();
620a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        config.sample_rate = sampleRate();
621a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        config.buffer_size = bufferSize();
6227510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        config.buffer_count = AUDIO_HW_NUM_OUT_BUF;
623a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        config.codec_type = CODEC_TYPE_PCM;
624a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        status = ioctl(mFd, AUDIO_SET_CONFIG, &config);
625a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        if (status < 0) {
626a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            LOGE("Cannot set config");
627a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            goto Error;
628a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        }
629a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
630a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        LOGV("buffer_size: %u", config.buffer_size);
631a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        LOGV("buffer_count: %u", config.buffer_count);
632a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        LOGV("channel_count: %u", config.channel_count);
633a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        LOGV("sample_rate: %u", config.sample_rate);
634a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
635a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        // fill 2 buffers before AUDIO_START
6367510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        mStartCount = AUDIO_HW_NUM_OUT_BUF;
6377510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        mStandby = false;
638a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
639a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
640a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    while (count) {
641a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        ssize_t written = ::write(mFd, p, count);
642a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        if (written >= 0) {
643a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            count -= written;
644a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            p += written;
645a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        } else {
646a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            if (errno != EAGAIN) return written;
647a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            mRetryCount++;
648a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            LOGW("EAGAIN - retry");
649a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        }
650a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
651a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
652a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    // start audio after we fill 2 buffers
653a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    if (mStartCount) {
654a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        if (--mStartCount == 0) {
655a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            ioctl(mFd, AUDIO_START, 0);
656a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        }
657a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
658a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    return bytes;
659a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
660a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian SwetlandError:
661a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    if (mFd > 0) {
662a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        ::close(mFd);
663a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        mFd = -1;
664a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
665a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    // Simulate audio output timing in case of error
6667510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    usleep(bytes * 1000000 / frameSize() / sampleRate());
667a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
668a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    return status;
669a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
670a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
671a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatus_t AudioHardware::AudioStreamOutMSM72xx::standby()
672a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
673a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    status_t status = NO_ERROR;
6747510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    if (!mStandby && mFd > 0) {
675a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        ::close(mFd);
676a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        mFd = -1;
677a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
6787510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    mStandby = true;
679a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    return status;
680a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
681a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
682a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatus_t AudioHardware::AudioStreamOutMSM72xx::dump(int fd, const Vector<String16>& args)
683a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
684a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    const size_t SIZE = 256;
685a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    char buffer[SIZE];
686a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    String8 result;
687a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    result.append("AudioStreamOutMSM72xx::dump\n");
688a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    snprintf(buffer, SIZE, "\tsample rate: %d\n", sampleRate());
689a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    result.append(buffer);
690a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize());
691a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    result.append(buffer);
692a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    snprintf(buffer, SIZE, "\tchannel count: %d\n", channelCount());
693a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    result.append(buffer);
694a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    snprintf(buffer, SIZE, "\tformat: %d\n", format());
695a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    result.append(buffer);
696a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    snprintf(buffer, SIZE, "\tmHardware: %p\n", mHardware);
697a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    result.append(buffer);
698a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    snprintf(buffer, SIZE, "\tmFd: %d\n", mFd);
699a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    result.append(buffer);
700a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    snprintf(buffer, SIZE, "\tmStartCount: %d\n", mStartCount);
701a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    result.append(buffer);
702a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    snprintf(buffer, SIZE, "\tmRetryCount: %d\n", mRetryCount);
703a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    result.append(buffer);
7047510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    snprintf(buffer, SIZE, "\tmStandby: %s\n", mStandby? "true": "false");
7057510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    result.append(buffer);
706a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    ::write(fd, result.string(), result.size());
707a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    return NO_ERROR;
708a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
709a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
7107510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Projectbool AudioHardware::AudioStreamOutMSM72xx::checkStandby()
7117510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project{
7127510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    return mStandby;
7137510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project}
7147510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project
715a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland// ----------------------------------------------------------------------------
716a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
717a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian SwetlandAudioHardware::AudioStreamInMSM72xx::AudioStreamInMSM72xx() :
7187510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    mHardware(0), mFd(-1), mState(AUDIO_INPUT_CLOSED), mRetryCount(0),
7197510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    mFormat(AUDIO_HW_IN_FORMAT), mChannelCount(AUDIO_HW_IN_CHANNELS),
7207510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    mSampleRate(AUDIO_HW_IN_SAMPLERATE), mBufferSize(AUDIO_HW_IN_BUFFERSIZE),
7217510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    mAcoustics((AudioSystem::audio_in_acoustics)0)
722a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
723a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
724a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
725a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatus_t AudioHardware::AudioStreamInMSM72xx::set(
7267510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        AudioHardware* hw, int format, int channelCount, uint32_t sampleRate,
7277510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        AudioSystem::audio_in_acoustics acoustic_flags)
728a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
729a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    LOGV("AudioStreamInMSM72xx::set(%d, %d, %u)", format, channelCount, sampleRate);
730a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    if (mFd >= 0) {
731a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        LOGE("Audio record already open");
732a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        return -EPERM;
733a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
734a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
735a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    // open audio input device
736a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    status_t status = ::open("/dev/msm_pcm_in", O_RDWR);
737a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    if (status < 0) {
7387510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        LOGE("Cannot open /dev/msm_pcm_in errno: %d", errno);
739a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        goto Error;
740a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
741a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    mFd = status;
742a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
743a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    // configuration
744a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    LOGV("get config");
745a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    struct msm_audio_config config;
746a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    status = ioctl(mFd, AUDIO_GET_CONFIG, &config);
747a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    if (status < 0) {
748a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        LOGE("Cannot read config");
749a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        goto Error;
750a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
751a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
752a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    LOGV("set config");
753a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    config.channel_count = channelCount;
754a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    config.sample_rate = sampleRate;
755a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    config.buffer_size = bufferSize();
756a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    config.buffer_count = 2;
757a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    config.codec_type = CODEC_TYPE_PCM;
758a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    status = ioctl(mFd, AUDIO_SET_CONFIG, &config);
759a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    if (status < 0) {
760a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        LOGE("Cannot set config");
761a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        goto Error;
762a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
763a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
764a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    LOGV("confirm config");
765a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    status = ioctl(mFd, AUDIO_GET_CONFIG, &config);
766a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    if (status < 0) {
767a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        LOGE("Cannot read config");
768a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        goto Error;
769a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
770a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    LOGV("buffer_size: %u", config.buffer_size);
771a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    LOGV("buffer_count: %u", config.buffer_count);
772a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    LOGV("channel_count: %u", config.channel_count);
773a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    LOGV("sample_rate: %u", config.sample_rate);
774a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
7757510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    mFormat = format;
7767510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    mChannelCount = config.channel_count;
7777510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    mSampleRate = config.sample_rate;
7787510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    mBufferSize = config.buffer_size;
7797510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project
780a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    mHardware = hw;
781a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    mHardware->setMicMute_nosync(false);
7827510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    mState = AUDIO_INPUT_OPENED;
7837510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    audpre_index = calculate_audpre_table_index(sampleRate);
7847510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    tx_iir_index = (audpre_index * 2) + (hw->checkOutputStandby() ? 0 : 1);
7857510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    LOGD("audpre_index = %d, tx_iir_index = %d\n", audpre_index, tx_iir_index);
7867510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project
7877510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    /**
7887510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project     * If audio-preprocessing failed, we should not block record.
7897510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project     */
7907510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    int (*msm72xx_set_audpre_params)(int, int);
7917510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    msm72xx_set_audpre_params = (int (*)(int, int))::dlsym(acoustic, "msm72xx_set_audpre_params");
7927510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    status = msm72xx_set_audpre_params(audpre_index, tx_iir_index);
7937510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    if (status < 0)
7947510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        LOGE("Cannot set audpre parameters");
7957510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project
7967510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    int (*msm72xx_enable_audpre)(int, int, int);
7977510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    msm72xx_enable_audpre = (int (*)(int, int, int))::dlsym(acoustic, "msm72xx_enable_audpre");
7987510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    mAcoustics = acoustic_flags;
7997510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    status = msm72xx_enable_audpre((int)acoustic_flags, audpre_index, tx_iir_index);
8007510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    if (status < 0)
8017510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        LOGE("Cannot enable audpre");
8027510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project
803a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    return NO_ERROR;
804a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
805a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian SwetlandError:
806a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    if (mFd > 0) {
807a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        ::close(mFd);
808a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        mFd = -1;
809a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
810a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    return status;
811a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
812a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
813a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian SwetlandAudioHardware::AudioStreamInMSM72xx::~AudioStreamInMSM72xx()
814a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
8157510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    LOGV("AudioStreamInMSM72xx destructor");
8167510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    if (mHardware) {
8177510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        standby();
8187510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        mHardware->closeInputStream(this);
8197510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    }
820a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
821a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
822a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandssize_t AudioHardware::AudioStreamInMSM72xx::read( void* buffer, ssize_t bytes)
823a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
824d066973de83218a24c773e5de04d10ed2d730873Eric Laurent    LOGV("AudioStreamInMSM72xx::read(%p, %ld)", buffer, bytes);
8257510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    if (!mHardware) return -1;
826a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
827a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    size_t count = bytes;
828a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    uint8_t* p = static_cast<uint8_t*>(buffer);
829a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
8307510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    if (mState < AUDIO_INPUT_OPENED) {
831d066973de83218a24c773e5de04d10ed2d730873Eric Laurent        Mutex::Autolock lock(mHardware->mLock);
8327510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        if (set(mHardware, mFormat, mChannelCount, mSampleRate, mAcoustics) != NO_ERROR) {
8337510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project            return -1;
8347510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        }
8357510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    }
8367510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project
8377510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    if (mState < AUDIO_INPUT_STARTED) {
838a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        if (ioctl(mFd, AUDIO_START, 0)) {
839a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            LOGE("Error starting record");
840a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            return -1;
841a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        }
8427510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        mState = AUDIO_INPUT_STARTED;
843a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
844a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
845a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    while (count) {
846a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        ssize_t bytesRead = ::read(mFd, buffer, count);
847a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        if (bytesRead >= 0) {
848a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            count -= bytesRead;
849a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            p += bytesRead;
850a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        } else {
851a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            if (errno != EAGAIN) return bytesRead;
852a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            mRetryCount++;
853a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland            LOGW("EAGAIN - retrying");
854a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland        }
855a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    }
856a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    return bytes;
857a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
858a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
8597510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Projectstatus_t AudioHardware::AudioStreamInMSM72xx::standby()
8607510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project{
8617510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    if (!mHardware) return -1;
8627510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    if (mState > AUDIO_INPUT_CLOSED) {
8637510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        if (mFd > 0) {
8647510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project            ::close(mFd);
8657510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project            mFd = -1;
8667510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        }
8677510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        mHardware->checkMicMute();
8687510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project        mState = AUDIO_INPUT_CLOSED;
8697510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    }
8707510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    return NO_ERROR;
8717510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project}
8727510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project
873a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandstatus_t AudioHardware::AudioStreamInMSM72xx::dump(int fd, const Vector<String16>& args)
874a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland{
875a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    const size_t SIZE = 256;
876a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    char buffer[SIZE];
877a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    String8 result;
878a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    result.append("AudioStreamInMSM72xx::dump\n");
879a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    snprintf(buffer, SIZE, "\tsample rate: %d\n", sampleRate());
880a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    result.append(buffer);
881a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    snprintf(buffer, SIZE, "\tbuffer size: %d\n", bufferSize());
882a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    result.append(buffer);
883a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    snprintf(buffer, SIZE, "\tchannel count: %d\n", channelCount());
884a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    result.append(buffer);
885a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    snprintf(buffer, SIZE, "\tformat: %d\n", format());
886a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    result.append(buffer);
887a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    snprintf(buffer, SIZE, "\tmHardware: %p\n", mHardware);
888a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    result.append(buffer);
889a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    snprintf(buffer, SIZE, "\tmFd count: %d\n", mFd);
890a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    result.append(buffer);
8917510aaf4b3a3c545d943b09e0fb9f56ea2fc5e24The Android Open Source Project    snprintf(buffer, SIZE, "\tmState: %d\n", mState);
892a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    result.append(buffer);
893a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    snprintf(buffer, SIZE, "\tmRetryCount: %d\n", mRetryCount);
894a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    result.append(buffer);
895a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    ::write(fd, result.string(), result.size());
896a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    return NO_ERROR;
897a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
898a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
899a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland// ----------------------------------------------------------------------------
900a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
901a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetlandextern "C" AudioHardwareInterface* createAudioHardware(void) {
902a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland    return new AudioHardware();
903a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}
904a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland
905a3a947cc7e1bfaf7b5cfc85b71f602edf562836Brian Swetland}; // namespace android
906