Browse files

resolved conflicts for merge of e6fda490 to master

Change-Id: Ia943cf3acdb56bdda1c28a3942dde2e6565d4b13
  • Loading branch information...
1 parent 75858c7 commit a5e2cc87f66a6806bdabb3f63b277116c270a618 @wangying1015 wangying1015 committed Feb 18, 2011
Showing with 144 additions and 109 deletions.
  1. BIN bcm4329.ko
  2. BIN kernel
  3. +126 −101 libaudio/AudioHardware.cpp
  4. +14 −3 libaudio/AudioHardware.h
  5. +1 −0 taudio/resample.c
  6. +3 −5 taudio/twav.c
View
BIN bcm4329.ko
Binary file not shown.
View
BIN kernel
Binary file not shown.
View
227 libaudio/AudioHardware.cpp
@@ -48,7 +48,7 @@ AudioHardware::AudioHardware() :
mOutput(0), /*mCurOut/InDevice*/ mCpcapCtlFd(-1), mHwOutRate(0), mHwInRate(0),
mMasterVol(1.0), mVoiceVol(1.0),
/*mCpcapGain*/
- mSpkrVolume(-1), mMicVolume(-1)
+ mSpkrVolume(-1), mMicVolume(-1), mEcnsEnabled(false), mBtScoOn(false)
{
LOGV("AudioHardware constructor");
}
@@ -675,29 +675,30 @@ status_t AudioHardware::doRouting_l()
mCurOutDevice.on ? "on" : "off");
}
- bool ecnsEnabled = false;
+ mEcnsEnabled = false;
// enable EC if:
// - the audio mode is IN_CALL or IN_COMMUNICATION AND
// - the output stream is active AND
// - an input stream with VOICE_COMMUNICATION source is active
if (isInCall() && !mOutput->getStandby() &&
input && input->source() == AUDIO_SOURCE_VOICE_COMMUNICATION) {
- ecnsEnabled = true;
+ mEcnsEnabled = true;
}
- int oldInRate=mHwInRate, oldOutRate=mHwOutRate;
#ifdef USE_PROPRIETARY_AUDIO_EXTENSIONS
- int ecnsRate = getActiveInputRate() < 16000? 8000 : 16000;
+ int ecnsRate = (btScoOn || (getActiveInputRate() < 16000)) ? 8000 : 16000;
// Check input/output rates for HW.
- if (ecnsEnabled) {
+ if (mEcnsEnabled) {
mHwInRate = ecnsRate;
mHwOutRate = mHwInRate;
LOGD("EC/NS active, requests rate as %d for in/out", mHwInRate);
}
else
#endif
{
- mHwInRate = getActiveInputRate();
+ if (input) {
+ mHwInRate = getActiveInputRate();
+ }
mHwOutRate = AUDIO_HW_OUT_SAMPLERATE;
LOGV("No EC/NS, set input rate %d, output %d.", mHwInRate, mHwOutRate);
}
@@ -712,60 +713,60 @@ status_t AudioHardware::doRouting_l()
if (!input->isLocked()) {
input->lock();
}
- if (mHwInRate != oldInRate) {
- LOGV("Minor TODO: Flush input if active.");
- if (::ioctl(mCpcapCtlFd, CPCAP_AUDIO_IN_SET_RATE,
- mHwInRate) < 0)
- LOGE("could not set input rate(%d): %s",
- mHwInRate, strerror(errno));
- if (::ioctl(mCpcapCtlFd, CPCAP_AUDIO_IN_GET_RATE, &mHwInRate))
- LOGE("CPCAP driver error reading rates: %s", strerror(errno));
- }
}
-
// acquire mutex if not already locked by write()
if (!mOutput->isLocked()) {
mOutput->lock();
}
- int speakerOutRate = 0;
- if (::ioctl(mCpcapCtlFd, CPCAP_AUDIO_OUT_GET_RATE, &speakerOutRate))
- LOGE("could not read output rate: %s",
- strerror(errno));
- if (mHwOutRate != oldOutRate ||
- (speakerOutRate!=AUDIO_HW_OUT_SAMPLERATE && btScoOn)) {
- int speaker_rate = mHwOutRate;
- if (btScoOn) {
- speaker_rate = AUDIO_HW_OUT_SAMPLERATE;
- }
- // Flush old data (wrong rate) from I2S driver before changing rate.
- if (mOutput) {
- mOutput->flush();
- if (ecnsEnabled) {
- mOutput->setNumBufs(AUDIO_HW_NUM_OUT_BUF);
- } else {
- mOutput->setNumBufs(AUDIO_HW_NUM_OUT_BUF_LONG);
- }
- }
- // Now the DMA is empty, change the rate.
- if (::ioctl(mCpcapCtlFd, CPCAP_AUDIO_OUT_SET_RATE,
- speaker_rate) < 0)
- LOGE("could not set output rate(%d): %s",
- speaker_rate, strerror(errno));
- }
#ifdef USE_PROPRIETARY_AUDIO_EXTENSIONS
mAudioPP.setAudioDev(&mCurOutDevice, &mCurInDevice,
btScoOn, mBluetoothNrec,
spdifOutDevices?true:false);
- mAudioPP.enableEcns(ecnsEnabled);
+ mAudioPP.enableEcns(mEcnsEnabled);
#endif
mOutput->setDriver_l(speakerOutDevices?true:false,
btScoOn,
spdifOutDevices?true:false, mHwOutRate);
+
if (input) {
input->setDriver_l(micInDevice?true:false,
- btScoInDevice?true:false, mHwInRate);
+ btScoOn, mHwInRate);
}
+
+ // Changing I2S to port connection when bluetooth starts or stopS must be done simultaneously
+ // for input and output while both DMAs are stopped
+ if (btScoOn != mBtScoOn) {
+ if (input) {
+ input->lockFd();
+ input->stop_l();
+ }
+ mOutput->lockFd();
+ mOutput->flush_l();
+
+ int bit_format = TEGRA_AUDIO_BIT_FORMAT_DEFAULT;
+ bool is_bt_bypass = false;
+ if (btScoOn) {
+ bit_format = TEGRA_AUDIO_BIT_FORMAT_DSP;
+ is_bt_bypass = true;
+ }
+ LOGV("%s: bluetooth state changed. is_bt_bypass %d bit_format %d",
+ __FUNCTION__, is_bt_bypass, bit_format);
+ // Setup the I2S2-> DAP2/4 capture/playback path.
+ if (::ioctl(mOutput->mBtFdIoCtl, TEGRA_AUDIO_SET_BIT_FORMAT, &bit_format) < 0) {
+ LOGE("could not set bit format %s", strerror(errno));
+ }
+ if (::ioctl(mCpcapCtlFd, CPCAP_AUDIO_SET_BLUETOOTH_BYPASS, is_bt_bypass) < 0) {
+ LOGE("could not set bluetooth bypass %s", strerror(errno));
+ }
+
+ mBtScoOn = btScoOn;
+ mOutput->unlockFd();
+ if (input) {
+ input->unlockFd();
+ }
+ }
+
if (!mOutput->isLocked()) {
mOutput->unlock();
}
@@ -775,7 +776,7 @@ status_t AudioHardware::doRouting_l()
// Since HW path may have changed, set the hardware gains.
int useCase = AUDIO_HW_GAIN_USECASE_MM;
- if (ecnsEnabled) {
+ if (mEcnsEnabled) {
useCase = AUDIO_HW_GAIN_USECASE_VOICE;
} else if (input && input->source() == AUDIO_SOURCE_VOICE_RECOGNITION) {
useCase = AUDIO_HW_GAIN_USECASE_VOICE_REC;
@@ -849,17 +850,21 @@ AudioHardware::AudioStreamInTegra *AudioHardware::getActiveInput_l()
//
#ifdef USE_PROPRIETARY_AUDIO_EXTENSIONS
AudioHardware::AudioStreamSrc::AudioStreamSrc() :
- mSrcInitted(false)
+ mSrcBuffer(NULL), mSrcInitted(false)
{
}
AudioHardware::AudioStreamSrc::~AudioStreamSrc()
{
+ if (mSrcBuffer != NULL) {
+ delete[] mSrcBuffer;
+ }
}
void AudioHardware::AudioStreamSrc::init(int inRate, int outRate)
{
- if (mSrcBuffer == NULL)
+ if (mSrcBuffer == NULL) {
mSrcBuffer = new char[src_memory_required_stereo(MAX_FRAME_LEN, MAX_CONVERT_RATIO)];
+ }
if (mSrcBuffer == NULL) {
LOGE("Failed to allocate memory for sample rate converter.");
return;
@@ -883,8 +888,8 @@ void AudioHardware::AudioStreamSrc::init(int inRate, int outRate)
// always succeeds, must call init() immediately after
AudioHardware::AudioStreamOutTegra::AudioStreamOutTegra() :
- mHardware(0), mFd(-1), mFdCtl(-1),
- mBtFd(-1), mBtFdCtl(-1), mBtFdIoCtl(-1),
+ mBtFdIoCtl(-1), mHardware(0), mFd(-1), mFdCtl(-1),
+ mBtFd(-1), mBtFdCtl(-1),
mSpdifFd(-1), mSpdifFdCtl(-1),
mStartCount(0), mRetryCount(0), mDevices(0),
mIsSpkrEnabled(false), mIsBtEnabled(false), mIsSpdifEnabled(false),
@@ -948,9 +953,6 @@ status_t AudioHardware::AudioStreamOutTegra::initCheck()
void AudioHardware::AudioStreamOutTegra::setDriver_l(
bool speaker, bool bluetooth, bool spdif, int sampleRate)
{
- int bit_format = TEGRA_AUDIO_BIT_FORMAT_DEFAULT;
- bool is_bt_bypass = false;
-
LOGV("%s: Analog speaker? %s. Bluetooth? %s. S/PDIF? %s. sampleRate %d", __FUNCTION__,
speaker?"yes":"no", bluetooth?"yes":"no", spdif?"yes":"no", sampleRate);
@@ -1239,6 +1241,11 @@ void AudioHardware::AudioStreamOutTegra::flush()
{
// Prevent someone from writing the fd while we flush
Mutex::Autolock lock(mFdLock);
+ flush_l();
+}
+
+void AudioHardware::AudioStreamOutTegra::flush_l()
+{
LOGD("AudioStreamOutTegra::flush()");
if (::ioctl(mFdCtl, TEGRA_AUDIO_OUT_FLUSH) < 0)
LOGE("could not flush playback: %s", strerror(errno));
@@ -1287,28 +1294,27 @@ status_t AudioHardware::AudioStreamOutTegra::online_l()
}
mIsSpkrEnabled = mIsSpkrEnabledReq;
- if ((mIsBtEnabled && !mIsBtEnabledReq) ||
- (mIsSpdifEnabled && !mIsSpdifEnabledReq)) {
- flush();
- }
mIsBtEnabled = mIsBtEnabledReq;
mIsSpdifEnabled = mIsSpdifEnabledReq;
- int bit_format = TEGRA_AUDIO_BIT_FORMAT_DEFAULT;
- bool is_bt_bypass = false;
- if (mIsBtEnabled) {
- bit_format = TEGRA_AUDIO_BIT_FORMAT_DSP;
- is_bt_bypass = true;
- }
- // Setup the I2S2-> DAP2/4 capture/playback path.
- if (::ioctl(mBtFdIoCtl, TEGRA_AUDIO_SET_BIT_FORMAT, &bit_format) < 0) {
- LOGE("could not set bit format %s", strerror(errno));
- }
- if (::ioctl(mHardware->mCpcapCtlFd, CPCAP_AUDIO_SET_BLUETOOTH_BYPASS, is_bt_bypass) < 0) {
- LOGE("could not set bluetooth bypass %s", strerror(errno));
- }
+ }
+ // Flush old data (wrong rate) from I2S driver before changing rate.
+ flush();
+ if (mHardware->mEcnsEnabled) {
+ setNumBufs(AUDIO_HW_NUM_OUT_BUF);
+ } else {
+ setNumBufs(AUDIO_HW_NUM_OUT_BUF_LONG);
+ }
+ int speaker_rate = mHardware->mHwOutRate;
+ if (mIsBtEnabled) {
+ speaker_rate = AUDIO_HW_OUT_SAMPLERATE;
}
+ // Now the DMA is empty, change the rate.
+ if (::ioctl(mHardware->mCpcapCtlFd, CPCAP_AUDIO_OUT_SET_RATE,
+ speaker_rate) < 0)
+ LOGE("could not set output rate(%d): %s",
+ speaker_rate, strerror(errno));
mDriverRate = mHardware->mHwOutRate;
@@ -1507,15 +1513,6 @@ AudioHardware::AudioStreamInTegra::~AudioStreamInTegra()
standby();
- if (mFd >= 0) {
- ::close(mFd);
- mFd = -1;
- }
-
- if (mFdCtl >= 0) {
- ::close(mFdCtl);
- mFdCtl = -1;
- }
}
// Called with mHardware->mLock and mLock held.
@@ -1597,15 +1594,17 @@ ssize_t AudioHardware::AudioStreamInTegra::read(void* buffer, ssize_t bytes)
status = NO_INIT;
goto error;
}
- reopenReconfigDriver();
}
} else {
hwReadBytes = bytes;
inbuf = (int16_t *)buffer;
mSrc.deinit();
}
// Read from driver, or ECNS thread, as appropriate.
- ret = mHardware->mAudioPP.read(mFd, inbuf, hwReadBytes, mDriverRate);
+ {
+ Mutex::Autolock dfl(mFdLock);
+ ret = mHardware->mAudioPP.read(mFd, inbuf, hwReadBytes, mDriverRate);
+ }
if (ret>0 && srcReqd) {
mSrc.mIoData.in_buf_ch1 = (SRC16 *) (inbuf);
mSrc.mIoData.in_buf_ch2 = 0;
@@ -1626,7 +1625,10 @@ ssize_t AudioHardware::AudioStreamInTegra::read(void* buffer, ssize_t bytes)
status = INVALID_OPERATION;
goto error;
}
- ret = ::read(mFd, buffer, hwReadBytes);
+ {
+ Mutex::Autolock dfl(mFdLock);
+ ret = ::read(mFd, buffer, hwReadBytes);
+ }
#endif
// It is not optimal to mute after all the above processing but it is necessary to
@@ -1645,7 +1647,10 @@ ssize_t AudioHardware::AudioStreamInTegra::read(void* buffer, ssize_t bytes)
goto error;
}
- mTotalBuffersRead++;
+ {
+ Mutex::Autolock _fl(mFramesLock);
+ mTotalBuffersRead++;
+ }
return ret;
}
@@ -1696,9 +1701,30 @@ status_t AudioHardware::AudioStreamInTegra::online_l()
{
status_t status = NO_ERROR;
+ reopenReconfigDriver();
+
if (mState < AUDIO_STREAM_NEW_RATE_REQ) {
- reopenReconfigDriver();
+ // Use standby to flush the driver. mHardware->mLock should already be held
+
+ mHardware->doStandby(mFdCtl, false, true);
+ if (mDevices & ~AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
+ status = mHardware->doStandby(mFdCtl, false, false);
+ }
+
+ if (mState == AUDIO_STREAM_IDLE) {
+ mState = AUDIO_STREAM_CONFIG_REQ;
+ LOGV("input %p going online", this);
+ // setDriver_l() will not try to lock mLock when called by doRouting_l()
+ mLocked = true;
+ mHardware->doRouting_l();
+ mLocked = false;
+ {
+ Mutex::Autolock _fl(mFramesLock);
+ mTotalBuffersRead = 0;
+ mStartTimeNs = systemTime();
+ }
+ }
// configuration
struct tegra_audio_in_config config;
@@ -1708,7 +1734,7 @@ status_t AudioHardware::AudioStreamInTegra::online_l()
return status;
}
config.stereo = AudioSystem::popCount(mChannels) == 2;
- config.rate = mSampleRate;
+ config.rate = mHardware->mHwInRate;
status = ::ioctl(mFdCtl, TEGRA_AUDIO_IN_SET_CONFIG, &config);
if (status < 0) {
@@ -1722,27 +1748,15 @@ status_t AudioHardware::AudioStreamInTegra::online_l()
}
}
- // Use standby to flush the driver. mHardware->mLock should already be held
- mHardware->doStandby(mFdCtl, false, true);
- if (mDevices & ~AudioSystem::DEVICE_IN_BLUETOOTH_SCO_HEADSET) {
- status = mHardware->doStandby(mFdCtl, false, false);
- }
-
- if (mState == AUDIO_STREAM_IDLE) {
- mState = AUDIO_STREAM_CONFIG_REQ;
- LOGV("input %p going online", this);
- // setDriver_l() will not try to lock mLock when called by doRouting_l()
- mLocked = true;
- mHardware->doRouting_l();
- mLocked = false;
- mTotalBuffersRead = 0;
- mStartTimeNs = systemTime();
- }
}
mDriverRate = mHardware->mHwInRate;
+ if (::ioctl(mHardware->mCpcapCtlFd, CPCAP_AUDIO_IN_SET_RATE,
+ mDriverRate) < 0)
+ LOGE("could not set input rate(%d): %s", mDriverRate, strerror(errno));
+
mState = AUDIO_STREAM_CONFIGURED;
return status;
@@ -1781,6 +1795,7 @@ void AudioHardware::AudioStreamInTegra::reopenReconfigDriver()
}
}
+
status_t AudioHardware::AudioStreamInTegra::dump(int fd, const Vector<String16>& args)
{
const size_t SIZE = 256;
@@ -1858,7 +1873,7 @@ String8 AudioHardware::AudioStreamInTegra::getParameters(const String8& keys)
unsigned int AudioHardware::AudioStreamInTegra::getInputFramesLost() const
{
- Mutex::Autolock _l(mLock);
+ Mutex::Autolock _l(mFramesLock);
unsigned int lostFrames = 0;
if (!getStandby()) {
unsigned int framesPerBuffer = bufferSize() / frameSize();
@@ -1878,6 +1893,16 @@ unsigned int AudioHardware::AudioStreamInTegra::getInputFramesLost() const
return lostFrames;
}
+// must be called with mLock and mFdLock held
+void AudioHardware::AudioStreamInTegra::stop_l()
+{
+ LOGV("AudioStreamInTegra::stop_l() starts");
+ if (::ioctl(mFdCtl, TEGRA_AUDIO_IN_STOP) < 0) {
+ LOGE("could not stop recording: %d %s", errno, strerror(errno));
+ }
+ LOGV("AudioStreamInTegra::stop_l() returns");
+}
+
// ----------------------------------------------------------------------------
extern "C" AudioHardwareInterface* createAudioHardware(void) {
View
17 libaudio/AudioHardware.h
@@ -198,10 +198,11 @@ class AudioHardware : public AudioHardwareBase
virtual size_t bufferSize() const { return 4096; }
virtual uint32_t channels() const { return AudioSystem::CHANNEL_OUT_STEREO; }
virtual int format() const { return AudioSystem::PCM_16_BIT; }
- virtual uint32_t latency() const { return (1000*AUDIO_HW_NUM_OUT_BUF*(bufferSize()/frameSize()))/sampleRate()+AUDIO_HW_OUT_LATENCY_MS; }
+ virtual uint32_t latency() const { return (1000*AUDIO_HW_NUM_OUT_BUF_LONG*(bufferSize()/frameSize()))/sampleRate()+AUDIO_HW_OUT_LATENCY_MS; }
virtual status_t setVolume(float left, float right) { return INVALID_OPERATION; }
virtual ssize_t write(const void* buffer, size_t bytes);
void flush();
+ void flush_l();
virtual status_t standby();
status_t online_l();
virtual status_t dump(int fd, const Vector<String16>& args);
@@ -214,6 +215,10 @@ class AudioHardware : public AudioHardwareBase
void unlock() { mLock.unlock(); }
bool isLocked() { return mLocked; }
void setNumBufs(int numBufs);
+ void lockFd() { mFdLock.lock(); }
+ void unlockFd() { mFdLock.unlock(); }
+
+ int mBtFdIoCtl;
private:
AudioHardware* mHardware;
@@ -222,7 +227,6 @@ class AudioHardware : public AudioHardwareBase
int mFdCtl;
int mBtFd;
int mBtFdCtl;
- int mBtFdIoCtl;
int mSpdifFd;
int mSpdifFdCtl;
int mStartCount;
@@ -275,12 +279,15 @@ class AudioHardware : public AudioHardwareBase
void lock() { mLock.lock(); }
void unlock() { mLock.unlock(); }
bool isLocked() { return mLocked; }
+ void stop_l();
+ void lockFd() { mFdLock.lock(); }
+ void unlockFd() { mFdLock.unlock(); }
private:
void reopenReconfigDriver();
AudioHardware* mHardware;
- mutable Mutex mLock;
+ Mutex mLock;
int mFd;
int mFdCtl;
int mState;
@@ -303,6 +310,8 @@ class AudioHardware : public AudioHardwareBase
mutable uint32_t mTotalBuffersRead;
mutable nsecs_t mStartTimeNs;
int mDriverRate;
+ mutable Mutex mFramesLock;
+ Mutex mFdLock;
};
static const uint32_t inputSamplingRates[];
@@ -332,6 +341,8 @@ class AudioHardware : public AudioHardwareBase
#endif
int mSpkrVolume;
int mMicVolume;
+ bool mEcnsEnabled;
+ bool mBtScoOn;
};
// ----------------------------------------------------------------------------
View
1 taudio/resample.c
@@ -131,6 +131,7 @@ int main(int argc, char **argv)
while ((opt = getopt(argc, argv, "o:s:c:w")) != -1) {
switch (opt) {
case 'o':
+ FAILIF(output != NULL, "Multiple output files not supported\n");
output = strdup(optarg);
break;
case 's':
View
8 taudio/twav.c
@@ -113,15 +113,13 @@ main(int argc, char *argv[])
assert(sampling_rate >= 0);
assert(num_channels >= 0);
- if (optind >= argc) {
- fprintf(stderr, "Expected argument after options\n");
- exit(EXIT_FAILURE);
- }
+ FAILIF(!output, "Expecting an output file name\n");
+ FAILIF(optind >= argc, "Expecting an input file name\n");
input = argv[optind];
printf("> input %s\n", input);
- printf("> output %s\n", input);
+ printf("> output %s\n", output);
printf("> bits per sample %d\n", bits_per_sample);
printf("> sampling rate %d\n", sampling_rate);
printf("> channels %d\n", num_channels);

0 comments on commit a5e2cc8

Please sign in to comment.