| Ying Wang | 2896e59 | 2011-02-18 12:00:38 -0800 | [diff] [blame] | 1 | /* |
| 2 | ** Copyright 2008-2010, The Android Open-Source Project |
| 3 | ** |
| 4 | ** Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | ** you may not use this file except in compliance with the License. |
| 6 | ** You may obtain a copy of the License at |
| 7 | ** |
| 8 | ** http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | ** |
| 10 | ** Unless required by applicable law or agreed to in writing, software |
| 11 | ** distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | ** See the License for the specific language governing permissions and |
| 14 | ** limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | #ifndef ANDROID_AUDIO_HARDWARE_H |
| 18 | #define ANDROID_AUDIO_HARDWARE_H |
| 19 | |
| 20 | #include <stdint.h> |
| 21 | #include <sys/types.h> |
| 22 | |
| 23 | #include <utils/threads.h> |
| 24 | #include <utils/SortedVector.h> |
| 25 | |
| 26 | #include <hardware_legacy/AudioHardwareBase.h> |
| 27 | #include <media/mediarecorder.h> |
| 28 | #include "AudioPostProcessor.h" |
| 29 | #ifdef USE_PROPRIETARY_AUDIO_EXTENSIONS |
| 30 | extern "C" { |
| 31 | #include "rate_conv.h" |
| 32 | } |
| 33 | #endif |
| 34 | |
| Dima Zavin | bacc417 | 2011-04-05 16:02:49 -0700 | [diff] [blame] | 35 | namespace android_audio_legacy { |
| Dima Zavin | 3a565f6 | 2011-04-27 23:37:10 -0700 | [diff] [blame] | 36 | using android::AutoMutex; |
| Dima Zavin | bacc417 | 2011-04-05 16:02:49 -0700 | [diff] [blame] | 37 | using android::Mutex; |
| 38 | using android::SortedVector; |
| Ying Wang | 2896e59 | 2011-02-18 12:00:38 -0800 | [diff] [blame] | 39 | |
| 40 | #include <linux/cpcap_audio.h> |
| 41 | #include <linux/tegra_audio.h> |
| 42 | |
| 43 | #define AUDIO_HW_OUT_SAMPLERATE 44100 |
| 44 | #define AUDIO_HW_NUM_OUT_BUF 2 |
| 45 | #define AUDIO_HW_OUT_LATENCY_MS 0 |
| 46 | |
| 47 | // FIXME: this is a workaround for issue 3387419 with impact on latency |
| 48 | // to be removed when root cause is fixed |
| 49 | #define AUDIO_HW_NUM_OUT_BUF_LONG 4 |
| 50 | |
| 51 | #define AUDIO_HW_IN_SAMPLERATE 11025 // Default audio input sample rate |
| 52 | #define AUDIO_HW_IN_CHANNELS (AudioSystem::CHANNEL_IN_MONO) // Default audio input channel mask |
| 53 | #define AUDIO_HW_IN_BUFFERSIZE (4096) // Default audio input buffer size |
| 54 | #define AUDIO_HW_IN_FORMAT (AudioSystem::PCM_16_BIT) // Default audio input sample format |
| 55 | |
| 56 | enum { |
| 57 | AUDIO_HW_GAIN_SPKR_GAIN = 0, |
| 58 | AUDIO_HW_GAIN_MIC_GAIN, |
| 59 | AUDIO_HW_GAIN_NUM_DIRECTIONS |
| 60 | }; |
| 61 | enum { |
| 62 | AUDIO_HW_GAIN_USECASE_VOICE= 0, |
| 63 | AUDIO_HW_GAIN_USECASE_MM, |
| 64 | AUDIO_HW_GAIN_USECASE_VOICE_REC, |
| 65 | AUDIO_HW_GAIN_NUM_USECASES |
| 66 | }; |
| 67 | enum { |
| 68 | AUDIO_HW_GAIN_EARPIECE = 0, |
| 69 | AUDIO_HW_GAIN_SPEAKERPHONE, |
| 70 | AUDIO_HW_GAIN_HEADSET_W_MIC, |
| 71 | AUDIO_HW_GAIN_MONO_HEADSET, |
| 72 | AUDIO_HW_GAIN_HEADSET_NO_MIC, |
| 73 | AUDIO_HW_GAIN_EMU_DEVICE, |
| 74 | AUDIO_HW_GAIN_RSVD1, |
| 75 | AUDIO_HW_GAIN_RSVD2, |
| 76 | AUDIO_HW_GAIN_RSVD3, |
| 77 | AUDIO_HW_GAIN_RSVD4, |
| 78 | AUDIO_HW_GAIN_RSVD5, |
| 79 | AUDIO_HW_GAIN_NUM_PATHS |
| 80 | }; |
| 81 | |
| 82 | enum input_state { |
| 83 | AUDIO_STREAM_IDLE, |
| 84 | AUDIO_STREAM_CONFIG_REQ, |
| 85 | AUDIO_STREAM_NEW_RATE_REQ, |
| 86 | AUDIO_STREAM_CONFIGURED |
| 87 | }; |
| 88 | |
| 89 | class AudioHardware : public AudioHardwareBase |
| 90 | { |
| 91 | class AudioStreamOutTegra; |
| 92 | class AudioStreamInTegra; |
| 93 | class AudioStreamSrc; |
| 94 | |
| 95 | public: |
| 96 | // AudioHardwareInterface |
| 97 | AudioHardware(); |
| 98 | virtual ~AudioHardware(); |
| 99 | virtual status_t initCheck(); |
| 100 | |
| 101 | virtual status_t setVoiceVolume(float volume); |
| 102 | virtual status_t setMasterVolume(float volume); |
| 103 | |
| 104 | virtual status_t setMode(int mode); |
| 105 | |
| 106 | // mic mute |
| 107 | virtual status_t setMicMute(bool state); |
| 108 | virtual status_t getMicMute(bool* state); |
| 109 | |
| 110 | virtual status_t setParameters(const String8& keyValuePairs); |
| 111 | virtual String8 getParameters(const String8& keys); |
| 112 | |
| 113 | // create I/O streams |
| 114 | virtual AudioStreamOut* openOutputStream( |
| 115 | uint32_t devices, |
| 116 | int *format=0, |
| 117 | uint32_t *channels=0, |
| 118 | uint32_t *sampleRate=0, |
| 119 | status_t *status=0); |
| 120 | |
| 121 | virtual AudioStreamIn* openInputStream( |
| 122 | |
| 123 | uint32_t devices, |
| 124 | int *format, |
| 125 | uint32_t *channels, |
| 126 | uint32_t *sampleRate, |
| 127 | status_t *status, |
| 128 | AudioSystem::audio_in_acoustics acoustics); |
| 129 | |
| 130 | virtual void closeOutputStream(AudioStreamOut* out); |
| 131 | virtual void closeInputStream(AudioStreamIn* in); |
| 132 | |
| 133 | virtual size_t getInputBufferSize(uint32_t sampleRate, int format, int channelCount); |
| 134 | // AudioHardwareBase provides default implementation |
| 135 | //virtual status_t dumpState(int fd, const Vector<String16>& args); |
| 136 | |
| 137 | // added by AudioHardware |
| 138 | status_t init(); |
| 139 | |
| Eric Laurent | 1abc062 | 2011-08-08 12:34:25 -0700 | [diff] [blame] | 140 | // voice processing IDs for mEcnsRequested and mEcnsEnabled |
| 141 | enum { |
| 142 | #ifdef USE_PROPRIETARY_AUDIO_EXTENSIONS |
| 143 | PREPROC_AEC = AudioPostProcessor::AEC, // AEC is enabled |
| 144 | PREPROC_NS = AudioPostProcessor::NS, // NS is enabled |
| 145 | #else |
| 146 | PREPROC_AEC = 0x1, // AEC is enabled |
| 147 | PREPROC_NS = 0x2, // NS is enabled |
| 148 | #endif |
| 149 | }; |
| Eric Laurent | 9027dad | 2011-08-05 19:42:36 -0700 | [diff] [blame] | 150 | |
| Eric Laurent | 1abc062 | 2011-08-08 12:34:25 -0700 | [diff] [blame] | 151 | void setEcnsRequested_l(int ecns, bool enabled); |
| 152 | bool isEcRequested() { return !!(mEcnsRequested & PREPROC_AEC); } |
| Ying Wang | 2896e59 | 2011-02-18 12:00:38 -0800 | [diff] [blame] | 153 | protected: |
| 154 | // AudioHardwareBase provides default implementation |
| 155 | //virtual bool isModeInCall(int mode); |
| 156 | //virtual bool isInCall(); |
| 157 | |
| 158 | // AudioHardwareInterface |
| 159 | virtual status_t dump(int fd, const Vector<String16>& args); |
| 160 | |
| 161 | // added by AudioHardware |
| 162 | int getActiveInputRate(); |
| 163 | |
| Eric Laurent | 9027dad | 2011-08-05 19:42:36 -0700 | [diff] [blame] | 164 | |
| Ying Wang | 2896e59 | 2011-02-18 12:00:38 -0800 | [diff] [blame] | 165 | private: |
| 166 | |
| 167 | status_t dumpInternals(int fd, const Vector<String16>& args); |
| 168 | uint32_t getInputSampleRate(uint32_t sampleRate); |
| 169 | status_t doStandby(int stop_fd, bool output, bool enable); |
| 170 | status_t doRouting_l(); |
| 171 | status_t doRouting(); |
| 172 | status_t setVolume_l(float v, int usecase); |
| 173 | uint8_t getGain(int direction, int usecase); |
| 174 | void readHwGainFile(); |
| 175 | |
| 176 | AudioStreamInTegra* getActiveInput_l(); |
| 177 | status_t setMicMute_l(bool state); |
| 178 | |
| 179 | #ifdef USE_PROPRIETARY_AUDIO_EXTENSIONS |
| 180 | class AudioStreamSrc { |
| 181 | public: |
| 182 | AudioStreamSrc(); |
| 183 | ~AudioStreamSrc(); |
| 184 | inline int inRate() {return mSrcInRate;}; |
| 185 | inline int outRate() {return mSrcOutRate;}; |
| 186 | inline bool initted() {return mSrcInitted;}; |
| 187 | void init(int inRate, int outRate); |
| 188 | inline void deinit() {mSrcInitted = false;}; |
| 189 | SRC_IO_T mIoData; |
| 190 | inline void srcConvert() { rate_convert(&mIoData, &mSrcObj, 0x0800); }; |
| 191 | private: |
| 192 | SRC_OBJ_T mSrcObj; |
| 193 | char * mSrcBuffer; |
| 194 | SRC_INIT_T mSrcInit; |
| 195 | int mSrcInRate; |
| 196 | int mSrcOutRate; |
| 197 | bool mSrcInitted; |
| 198 | }; |
| 199 | #endif |
| 200 | |
| 201 | class AudioStreamOutTegra : public AudioStreamOut { |
| 202 | public: |
| 203 | AudioStreamOutTegra(); |
| 204 | virtual ~AudioStreamOutTegra(); |
| 205 | status_t init(); |
| 206 | status_t initCheck(); |
| 207 | void setDriver_l(bool speaker, bool bluetooth, bool spdif, int sampleRate); |
| 208 | status_t set(AudioHardware* mHardware, |
| 209 | uint32_t devices, |
| 210 | int *pFormat, |
| 211 | uint32_t *pChannels, |
| 212 | uint32_t *pRate); |
| 213 | virtual uint32_t sampleRate() const { return AUDIO_HW_OUT_SAMPLERATE; } |
| 214 | // must be 32-bit aligned - driver only seems to like 4800 |
| 215 | virtual size_t bufferSize() const { return 4096; } |
| 216 | virtual uint32_t channels() const { return AudioSystem::CHANNEL_OUT_STEREO; } |
| 217 | virtual int format() const { return AudioSystem::PCM_16_BIT; } |
| a5e2cc8 | 2011-02-18 14:56:37 -0800 | [diff] [blame] | 218 | virtual uint32_t latency() const { return (1000*AUDIO_HW_NUM_OUT_BUF_LONG*(bufferSize()/frameSize()))/sampleRate()+AUDIO_HW_OUT_LATENCY_MS; } |
| Ying Wang | 2896e59 | 2011-02-18 12:00:38 -0800 | [diff] [blame] | 219 | virtual status_t setVolume(float left, float right) { return INVALID_OPERATION; } |
| 220 | virtual ssize_t write(const void* buffer, size_t bytes); |
| 221 | void flush(); |
| a5e2cc8 | 2011-02-18 14:56:37 -0800 | [diff] [blame] | 222 | void flush_l(); |
| Ying Wang | 2896e59 | 2011-02-18 12:00:38 -0800 | [diff] [blame] | 223 | virtual status_t standby(); |
| 224 | status_t online_l(); |
| 225 | virtual status_t dump(int fd, const Vector<String16>& args); |
| 226 | bool getStandby(); |
| 227 | virtual status_t setParameters(const String8& keyValuePairs); |
| 228 | virtual String8 getParameters(const String8& keys); |
| 229 | uint32_t devices() { return mDevices; } |
| 230 | virtual status_t getRenderPosition(uint32_t *dspFrames); |
| Eric Laurent | f0d2c70 | 2011-03-07 15:19:23 -0800 | [diff] [blame] | 231 | void lock() { mSleepReq = true; mLock.lock(); mSleepReq = false; } |
| Ying Wang | 2896e59 | 2011-02-18 12:00:38 -0800 | [diff] [blame] | 232 | void unlock() { mLock.unlock(); } |
| 233 | bool isLocked() { return mLocked; } |
| 234 | void setNumBufs(int numBufs); |
| a5e2cc8 | 2011-02-18 14:56:37 -0800 | [diff] [blame] | 235 | void lockFd() { mFdLock.lock(); } |
| 236 | void unlockFd() { mFdLock.unlock(); } |
| 237 | |
| 238 | int mBtFdIoCtl; |
| Ying Wang | 2896e59 | 2011-02-18 12:00:38 -0800 | [diff] [blame] | 239 | |
| 240 | private: |
| 241 | AudioHardware* mHardware; |
| 242 | Mutex mLock; |
| 243 | int mFd; |
| 244 | int mFdCtl; |
| 245 | int mBtFd; |
| 246 | int mBtFdCtl; |
| Ying Wang | 2896e59 | 2011-02-18 12:00:38 -0800 | [diff] [blame] | 247 | int mSpdifFd; |
| 248 | int mSpdifFdCtl; |
| 249 | int mStartCount; |
| 250 | int mRetryCount; |
| 251 | uint32_t mDevices; |
| 252 | Mutex mFdLock; |
| 253 | bool mIsSpkrEnabled; |
| 254 | bool mIsBtEnabled; |
| 255 | bool mIsSpdifEnabled; |
| 256 | bool mIsSpkrEnabledReq; |
| 257 | bool mIsBtEnabledReq; |
| 258 | bool mIsSpdifEnabledReq; |
| 259 | int16_t mSpareSample; |
| 260 | bool mHaveSpareSample; |
| 261 | int mState; |
| 262 | #ifdef USE_PROPRIETARY_AUDIO_EXTENSIONS |
| 263 | AudioStreamSrc mSrc; |
| 264 | #endif |
| 265 | bool mLocked; // setDriver() doesn't have to lock if true |
| 266 | int mDriverRate; |
| 267 | bool mInit; |
| Eric Laurent | f0d2c70 | 2011-03-07 15:19:23 -0800 | [diff] [blame] | 268 | bool mSleepReq; |
| Ying Wang | 2896e59 | 2011-02-18 12:00:38 -0800 | [diff] [blame] | 269 | }; |
| 270 | |
| 271 | class AudioStreamInTegra : public AudioStreamIn { |
| 272 | public: |
| 273 | AudioStreamInTegra(); |
| 274 | virtual ~AudioStreamInTegra(); |
| 275 | status_t set(AudioHardware* mHardware, |
| 276 | uint32_t devices, |
| 277 | int *pFormat, |
| 278 | uint32_t *pChannels, |
| 279 | uint32_t *pRate, |
| 280 | AudioSystem::audio_in_acoustics acoustics); |
| 281 | virtual size_t bufferSize() const { return mBufferSize; } |
| 282 | virtual uint32_t channels() const { return mChannels; } |
| 283 | virtual int format() const { return mFormat; } |
| 284 | virtual uint32_t sampleRate() const { return mSampleRate; } |
| 285 | virtual status_t setGain(float gain) { return INVALID_OPERATION; } |
| 286 | virtual ssize_t read(void* buffer, ssize_t bytes); |
| 287 | virtual status_t dump(int fd, const Vector<String16>& args); |
| 288 | virtual status_t standby(); |
| 289 | virtual status_t online_l(); |
| 290 | bool getStandby() const; |
| 291 | virtual status_t setParameters(const String8& keyValuePairs); |
| 292 | virtual String8 getParameters(const String8& keys); |
| 293 | virtual unsigned int getInputFramesLost() const; |
| Eric Laurent | a25f559 | 2011-06-17 16:09:41 -0700 | [diff] [blame] | 294 | virtual status_t addAudioEffect(effect_handle_t effect); |
| 295 | virtual status_t removeAudioEffect(effect_handle_t effect); |
| 296 | |
| Ying Wang | 2896e59 | 2011-02-18 12:00:38 -0800 | [diff] [blame] | 297 | uint32_t devices() { return mDevices; } |
| 298 | void setDriver_l(bool mic, bool bluetooth, int sampleRate); |
| 299 | int source() const { return mSource; } |
| Eric Laurent | f0d2c70 | 2011-03-07 15:19:23 -0800 | [diff] [blame] | 300 | void lock() { mSleepReq = true; mLock.lock(); mSleepReq = false; } |
| Ying Wang | 2896e59 | 2011-02-18 12:00:38 -0800 | [diff] [blame] | 301 | void unlock() { mLock.unlock(); } |
| 302 | bool isLocked() { return mLocked; } |
| a5e2cc8 | 2011-02-18 14:56:37 -0800 | [diff] [blame] | 303 | void stop_l(); |
| 304 | void lockFd() { mFdLock.lock(); } |
| 305 | void unlockFd() { mFdLock.unlock(); } |
| Ying Wang | 2896e59 | 2011-02-18 12:00:38 -0800 | [diff] [blame] | 306 | |
| 307 | private: |
| 308 | void reopenReconfigDriver(); |
| Eric Laurent | 9027dad | 2011-08-05 19:42:36 -0700 | [diff] [blame] | 309 | void updateEcnsRequested(effect_handle_t effect, bool enabled); |
| Ying Wang | 2896e59 | 2011-02-18 12:00:38 -0800 | [diff] [blame] | 310 | |
| 311 | AudioHardware* mHardware; |
| a5e2cc8 | 2011-02-18 14:56:37 -0800 | [diff] [blame] | 312 | Mutex mLock; |
| Ying Wang | 2896e59 | 2011-02-18 12:00:38 -0800 | [diff] [blame] | 313 | int mFd; |
| 314 | int mFdCtl; |
| 315 | int mState; |
| 316 | int mRetryCount; |
| 317 | int mFormat; |
| 318 | uint32_t mChannels; |
| 319 | uint32_t mSampleRate; |
| 320 | size_t mBufferSize; |
| 321 | AudioSystem::audio_in_acoustics mAcoustics; |
| 322 | uint32_t mDevices; |
| 323 | bool mIsMicEnabled; |
| 324 | bool mIsBtEnabled; |
| 325 | int mSource; |
| 326 | // 20 millisecond scratch buffer |
| 327 | int16_t mInScratch[48000/50]; |
| 328 | #ifdef USE_PROPRIETARY_AUDIO_EXTENSIONS |
| 329 | AudioStreamSrc mSrc; |
| 330 | #endif |
| 331 | bool mLocked; // setDriver() doesn't have to lock if true |
| 332 | mutable uint32_t mTotalBuffersRead; |
| 333 | mutable nsecs_t mStartTimeNs; |
| 334 | int mDriverRate; |
| a5e2cc8 | 2011-02-18 14:56:37 -0800 | [diff] [blame] | 335 | mutable Mutex mFramesLock; |
| 336 | Mutex mFdLock; |
| Eric Laurent | f0d2c70 | 2011-03-07 15:19:23 -0800 | [diff] [blame] | 337 | bool mSleepReq; |
| Eric Laurent | 9027dad | 2011-08-05 19:42:36 -0700 | [diff] [blame] | 338 | int mEcnsRequested; // bit field indicating if AEC and/or NS are requested |
| Ying Wang | 2896e59 | 2011-02-18 12:00:38 -0800 | [diff] [blame] | 339 | }; |
| 340 | |
| 341 | static const uint32_t inputSamplingRates[]; |
| 342 | bool mInit; |
| 343 | bool mMicMute; |
| 344 | bool mBluetoothNrec; |
| 345 | uint32_t mBluetoothId; |
| 346 | AudioStreamOutTegra* mOutput; |
| 347 | SortedVector <AudioStreamInTegra*> mInputs; |
| 348 | |
| 349 | struct cpcap_audio_stream mCurOutDevice; |
| 350 | struct cpcap_audio_stream mCurInDevice; |
| 351 | |
| 352 | friend class AudioStreamInTegra; |
| 353 | Mutex mLock; |
| 354 | |
| 355 | int mCpcapCtlFd; |
| 356 | int mHwOutRate; |
| 357 | int mHwInRate; |
| 358 | float mMasterVol; |
| 359 | float mVoiceVol; |
| 360 | uint8_t mCpcapGain[AUDIO_HW_GAIN_NUM_DIRECTIONS] |
| 361 | [AUDIO_HW_GAIN_NUM_USECASES] |
| 362 | [AUDIO_HW_GAIN_NUM_PATHS]; |
| 363 | #ifdef USE_PROPRIETARY_AUDIO_EXTENSIONS |
| 364 | AudioPostProcessor mAudioPP; |
| 365 | #endif |
| 366 | int mSpkrVolume; |
| 367 | int mMicVolume; |
| Eric Laurent | 9027dad | 2011-08-05 19:42:36 -0700 | [diff] [blame] | 368 | |
| 369 | int mEcnsEnabled; // bit field indicating if AEC and/or NS are enabled |
| 370 | int mEcnsRequested; // bit field indicating if AEC and/or NS are requested |
| a5e2cc8 | 2011-02-18 14:56:37 -0800 | [diff] [blame] | 371 | bool mBtScoOn; |
| Ying Wang | 2896e59 | 2011-02-18 12:00:38 -0800 | [diff] [blame] | 372 | }; |
| 373 | |
| 374 | // ---------------------------------------------------------------------------- |
| 375 | |
| 376 | }; // namespace android |
| 377 | |
| 378 | #endif // ANDROID_AUDIO_HARDWARE_H |