| 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 | |
| 35 | namespace android { |
| 36 | |
| 37 | #include <linux/cpcap_audio.h> |
| 38 | #include <linux/tegra_audio.h> |
| 39 | |
| 40 | #define AUDIO_HW_OUT_SAMPLERATE 44100 |
| 41 | #define AUDIO_HW_NUM_OUT_BUF 2 |
| 42 | #define AUDIO_HW_OUT_LATENCY_MS 0 |
| 43 | |
| 44 | // FIXME: this is a workaround for issue 3387419 with impact on latency |
| 45 | // to be removed when root cause is fixed |
| 46 | #define AUDIO_HW_NUM_OUT_BUF_LONG 4 |
| 47 | |
| 48 | #define AUDIO_HW_IN_SAMPLERATE 11025 // Default audio input sample rate |
| 49 | #define AUDIO_HW_IN_CHANNELS (AudioSystem::CHANNEL_IN_MONO) // Default audio input channel mask |
| 50 | #define AUDIO_HW_IN_BUFFERSIZE (4096) // Default audio input buffer size |
| 51 | #define AUDIO_HW_IN_FORMAT (AudioSystem::PCM_16_BIT) // Default audio input sample format |
| 52 | |
| 53 | enum { |
| 54 | AUDIO_HW_GAIN_SPKR_GAIN = 0, |
| 55 | AUDIO_HW_GAIN_MIC_GAIN, |
| 56 | AUDIO_HW_GAIN_NUM_DIRECTIONS |
| 57 | }; |
| 58 | enum { |
| 59 | AUDIO_HW_GAIN_USECASE_VOICE= 0, |
| 60 | AUDIO_HW_GAIN_USECASE_MM, |
| 61 | AUDIO_HW_GAIN_USECASE_VOICE_REC, |
| 62 | AUDIO_HW_GAIN_NUM_USECASES |
| 63 | }; |
| 64 | enum { |
| 65 | AUDIO_HW_GAIN_EARPIECE = 0, |
| 66 | AUDIO_HW_GAIN_SPEAKERPHONE, |
| 67 | AUDIO_HW_GAIN_HEADSET_W_MIC, |
| 68 | AUDIO_HW_GAIN_MONO_HEADSET, |
| 69 | AUDIO_HW_GAIN_HEADSET_NO_MIC, |
| 70 | AUDIO_HW_GAIN_EMU_DEVICE, |
| 71 | AUDIO_HW_GAIN_RSVD1, |
| 72 | AUDIO_HW_GAIN_RSVD2, |
| 73 | AUDIO_HW_GAIN_RSVD3, |
| 74 | AUDIO_HW_GAIN_RSVD4, |
| 75 | AUDIO_HW_GAIN_RSVD5, |
| 76 | AUDIO_HW_GAIN_NUM_PATHS |
| 77 | }; |
| 78 | |
| 79 | enum input_state { |
| 80 | AUDIO_STREAM_IDLE, |
| 81 | AUDIO_STREAM_CONFIG_REQ, |
| 82 | AUDIO_STREAM_NEW_RATE_REQ, |
| 83 | AUDIO_STREAM_CONFIGURED |
| 84 | }; |
| 85 | |
| 86 | class AudioHardware : public AudioHardwareBase |
| 87 | { |
| 88 | class AudioStreamOutTegra; |
| 89 | class AudioStreamInTegra; |
| 90 | class AudioStreamSrc; |
| 91 | |
| 92 | public: |
| 93 | // AudioHardwareInterface |
| 94 | AudioHardware(); |
| 95 | virtual ~AudioHardware(); |
| 96 | virtual status_t initCheck(); |
| 97 | |
| 98 | virtual status_t setVoiceVolume(float volume); |
| 99 | virtual status_t setMasterVolume(float volume); |
| 100 | |
| 101 | virtual status_t setMode(int mode); |
| 102 | |
| 103 | // mic mute |
| 104 | virtual status_t setMicMute(bool state); |
| 105 | virtual status_t getMicMute(bool* state); |
| 106 | |
| 107 | virtual status_t setParameters(const String8& keyValuePairs); |
| 108 | virtual String8 getParameters(const String8& keys); |
| 109 | |
| 110 | // create I/O streams |
| 111 | virtual AudioStreamOut* openOutputStream( |
| 112 | uint32_t devices, |
| 113 | int *format=0, |
| 114 | uint32_t *channels=0, |
| 115 | uint32_t *sampleRate=0, |
| 116 | status_t *status=0); |
| 117 | |
| 118 | virtual AudioStreamIn* openInputStream( |
| 119 | |
| 120 | uint32_t devices, |
| 121 | int *format, |
| 122 | uint32_t *channels, |
| 123 | uint32_t *sampleRate, |
| 124 | status_t *status, |
| 125 | AudioSystem::audio_in_acoustics acoustics); |
| 126 | |
| 127 | virtual void closeOutputStream(AudioStreamOut* out); |
| 128 | virtual void closeInputStream(AudioStreamIn* in); |
| 129 | |
| 130 | virtual size_t getInputBufferSize(uint32_t sampleRate, int format, int channelCount); |
| 131 | // AudioHardwareBase provides default implementation |
| 132 | //virtual status_t dumpState(int fd, const Vector<String16>& args); |
| 133 | |
| 134 | // added by AudioHardware |
| 135 | status_t init(); |
| 136 | |
| 137 | protected: |
| 138 | // AudioHardwareBase provides default implementation |
| 139 | //virtual bool isModeInCall(int mode); |
| 140 | //virtual bool isInCall(); |
| 141 | |
| 142 | // AudioHardwareInterface |
| 143 | virtual status_t dump(int fd, const Vector<String16>& args); |
| 144 | |
| 145 | // added by AudioHardware |
| 146 | int getActiveInputRate(); |
| 147 | |
| 148 | private: |
| 149 | |
| 150 | status_t dumpInternals(int fd, const Vector<String16>& args); |
| 151 | uint32_t getInputSampleRate(uint32_t sampleRate); |
| 152 | status_t doStandby(int stop_fd, bool output, bool enable); |
| 153 | status_t doRouting_l(); |
| 154 | status_t doRouting(); |
| 155 | status_t setVolume_l(float v, int usecase); |
| 156 | uint8_t getGain(int direction, int usecase); |
| 157 | void readHwGainFile(); |
| 158 | |
| 159 | AudioStreamInTegra* getActiveInput_l(); |
| 160 | status_t setMicMute_l(bool state); |
| 161 | |
| 162 | #ifdef USE_PROPRIETARY_AUDIO_EXTENSIONS |
| 163 | class AudioStreamSrc { |
| 164 | public: |
| 165 | AudioStreamSrc(); |
| 166 | ~AudioStreamSrc(); |
| 167 | inline int inRate() {return mSrcInRate;}; |
| 168 | inline int outRate() {return mSrcOutRate;}; |
| 169 | inline bool initted() {return mSrcInitted;}; |
| 170 | void init(int inRate, int outRate); |
| 171 | inline void deinit() {mSrcInitted = false;}; |
| 172 | SRC_IO_T mIoData; |
| 173 | inline void srcConvert() { rate_convert(&mIoData, &mSrcObj, 0x0800); }; |
| 174 | private: |
| 175 | SRC_OBJ_T mSrcObj; |
| 176 | char * mSrcBuffer; |
| 177 | SRC_INIT_T mSrcInit; |
| 178 | int mSrcInRate; |
| 179 | int mSrcOutRate; |
| 180 | bool mSrcInitted; |
| 181 | }; |
| 182 | #endif |
| 183 | |
| 184 | class AudioStreamOutTegra : public AudioStreamOut { |
| 185 | public: |
| 186 | AudioStreamOutTegra(); |
| 187 | virtual ~AudioStreamOutTegra(); |
| 188 | status_t init(); |
| 189 | status_t initCheck(); |
| 190 | void setDriver_l(bool speaker, bool bluetooth, bool spdif, int sampleRate); |
| 191 | status_t set(AudioHardware* mHardware, |
| 192 | uint32_t devices, |
| 193 | int *pFormat, |
| 194 | uint32_t *pChannels, |
| 195 | uint32_t *pRate); |
| 196 | virtual uint32_t sampleRate() const { return AUDIO_HW_OUT_SAMPLERATE; } |
| 197 | // must be 32-bit aligned - driver only seems to like 4800 |
| 198 | virtual size_t bufferSize() const { return 4096; } |
| 199 | virtual uint32_t channels() const { return AudioSystem::CHANNEL_OUT_STEREO; } |
| 200 | virtual int format() const { return AudioSystem::PCM_16_BIT; } |
| a5e2cc8 | 2011-02-18 14:56:37 -0800 | [diff] [blame^] | 201 | 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] | 202 | virtual status_t setVolume(float left, float right) { return INVALID_OPERATION; } |
| 203 | virtual ssize_t write(const void* buffer, size_t bytes); |
| 204 | void flush(); |
| a5e2cc8 | 2011-02-18 14:56:37 -0800 | [diff] [blame^] | 205 | void flush_l(); |
| Ying Wang | 2896e59 | 2011-02-18 12:00:38 -0800 | [diff] [blame] | 206 | virtual status_t standby(); |
| 207 | status_t online_l(); |
| 208 | virtual status_t dump(int fd, const Vector<String16>& args); |
| 209 | bool getStandby(); |
| 210 | virtual status_t setParameters(const String8& keyValuePairs); |
| 211 | virtual String8 getParameters(const String8& keys); |
| 212 | uint32_t devices() { return mDevices; } |
| 213 | virtual status_t getRenderPosition(uint32_t *dspFrames); |
| 214 | void lock() { mLock.lock(); } |
| 215 | void unlock() { mLock.unlock(); } |
| 216 | bool isLocked() { return mLocked; } |
| 217 | void setNumBufs(int numBufs); |
| a5e2cc8 | 2011-02-18 14:56:37 -0800 | [diff] [blame^] | 218 | void lockFd() { mFdLock.lock(); } |
| 219 | void unlockFd() { mFdLock.unlock(); } |
| 220 | |
| 221 | int mBtFdIoCtl; |
| Ying Wang | 2896e59 | 2011-02-18 12:00:38 -0800 | [diff] [blame] | 222 | |
| 223 | private: |
| 224 | AudioHardware* mHardware; |
| 225 | Mutex mLock; |
| 226 | int mFd; |
| 227 | int mFdCtl; |
| 228 | int mBtFd; |
| 229 | int mBtFdCtl; |
| Ying Wang | 2896e59 | 2011-02-18 12:00:38 -0800 | [diff] [blame] | 230 | int mSpdifFd; |
| 231 | int mSpdifFdCtl; |
| 232 | int mStartCount; |
| 233 | int mRetryCount; |
| 234 | uint32_t mDevices; |
| 235 | Mutex mFdLock; |
| 236 | bool mIsSpkrEnabled; |
| 237 | bool mIsBtEnabled; |
| 238 | bool mIsSpdifEnabled; |
| 239 | bool mIsSpkrEnabledReq; |
| 240 | bool mIsBtEnabledReq; |
| 241 | bool mIsSpdifEnabledReq; |
| 242 | int16_t mSpareSample; |
| 243 | bool mHaveSpareSample; |
| 244 | int mState; |
| 245 | #ifdef USE_PROPRIETARY_AUDIO_EXTENSIONS |
| 246 | AudioStreamSrc mSrc; |
| 247 | #endif |
| 248 | bool mLocked; // setDriver() doesn't have to lock if true |
| 249 | int mDriverRate; |
| 250 | bool mInit; |
| 251 | }; |
| 252 | |
| 253 | class AudioStreamInTegra : public AudioStreamIn { |
| 254 | public: |
| 255 | AudioStreamInTegra(); |
| 256 | virtual ~AudioStreamInTegra(); |
| 257 | status_t set(AudioHardware* mHardware, |
| 258 | uint32_t devices, |
| 259 | int *pFormat, |
| 260 | uint32_t *pChannels, |
| 261 | uint32_t *pRate, |
| 262 | AudioSystem::audio_in_acoustics acoustics); |
| 263 | virtual size_t bufferSize() const { return mBufferSize; } |
| 264 | virtual uint32_t channels() const { return mChannels; } |
| 265 | virtual int format() const { return mFormat; } |
| 266 | virtual uint32_t sampleRate() const { return mSampleRate; } |
| 267 | virtual status_t setGain(float gain) { return INVALID_OPERATION; } |
| 268 | virtual ssize_t read(void* buffer, ssize_t bytes); |
| 269 | virtual status_t dump(int fd, const Vector<String16>& args); |
| 270 | virtual status_t standby(); |
| 271 | virtual status_t online_l(); |
| 272 | bool getStandby() const; |
| 273 | virtual status_t setParameters(const String8& keyValuePairs); |
| 274 | virtual String8 getParameters(const String8& keys); |
| 275 | virtual unsigned int getInputFramesLost() const; |
| 276 | uint32_t devices() { return mDevices; } |
| 277 | void setDriver_l(bool mic, bool bluetooth, int sampleRate); |
| 278 | int source() const { return mSource; } |
| 279 | void lock() { mLock.lock(); } |
| 280 | void unlock() { mLock.unlock(); } |
| 281 | bool isLocked() { return mLocked; } |
| a5e2cc8 | 2011-02-18 14:56:37 -0800 | [diff] [blame^] | 282 | void stop_l(); |
| 283 | void lockFd() { mFdLock.lock(); } |
| 284 | void unlockFd() { mFdLock.unlock(); } |
| Ying Wang | 2896e59 | 2011-02-18 12:00:38 -0800 | [diff] [blame] | 285 | |
| 286 | private: |
| 287 | void reopenReconfigDriver(); |
| 288 | |
| 289 | AudioHardware* mHardware; |
| a5e2cc8 | 2011-02-18 14:56:37 -0800 | [diff] [blame^] | 290 | Mutex mLock; |
| Ying Wang | 2896e59 | 2011-02-18 12:00:38 -0800 | [diff] [blame] | 291 | int mFd; |
| 292 | int mFdCtl; |
| 293 | int mState; |
| 294 | int mRetryCount; |
| 295 | int mFormat; |
| 296 | uint32_t mChannels; |
| 297 | uint32_t mSampleRate; |
| 298 | size_t mBufferSize; |
| 299 | AudioSystem::audio_in_acoustics mAcoustics; |
| 300 | uint32_t mDevices; |
| 301 | bool mIsMicEnabled; |
| 302 | bool mIsBtEnabled; |
| 303 | int mSource; |
| 304 | // 20 millisecond scratch buffer |
| 305 | int16_t mInScratch[48000/50]; |
| 306 | #ifdef USE_PROPRIETARY_AUDIO_EXTENSIONS |
| 307 | AudioStreamSrc mSrc; |
| 308 | #endif |
| 309 | bool mLocked; // setDriver() doesn't have to lock if true |
| 310 | mutable uint32_t mTotalBuffersRead; |
| 311 | mutable nsecs_t mStartTimeNs; |
| 312 | int mDriverRate; |
| a5e2cc8 | 2011-02-18 14:56:37 -0800 | [diff] [blame^] | 313 | mutable Mutex mFramesLock; |
| 314 | Mutex mFdLock; |
| Ying Wang | 2896e59 | 2011-02-18 12:00:38 -0800 | [diff] [blame] | 315 | }; |
| 316 | |
| 317 | static const uint32_t inputSamplingRates[]; |
| 318 | bool mInit; |
| 319 | bool mMicMute; |
| 320 | bool mBluetoothNrec; |
| 321 | uint32_t mBluetoothId; |
| 322 | AudioStreamOutTegra* mOutput; |
| 323 | SortedVector <AudioStreamInTegra*> mInputs; |
| 324 | |
| 325 | struct cpcap_audio_stream mCurOutDevice; |
| 326 | struct cpcap_audio_stream mCurInDevice; |
| 327 | |
| 328 | friend class AudioStreamInTegra; |
| 329 | Mutex mLock; |
| 330 | |
| 331 | int mCpcapCtlFd; |
| 332 | int mHwOutRate; |
| 333 | int mHwInRate; |
| 334 | float mMasterVol; |
| 335 | float mVoiceVol; |
| 336 | uint8_t mCpcapGain[AUDIO_HW_GAIN_NUM_DIRECTIONS] |
| 337 | [AUDIO_HW_GAIN_NUM_USECASES] |
| 338 | [AUDIO_HW_GAIN_NUM_PATHS]; |
| 339 | #ifdef USE_PROPRIETARY_AUDIO_EXTENSIONS |
| 340 | AudioPostProcessor mAudioPP; |
| 341 | #endif |
| 342 | int mSpkrVolume; |
| 343 | int mMicVolume; |
| a5e2cc8 | 2011-02-18 14:56:37 -0800 | [diff] [blame^] | 344 | bool mEcnsEnabled; |
| 345 | bool mBtScoOn; |
| Ying Wang | 2896e59 | 2011-02-18 12:00:38 -0800 | [diff] [blame] | 346 | }; |
| 347 | |
| 348 | // ---------------------------------------------------------------------------- |
| 349 | |
| 350 | }; // namespace android |
| 351 | |
| 352 | #endif // ANDROID_AUDIO_HARDWARE_H |