You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
594 lines
18 KiB
594 lines
18 KiB
/* AudioHardwareALSA.h
|
|
**
|
|
** Copyright 2008-2010, Wind River Systems
|
|
** Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
|
|
**
|
|
** Licensed under the Apache License, Version 2.0 (the "License");
|
|
** you may not use this file except in compliance with the License.
|
|
** You may obtain a copy of the License at
|
|
**
|
|
** http://www.apache.org/licenses/LICENSE-2.0
|
|
**
|
|
** Unless required by applicable law or agreed to in writing, software
|
|
** distributed under the License is distributed on an "AS IS" BASIS,
|
|
** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
** See the License for the specific language governing permissions and
|
|
** limitations under the License.
|
|
*/
|
|
|
|
#ifndef ANDROID_AUDIO_HARDWARE_ALSA_H
|
|
#define ANDROID_AUDIO_HARDWARE_ALSA_H
|
|
|
|
#define QCOM_CSDCLIENT_ENABLED 1
|
|
|
|
#include <utils/List.h>
|
|
#include <hardware_legacy/AudioHardwareBase.h>
|
|
|
|
#include <hardware_legacy/AudioHardwareInterface.h>
|
|
#include <hardware_legacy/AudioSystemLegacy.h>
|
|
#include <system/audio.h>
|
|
#include <hardware/audio.h>
|
|
#include <utils/threads.h>
|
|
#include <dlfcn.h>
|
|
|
|
#ifdef QCOM_USBAUDIO_ENABLED
|
|
#include <AudioUsbALSA.h>
|
|
#endif
|
|
|
|
extern "C" {
|
|
#include <sound/asound.h>
|
|
#include "alsa_audio.h"
|
|
#include "msm8960_use_cases.h"
|
|
}
|
|
|
|
#include <hardware/hardware.h>
|
|
|
|
namespace android_audio_legacy
|
|
{
|
|
using android::List;
|
|
using android::Mutex;
|
|
class AudioHardwareALSA;
|
|
|
|
/**
|
|
* The id of ALSA module
|
|
*/
|
|
#define ALSA_HARDWARE_MODULE_ID "alsa"
|
|
#define ALSA_HARDWARE_NAME "alsa"
|
|
|
|
#define DEFAULT_SAMPLING_RATE 48000
|
|
#define DEFAULT_CHANNEL_MODE 2
|
|
#define VOICE_SAMPLING_RATE 8000
|
|
#define VOICE_CHANNEL_MODE 1
|
|
#define PLAYBACK_LATENCY 170000
|
|
#define RECORD_LATENCY 96000
|
|
#define VOICE_LATENCY 85333
|
|
#define DEFAULT_BUFFER_SIZE 4096
|
|
//4032 = 336(kernel buffer size) * 2(bytes pcm_16) * 6(number of channels)
|
|
#define DEFAULT_MULTI_CHANNEL_BUF_SIZE 4032
|
|
#define DEFAULT_VOICE_BUFFER_SIZE 2048
|
|
#define PLAYBACK_LOW_LATENCY_BUFFER_SIZE 1024
|
|
#define PLAYBACK_LOW_LATENCY 22000
|
|
#define PLAYBACK_LOW_LATENCY_MEASURED 42000
|
|
#define DEFAULT_IN_BUFFER_SIZE 320
|
|
#define MIN_CAPTURE_BUFFER_SIZE_PER_CH 320
|
|
#define MAX_CAPTURE_BUFFER_SIZE_PER_CH 2048
|
|
#define FM_BUFFER_SIZE 1024
|
|
|
|
#define VOIP_SAMPLING_RATE_8K 8000
|
|
#define VOIP_SAMPLING_RATE_16K 16000
|
|
#define VOIP_DEFAULT_CHANNEL_MODE 1
|
|
#define VOIP_BUFFER_SIZE_8K 320
|
|
#define VOIP_BUFFER_SIZE_16K 640
|
|
#define VOIP_BUFFER_MAX_SIZE VOIP_BUFFER_SIZE_16K
|
|
#define VOIP_PLAYBACK_LATENCY 6400
|
|
#define VOIP_RECORD_LATENCY 6400
|
|
|
|
#define MODE_IS127 0x2
|
|
#define MODE_4GV_NB 0x3
|
|
#define MODE_4GV_WB 0x4
|
|
#define MODE_AMR 0x5
|
|
#define MODE_AMR_WB 0xD
|
|
#define MODE_PCM 0xC
|
|
|
|
#define DUALMIC_KEY "dualmic_enabled"
|
|
#define FLUENCE_KEY "fluence"
|
|
#define ANC_KEY "anc_enabled"
|
|
#define TTY_MODE_KEY "tty_mode"
|
|
#define BT_SAMPLERATE_KEY "bt_samplerate"
|
|
#define BTHEADSET_VGS "bt_headset_vgs"
|
|
#define WIDEVOICE_KEY "wide_voice_enable"
|
|
#define VOIPRATE_KEY "voip_rate"
|
|
#define FENS_KEY "fens_enable"
|
|
#define ST_KEY "st_enable"
|
|
#define INCALLMUSIC_KEY "incall_music_enabled"
|
|
|
|
#define ANC_FLAG 0x00000001
|
|
#define DMIC_FLAG 0x00000002
|
|
#define QMIC_FLAG 0x00000004
|
|
#ifdef QCOM_SSR_ENABLED
|
|
#define SSRQMIC_FLAG 0x00000008
|
|
#endif
|
|
|
|
#define TTY_OFF 0x00000010
|
|
#define TTY_FULL 0x00000020
|
|
#define TTY_VCO 0x00000040
|
|
#define TTY_HCO 0x00000080
|
|
#define TTY_CLEAR 0xFFFFFF0F
|
|
|
|
#define LPA_SESSION_ID 1
|
|
#define TUNNEL_SESSION_ID 2
|
|
#ifdef QCOM_USBAUDIO_ENABLED
|
|
static int USBPLAYBACKBIT_MUSIC = (1 << 0);
|
|
static int USBPLAYBACKBIT_VOICECALL = (1 << 1);
|
|
static int USBPLAYBACKBIT_VOIPCALL = (1 << 2);
|
|
static int USBPLAYBACKBIT_FM = (1 << 3);
|
|
static int USBPLAYBACKBIT_LPA = (1 << 4);
|
|
|
|
static int USBRECBIT_REC = (1 << 0);
|
|
static int USBRECBIT_VOICECALL = (1 << 1);
|
|
static int USBRECBIT_VOIPCALL = (1 << 2);
|
|
static int USBRECBIT_FM = (1 << 3);
|
|
#endif
|
|
|
|
#define DEVICE_SPEAKER_HEADSET "Speaker Headset"
|
|
#define DEVICE_HEADSET "Headset"
|
|
#define DEVICE_HEADPHONES "Headphones"
|
|
|
|
#ifdef QCOM_SSR_ENABLED
|
|
#define COEFF_ARRAY_SIZE 4
|
|
#define FILT_SIZE ((512+1)* 6) /* # ((FFT bins)/2+1)*numOutputs */
|
|
#define SSR_FRAME_SIZE 512
|
|
#define SSR_INPUT_FRAME_SIZE (SSR_FRAME_SIZE * 4)
|
|
#define SSR_OUTPUT_FRAME_SIZE (SSR_FRAME_SIZE * 6)
|
|
#endif
|
|
|
|
#define MODE_CALL_KEY "CALL_KEY"
|
|
|
|
struct alsa_device_t;
|
|
static uint32_t FLUENCE_MODE_ENDFIRE = 0;
|
|
static uint32_t FLUENCE_MODE_BROADSIDE = 1;
|
|
|
|
enum {
|
|
INCALL_REC_MONO,
|
|
INCALL_REC_STEREO,
|
|
};
|
|
|
|
enum audio_call_mode {
|
|
CS_INACTIVE = 0x0,
|
|
CS_ACTIVE = 0x1,
|
|
CS_HOLD = 0x2,
|
|
IMS_INACTIVE = 0x0,
|
|
IMS_ACTIVE = 0x10,
|
|
IMS_HOLD = 0x20
|
|
};
|
|
|
|
|
|
struct alsa_handle_t {
|
|
alsa_device_t * module;
|
|
uint32_t devices;
|
|
char useCase[MAX_STR_LEN];
|
|
struct pcm * handle;
|
|
snd_pcm_format_t format;
|
|
uint32_t channels;
|
|
audio_channel_mask_t channelMask;
|
|
uint32_t sampleRate;
|
|
unsigned int latency; // Delay in usec
|
|
unsigned int bufferSize; // Size of sample buffer
|
|
unsigned int periodSize;
|
|
bool isDeepbufferOutput;
|
|
struct pcm * rxHandle;
|
|
snd_use_case_mgr_t *ucMgr;
|
|
};
|
|
|
|
typedef List < alsa_handle_t > ALSAHandleList;
|
|
|
|
struct use_case_t {
|
|
char useCase[MAX_STR_LEN];
|
|
};
|
|
|
|
typedef List < use_case_t > ALSAUseCaseList;
|
|
|
|
struct alsa_device_t {
|
|
hw_device_t common;
|
|
|
|
status_t (*init)(alsa_device_t *, ALSAHandleList &);
|
|
status_t (*open)(alsa_handle_t *);
|
|
status_t (*close)(alsa_handle_t *);
|
|
status_t (*standby)(alsa_handle_t *);
|
|
status_t (*route)(alsa_handle_t *, uint32_t, int);
|
|
status_t (*startVoiceCall)(alsa_handle_t *);
|
|
status_t (*startVoipCall)(alsa_handle_t *);
|
|
status_t (*startFm)(alsa_handle_t *);
|
|
void (*setVoiceVolume)(int);
|
|
void (*setVoipVolume)(int);
|
|
void (*setMicMute)(int);
|
|
void (*setVoipMicMute)(int);
|
|
void (*setVoipConfig)(int, int);
|
|
status_t (*setFmVolume)(int);
|
|
void (*setBtscoRate)(int);
|
|
status_t (*setLpaVolume)(int);
|
|
void (*enableWideVoice)(bool);
|
|
void (*enableFENS)(bool);
|
|
void (*setFlags)(uint32_t);
|
|
status_t (*setCompressedVolume)(int);
|
|
void (*enableSlowTalk)(bool);
|
|
void (*setVocRecMode)(uint8_t);
|
|
void (*setVoLTEMicMute)(int);
|
|
void (*setVoLTEVolume)(int);
|
|
#ifdef SEPERATED_AUDIO_INPUT
|
|
void (*setInput)(int);
|
|
#endif
|
|
#ifdef QCOM_CSDCLIENT_ENABLED
|
|
void (*setCsdHandle)(void*);
|
|
#endif
|
|
};
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
class ALSAMixer
|
|
{
|
|
public:
|
|
ALSAMixer();
|
|
virtual ~ALSAMixer();
|
|
|
|
bool isValid() { return 1;}
|
|
status_t setMasterVolume(float volume);
|
|
status_t setMasterGain(float gain);
|
|
|
|
status_t setVolume(uint32_t device, float left, float right);
|
|
status_t setGain(uint32_t device, float gain);
|
|
|
|
status_t setCaptureMuteState(uint32_t device, bool state);
|
|
status_t getCaptureMuteState(uint32_t device, bool *state);
|
|
status_t setPlaybackMuteState(uint32_t device, bool state);
|
|
status_t getPlaybackMuteState(uint32_t device, bool *state);
|
|
|
|
};
|
|
|
|
class ALSAControl
|
|
{
|
|
public:
|
|
ALSAControl(const char *device = "/dev/snd/controlC0");
|
|
virtual ~ALSAControl();
|
|
|
|
status_t get(const char *name, unsigned int &value, int index = 0);
|
|
status_t set(const char *name, unsigned int value, int index = -1);
|
|
status_t set(const char *name, const char *);
|
|
status_t setext(const char *name, int count, char **setValues);
|
|
|
|
private:
|
|
struct mixer* mHandle;
|
|
};
|
|
|
|
class ALSAStreamOps
|
|
{
|
|
public:
|
|
ALSAStreamOps(AudioHardwareALSA *parent, alsa_handle_t *handle);
|
|
virtual ~ALSAStreamOps();
|
|
|
|
status_t set(int *format, uint32_t *channels, uint32_t *rate, uint32_t device);
|
|
|
|
status_t setParameters(const String8& keyValuePairs);
|
|
String8 getParameters(const String8& keys);
|
|
|
|
uint32_t sampleRate() const;
|
|
size_t bufferSize() const;
|
|
int format() const;
|
|
uint32_t channels() const;
|
|
|
|
status_t open(int mode);
|
|
void close();
|
|
|
|
protected:
|
|
friend class AudioHardwareALSA;
|
|
|
|
AudioHardwareALSA * mParent;
|
|
alsa_handle_t * mHandle;
|
|
uint32_t mDevices;
|
|
};
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
class AudioStreamOutALSA : public AudioStreamOut, public ALSAStreamOps
|
|
{
|
|
public:
|
|
AudioStreamOutALSA(AudioHardwareALSA *parent, alsa_handle_t *handle);
|
|
virtual ~AudioStreamOutALSA();
|
|
|
|
virtual uint32_t sampleRate() const
|
|
{
|
|
return ALSAStreamOps::sampleRate();
|
|
}
|
|
|
|
virtual size_t bufferSize() const
|
|
{
|
|
return ALSAStreamOps::bufferSize();
|
|
}
|
|
|
|
virtual uint32_t channels() const;
|
|
|
|
virtual int format() const
|
|
{
|
|
return ALSAStreamOps::format();
|
|
}
|
|
|
|
virtual uint32_t latency() const;
|
|
|
|
virtual ssize_t write(const void *buffer, size_t bytes);
|
|
virtual status_t dump(int fd, const Vector<String16>& args);
|
|
|
|
status_t setVolume(float left, float right);
|
|
|
|
virtual status_t standby();
|
|
|
|
virtual status_t setParameters(const String8& keyValuePairs) {
|
|
return ALSAStreamOps::setParameters(keyValuePairs);
|
|
}
|
|
|
|
virtual String8 getParameters(const String8& keys) {
|
|
return ALSAStreamOps::getParameters(keys);
|
|
}
|
|
|
|
// return the number of audio frames written by the audio dsp to DAC since
|
|
// the output has exited standby
|
|
virtual status_t getRenderPosition(uint32_t *dspFrames);
|
|
|
|
status_t open(int mode);
|
|
status_t close();
|
|
|
|
private:
|
|
uint32_t mFrameCount;
|
|
|
|
protected:
|
|
AudioHardwareALSA * mParent;
|
|
};
|
|
|
|
class AudioStreamInALSA : public AudioStreamIn, public ALSAStreamOps
|
|
{
|
|
public:
|
|
AudioStreamInALSA(AudioHardwareALSA *parent,
|
|
alsa_handle_t *handle,
|
|
AudioSystem::audio_in_acoustics audio_acoustics);
|
|
virtual ~AudioStreamInALSA();
|
|
|
|
virtual uint32_t sampleRate() const
|
|
{
|
|
return ALSAStreamOps::sampleRate();
|
|
}
|
|
|
|
virtual size_t bufferSize() const
|
|
{
|
|
return ALSAStreamOps::bufferSize();
|
|
}
|
|
|
|
virtual uint32_t channels() const
|
|
{
|
|
return ALSAStreamOps::channels();
|
|
}
|
|
|
|
virtual int format() const
|
|
{
|
|
return ALSAStreamOps::format();
|
|
}
|
|
|
|
virtual ssize_t read(void* buffer, ssize_t bytes);
|
|
virtual status_t dump(int fd, const Vector<String16>& args);
|
|
|
|
virtual status_t setGain(float gain);
|
|
|
|
virtual status_t standby();
|
|
|
|
virtual status_t setParameters(const String8& keyValuePairs)
|
|
{
|
|
return ALSAStreamOps::setParameters(keyValuePairs);
|
|
}
|
|
|
|
virtual String8 getParameters(const String8& keys)
|
|
{
|
|
return ALSAStreamOps::getParameters(keys);
|
|
}
|
|
|
|
// Return the amount of input frames lost in the audio driver since the last call of this function.
|
|
// Audio driver is expected to reset the value to 0 and restart counting upon returning the current value by this function call.
|
|
// Such loss typically occurs when the user space process is blocked longer than the capacity of audio driver buffers.
|
|
// Unit: the number of input audio frames
|
|
virtual unsigned int getInputFramesLost() const;
|
|
|
|
virtual status_t addAudioEffect(effect_handle_t effect)
|
|
{
|
|
return BAD_VALUE;
|
|
}
|
|
|
|
virtual status_t removeAudioEffect(effect_handle_t effect)
|
|
{
|
|
return BAD_VALUE;
|
|
}
|
|
status_t setAcousticParams(void* params);
|
|
|
|
status_t open(int mode);
|
|
status_t close();
|
|
#ifdef QCOM_SSR_ENABLED
|
|
// Helper function to initialize the Surround Sound library.
|
|
status_t initSurroundSoundLibrary(unsigned long buffersize);
|
|
#endif
|
|
|
|
private:
|
|
void resetFramesLost();
|
|
|
|
#ifdef QCOM_CSDCLIENT_ENABLED
|
|
int start_csd_record(int);
|
|
int stop_csd_record(void);
|
|
#endif
|
|
|
|
unsigned int mFramesLost;
|
|
AudioSystem::audio_in_acoustics mAcoustics;
|
|
|
|
#ifdef QCOM_SSR_ENABLED
|
|
// Function to read coefficients from files.
|
|
status_t readCoeffsFromFile();
|
|
|
|
FILE *mFp_4ch;
|
|
FILE *mFp_6ch;
|
|
int16_t **mRealCoeffs;
|
|
int16_t **mImagCoeffs;
|
|
void *mSurroundObj;
|
|
|
|
int16_t *mSurroundInputBuffer;
|
|
int16_t *mSurroundOutputBuffer;
|
|
int mSurroundInputBufferIdx;
|
|
int mSurroundOutputBufferIdx;
|
|
#endif
|
|
|
|
protected:
|
|
AudioHardwareALSA * mParent;
|
|
};
|
|
|
|
class AudioHardwareALSA : public AudioHardwareBase
|
|
{
|
|
public:
|
|
AudioHardwareALSA();
|
|
virtual ~AudioHardwareALSA();
|
|
|
|
/**
|
|
* check to see if the audio hardware interface has been initialized.
|
|
* return status based on values defined in include/utils/Errors.h
|
|
*/
|
|
virtual status_t initCheck();
|
|
|
|
/** set the audio volume of a voice call. Range is between 0.0 and 1.0 */
|
|
virtual status_t setVoiceVolume(float volume);
|
|
|
|
/**
|
|
* set the audio volume for all audio activities other than voice call.
|
|
* Range between 0.0 and 1.0. If any value other than NO_ERROR is returned,
|
|
* the software mixer will emulate this capability.
|
|
*/
|
|
virtual status_t setMasterVolume(float volume);
|
|
#ifdef QCOM_FM_ENABLED
|
|
virtual status_t setFmVolume(float volume);
|
|
#endif
|
|
/**
|
|
* setMode is called when the audio mode changes. NORMAL mode is for
|
|
* standard audio playback, RINGTONE when a ringtone is playing, and IN_CALL
|
|
* when a call is in progress.
|
|
*/
|
|
virtual status_t setMode(int mode);
|
|
|
|
// mic mute
|
|
virtual status_t setMicMute(bool state);
|
|
virtual status_t getMicMute(bool* state);
|
|
|
|
// set/get global audio parameters
|
|
virtual status_t setParameters(const String8& keyValuePairs);
|
|
virtual String8 getParameters(const String8& keys);
|
|
|
|
// Returns audio input buffer size according to parameters passed or 0 if one of the
|
|
// parameters is not supported
|
|
virtual size_t getInputBufferSize(uint32_t sampleRate, int format, int channels);
|
|
|
|
#ifdef QCOM_TUNNEL_LPA_ENABLED
|
|
/** This method creates and opens the audio hardware output
|
|
* session for LPA */
|
|
virtual AudioStreamOut* openOutputSession(
|
|
uint32_t devices,
|
|
int *format,
|
|
status_t *status,
|
|
int sessionId,
|
|
uint32_t samplingRate=0,
|
|
uint32_t channels=0);
|
|
virtual void closeOutputSession(AudioStreamOut* out);
|
|
#endif
|
|
|
|
/** This method creates and opens the audio hardware output stream */
|
|
virtual AudioStreamOut* openOutputStream(
|
|
uint32_t devices,
|
|
int *format=0,
|
|
uint32_t *channels=0,
|
|
uint32_t *sampleRate=0,
|
|
status_t *status=0);
|
|
virtual void closeOutputStream(AudioStreamOut* out);
|
|
|
|
/** This method creates and opens the audio hardware input stream */
|
|
virtual AudioStreamIn* openInputStream(
|
|
uint32_t devices,
|
|
int *format,
|
|
uint32_t *channels,
|
|
uint32_t *sampleRate,
|
|
status_t *status,
|
|
AudioSystem::audio_in_acoustics acoustics);
|
|
virtual void closeInputStream(AudioStreamIn* in);
|
|
|
|
/**This method dumps the state of the audio hardware */
|
|
//virtual status_t dumpState(int fd, const Vector<String16>& args);
|
|
|
|
static AudioHardwareInterface* create();
|
|
|
|
int mode()
|
|
{
|
|
return mMode;
|
|
}
|
|
|
|
protected:
|
|
virtual status_t dump(int fd, const Vector<String16>& args);
|
|
virtual uint32_t getVoipMode(int format);
|
|
void doRouting(int device);
|
|
#ifdef QCOM_FM_ENABLED
|
|
void handleFm(int device);
|
|
#endif
|
|
#ifdef QCOM_USBAUDIO_ENABLED
|
|
void closeUSBPlayback();
|
|
void closeUSBRecording();
|
|
void closeUsbRecordingIfNothingActive();
|
|
void closeUsbPlaybackIfNothingActive();
|
|
void startUsbPlaybackIfNotStarted();
|
|
void startUsbRecordingIfNotStarted();
|
|
#endif
|
|
|
|
void disableVoiceCall(char* verb, char* modifier, int mode, int device);
|
|
void enableVoiceCall(char* verb, char* modifier, int mode, int device);
|
|
bool routeVoiceCall(int device, int newMode);
|
|
bool routeVoLTECall(int device, int newMode);
|
|
friend class AudioStreamOutALSA;
|
|
friend class AudioStreamInALSA;
|
|
friend class ALSAStreamOps;
|
|
|
|
alsa_device_t * mALSADevice;
|
|
|
|
ALSAHandleList mDeviceList;
|
|
|
|
#ifdef QCOM_USBAUDIO_ENABLED
|
|
AudioUsbALSA *mAudioUsbALSA;
|
|
#endif
|
|
|
|
Mutex mLock;
|
|
|
|
snd_use_case_mgr_t *mUcMgr;
|
|
|
|
uint32_t mCurDevice;
|
|
/* The flag holds all the audio related device settings from
|
|
* Settings and Qualcomm Settings applications */
|
|
uint32_t mDevSettingsFlag;
|
|
uint32_t mVoipStreamCount;
|
|
uint32_t mVoipBitRate;
|
|
uint32_t mIncallMode;
|
|
|
|
bool mMicMute;
|
|
int mCSCallActive;
|
|
int mVolteCallActive;
|
|
int mCallState;
|
|
int mIsFmActive;
|
|
bool mBluetoothVGS;
|
|
bool mFusion3Platform;
|
|
#ifdef QCOM_USBAUDIO_ENABLED
|
|
int musbPlaybackState;
|
|
int musbRecordingState;
|
|
#endif
|
|
void *mAcdbHandle;
|
|
void *mCsdHandle;
|
|
};
|
|
|
|
// ----------------------------------------------------------------------------
|
|
|
|
}; // namespace android_audio_legacy
|
|
#endif // ANDROID_AUDIO_HARDWARE_ALSA_H
|