165e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland/*
265e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland** Copyright 2008, The Android Open-Source Project
365e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland**
465e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland** Licensed under the Apache License, Version 2.0 (the "License");
565e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland** you may not use this file except in compliance with the License.
665e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland** You may obtain a copy of the License at
765e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland**
865e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland**     http://www.apache.org/licenses/LICENSE-2.0
965e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland**
1065e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland** Unless required by applicable law or agreed to in writing, software
1165e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland** distributed under the License is distributed on an "AS IS" BASIS,
1265e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1365e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland** See the License for the specific language governing permissions and
1465e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland** limitations under the License.
1565e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland*/
1665e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
1765e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland#include <math.h>
1865e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
1965e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland//#define LOG_NDEBUG 0
2065e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland#define LOG_TAG "AudioHardware"
2165e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
2265e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland#include <utils/Log.h>
2365e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland#include <utils/String8.h>
2465e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland//#include <hardware_legacy/power.h>
2565e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
2665e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland#include <stdio.h>
2765e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland#include <unistd.h>
2865e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland#include <sys/ioctl.h>
2965e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland#include <sys/types.h>
3065e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland#include <sys/stat.h>
3165e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland#include <dlfcn.h>
3265e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland#include <fcntl.h>
3365e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
3465e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland#include "AudioHardware.h"
3565e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland#include <media/AudioRecord.h>
3665e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
3765e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetlandextern "C" {
3865e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland#include "msm_audio.h"
3965e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland}
4065e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
4165e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
4265e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetlandnamespace android {
4365e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland// ----------------------------------------------------------------------------
4465e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
4565e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian SwetlandAudioHardware::AudioHardware() :
4665e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    mInit(false), mMicMute(true), mOutput(0)
4765e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland{
4865e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    mInit = true;
4965e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland}
5065e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
5165e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian SwetlandAudioHardware::~AudioHardware()
5265e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland{
5365e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    closeOutputStream((AudioStreamOut*)mOutput);
5465e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    mInit = false;
5565e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland}
5665e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
5765e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetlandstatus_t AudioHardware::initCheck()
5865e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland{
5965e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    return mInit ? NO_ERROR : NO_INIT;
6065e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland}
6165e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
6265e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian SwetlandAudioStreamOut* AudioHardware::openOutputStream(
6365e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status)
6465e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland{
6565e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    { // scope for the lock
6665e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        Mutex::Autolock lock(mLock);
6765e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
6865e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        // only one output stream allowed
6965e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        if (mOutput) {
7065e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland            if (status) {
7165e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland                *status = INVALID_OPERATION;
7265e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland            }
7365e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland            return 0;
7465e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        }
7565e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
7665e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        AudioStreamOutQ5V2* out = new AudioStreamOutQ5V2();
7765e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
7865e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        status_t rc = out->set(this, devices, format, channels, sampleRate);
7965e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        if (rc) {
8065e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland            *status = rc;
8165e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        }
8265e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        if (rc == NO_ERROR) {
8365e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland            mOutput = out;
8465e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        } else {
8565e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland            delete out;
8665e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        }
8765e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    }
8865e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    return mOutput;
8965e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland}
9065e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
9165e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetlandvoid AudioHardware::closeOutputStream(AudioStreamOut* out) {
9265e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    Mutex::Autolock lock(mLock);
9365e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    if (mOutput == 0 || mOutput != out) {
9465e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        LOGW("Attempt to close invalid output stream");
9565e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    }
9665e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    else {
9765e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        delete mOutput;
9865e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        mOutput = 0;
9965e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    }
10065e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland}
10165e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
10265e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian SwetlandAudioStreamIn* AudioHardware::openInputStream(
10365e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        uint32_t devices, int *format, uint32_t *channels, uint32_t *sampleRate, status_t *status,
10465e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        AudioSystem::audio_in_acoustics acoustic_flags)
10565e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland{
10665e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    return 0;
10765e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland}
10865e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
10965e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetlandvoid AudioHardware::closeInputStream(AudioStreamIn* in) {
11065e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland}
11165e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
11265e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetlandstatus_t AudioHardware::setMode(int mode)
11365e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland{
11465e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    return NO_ERROR;
11565e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland}
11665e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
11765e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetlandstatus_t AudioHardware::setMicMute(bool state)
11865e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland{
11965e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    return NO_ERROR;
12065e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland}
12165e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
12265e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetlandstatus_t AudioHardware::getMicMute(bool* state)
12365e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland{
12465e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    *state = mMicMute;
12565e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    return NO_ERROR;
12665e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland}
12765e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
12865e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetlandstatus_t AudioHardware::setParameters(const String8& keyValuePairs)
12965e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland{
13065e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    return NO_ERROR;
13165e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland}
13265e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
13365e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian SwetlandString8 AudioHardware::getParameters(const String8& keys)
13465e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland{
13565e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    AudioParameter request = AudioParameter(keys);
13665e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    AudioParameter reply = AudioParameter();
13765e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
13865e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    LOGV("getParameters() %s", keys.string());
13965e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
14065e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    return reply.toString();
14165e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland}
14265e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
14365e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetlandsize_t AudioHardware::getInputBufferSize(uint32_t sampleRate, int format, int channelCount)
14465e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland{
14565e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    return 4096;
14665e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland}
14765e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
14865e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetlandstatus_t AudioHardware::setVoiceVolume(float v)
14965e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland{
15065e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    return NO_ERROR;
15165e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland}
15265e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
15365e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetlandstatus_t AudioHardware::setMasterVolume(float v)
15465e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland{
15565e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    LOGI("Set master volume to %f.\n", v);
15665e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    // We return an error code here to let the audioflinger do in-software
15765e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    // volume on top of the maximum volume that we set through the SND API.
15865e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    // return error - software mixer will handle it
15965e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    return -1;
16065e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland}
16165e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
16265e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetlandstatus_t AudioHardware::dump(int fd, const Vector<String16>& args)
16365e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland{
16465e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    return NO_ERROR;
16565e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland}
16665e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
16765e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian SwetlandAudioHardware::AudioStreamOutQ5V2::AudioStreamOutQ5V2() :
16865e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    mHardware(0), mFd(-1), mStartCount(0), mRetryCount(0), mStandby(true),
16965e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    mDevices(0), mChannels(AUDIO_HW_OUT_CHANNELS), mSampleRate(AUDIO_HW_OUT_SAMPLERATE),
17065e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    mBufferSize(AUDIO_HW_OUT_BUFSZ)
17165e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland{
17265e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland}
17365e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
17465e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetlandstatus_t AudioHardware::AudioStreamOutQ5V2::set(
17565e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        AudioHardware* hw, uint32_t devices, int *pFormat, uint32_t *pChannels, uint32_t *pRate)
17665e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland{
17765e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    int lFormat = pFormat ? *pFormat : 0;
17865e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    uint32_t lChannels = pChannels ? *pChannels : 0;
17965e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    uint32_t lRate = pRate ? *pRate : 0;
18065e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
18165e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    mHardware = hw;
18265e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    mDevices = devices;
18365e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
18465e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    // fix up defaults
18565e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    if (lFormat == 0) lFormat = format();
18665e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    if (lChannels == 0) lChannels = channels();
18765e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    if (lRate == 0) lRate = sampleRate();
18865e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
18965e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    // check values
19065e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    if ((lFormat != format()) ||
19165e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        (lChannels != channels()) ||
19265e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        (lRate != sampleRate())) {
19365e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        if (pFormat) *pFormat = format();
19465e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        if (pChannels) *pChannels = channels();
19565e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        if (pRate) *pRate = sampleRate();
19665e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        return BAD_VALUE;
19765e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    }
19865e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
19965e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    if (pFormat) *pFormat = lFormat;
20065e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    if (pChannels) *pChannels = lChannels;
20165e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    if (pRate) *pRate = lRate;
20265e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
20365e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    mChannels = lChannels;
20465e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    mSampleRate = lRate;
20565e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    mBufferSize = 4096;
20665e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
20765e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    return NO_ERROR;
20865e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland}
20965e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
21065e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian SwetlandAudioHardware::AudioStreamOutQ5V2::~AudioStreamOutQ5V2()
21165e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland{
21265e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    standby();
21365e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland}
21465e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
21565e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetlandssize_t AudioHardware::AudioStreamOutQ5V2::write(const void* buffer, size_t bytes)
21665e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland{
21765e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    // LOGD("AudioStreamOutQ5V2::write(%p, %u)", buffer, bytes);
21865e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    status_t status = NO_INIT;
21965e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    size_t count = bytes;
22065e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    const uint8_t* p = static_cast<const uint8_t*>(buffer);
22165e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
22265e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    if (mStandby) {
22365e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        LOGV("open pcm_out driver");
22465e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        status = ::open("/dev/msm_pcm_out", O_RDWR);
22565e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        if (status < 0) {
22665e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland                LOGE("Cannot open /dev/msm_pcm_out errno: %d", errno);
22765e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland            goto Error;
22865e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        }
22965e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        mFd = status;
23065e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
23165e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        // configuration
23265e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        LOGV("get config");
23365e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        struct msm_audio_config config;
23465e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        status = ioctl(mFd, AUDIO_GET_CONFIG, &config);
23565e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        if (status < 0) {
23665e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland            LOGE("Cannot read pcm_out config");
23765e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland            goto Error;
23865e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        }
23965e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
24065e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        LOGV("set pcm_out config");
24165e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        config.channel_count = AudioSystem::popCount(channels());
24265e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        config.sample_rate = mSampleRate;
24365e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        config.buffer_size = mBufferSize;
24465e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        config.buffer_count = AUDIO_HW_NUM_OUT_BUF;
24565e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland//        config.codec_type = CODEC_TYPE_PCM;
24665e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        status = ioctl(mFd, AUDIO_SET_CONFIG, &config);
24765e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        if (status < 0) {
24865e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland            LOGE("Cannot set config");
24965e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland            goto Error;
25065e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        }
25165e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
25265e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        LOGV("buffer_size: %u", config.buffer_size);
25365e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        LOGV("buffer_count: %u", config.buffer_count);
25465e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        LOGV("channel_count: %u", config.channel_count);
25565e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        LOGV("sample_rate: %u", config.sample_rate);
25665e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
25765e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland#if 0
25865e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        status = ioctl(mFd, AUDIO_START, &acdb_id);
25965e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        if (status < 0) {
26065e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland            LOGE("Cannot start pcm playback");
26165e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland            goto Error;
26265e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        }
26365e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
26465e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        status = ioctl(mFd, AUDIO_SET_VOLUME, &stream_volume);
26565e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        if (status < 0) {
26665e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland            LOGE("Cannot start pcm playback");
26765e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland            goto Error;
26865e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        }
26965e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland#endif
27065e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        mStandby = false;
27165e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    }
27265e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
27365e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    while (count) {
27465e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        ssize_t written = ::write(mFd, p, count);
27565e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        if (written >= 0) {
27665e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland            count -= written;
27765e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland            p += written;
27865e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        } else {
27965e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland            if (errno != EAGAIN) return written;
28065e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland            mRetryCount++;
28165e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland            LOGW("EAGAIN - retry");
28265e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        }
28365e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    }
28465e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
28565e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    return bytes;
28665e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
28765e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian SwetlandError:
28865e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    if (mFd >= 0) {
28965e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        ::close(mFd);
29065e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        mFd = -1;
29165e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    }
29265e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    // Simulate audio output timing in case of error
29365e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    usleep(bytes * 1000000 / frameSize() / sampleRate());
29465e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
29565e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    return status;
29665e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland}
29765e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
29865e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetlandstatus_t AudioHardware::AudioStreamOutQ5V2::standby()
29965e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland{
30065e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    status_t status = NO_ERROR;
30165e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    if (!mStandby && mFd >= 0) {
30265e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        ::close(mFd);
30365e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland        mFd = -1;
30465e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    }
30565e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    mStandby = true;
30665e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    LOGI("AudioHardware pcm playback is going to standby.");
30765e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    return status;
30865e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland}
30965e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
31065e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetlandstatus_t AudioHardware::AudioStreamOutQ5V2::dump(int fd, const Vector<String16>& args)
31165e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland{
31265e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    return NO_ERROR;
31365e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland}
31465e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
31565e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetlandbool AudioHardware::AudioStreamOutQ5V2::checkStandby()
31665e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland{
31765e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    return mStandby;
31865e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland}
31965e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
32065e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetlandstatus_t AudioHardware::AudioStreamOutQ5V2::setParameters(const String8& keyValuePairs)
32165e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland{
32265e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    return NO_ERROR;
32365e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland}
32465e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
32565e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian SwetlandString8 AudioHardware::AudioStreamOutQ5V2::getParameters(const String8& keys)
32665e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland{
32765e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    AudioParameter param = AudioParameter(keys);
32865e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    LOGV("AudioStreamOutQ5V2::getParameters() %s", param.toString().string());
32965e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    return param.toString();
33065e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland}
33165e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
33265e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetlandstatus_t AudioHardware::AudioStreamOutQ5V2::getRenderPosition(uint32_t *dspFrames)
33365e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland{
33465e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    return INVALID_OPERATION;
33565e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland}
33665e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
33765e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetlandextern "C" AudioHardwareInterface* createAudioHardware(void) {
33865e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland    return new AudioHardware();
33965e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland}
34065e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland
34165e6c49fb6a8872a5e36fa479c4ed9f9fceba43cBrian Swetland}; // namespace android
342