From c4ac9e2cbf5521f857b1255f1ee48d9713e7ba78 Mon Sep 17 00:00:00 2001 From: Pawit Pornkitprasan Date: Thu, 25 Aug 2011 18:45:44 +0700 Subject: libaudio: Improve FM Radio - Set the volume control of the Si4709 chip (I891574d6 originally did this) - Set the playback path to HP, HP_NO_MIC, SPK as appropriate (allows WM8994 to apply its analog gain) - Turn off FM Radio properly to allow WM8994 to be turned off after disabling FM Radio (fixes battery drain and routing problems which caused FM Radio to be mute if you listen to FM, listen to music and listen to FM again.) Change-Id: Id04aaddc6de5ffe1c0826bea33fc8ec633afd419 --- libaudio/AudioHardware.cpp | 60 ++++++++++++++++++++++++++++++++++++++++------ libaudio/AudioHardware.h | 7 ++++++ 2 files changed, 60 insertions(+), 7 deletions(-) (limited to 'libaudio') diff --git a/libaudio/AudioHardware.cpp b/libaudio/AudioHardware.cpp index 939c54c..c2efbd1 100644 --- a/libaudio/AudioHardware.cpp +++ b/libaudio/AudioHardware.cpp @@ -40,6 +40,10 @@ extern "C" { #include "alsa_audio.h" } +#ifdef HAVE_FM_RADIO +#define Si4709_IOC_MAGIC 0xFA +#define Si4709_IOC_VOLUME_SET _IOW(Si4709_IOC_MAGIC, 15, __u8) +#endif namespace android { @@ -92,6 +96,9 @@ AudioHardware::AudioHardware() : mSecRilLibHandle(NULL), mRilClient(0), mActivatedCP(false), +#ifdef HAVE_FM_RADIO + mFmFd(-1), +#endif mDriverOp(DRV_NONE) { loadRILD(); @@ -523,6 +530,10 @@ status_t AudioHardware::setParameters(const String8& keyValuePairs) LOGV("AudioHardware::setParameters() FM Radio is ON, calling setFMRadioPath_l()"); setFMRadioPath_l(mOutput->device()); } + + if (mFmFd < 0) { + mFmFd = open("/dev/radio0", O_RDWR); + } } param.remove(key); @@ -532,22 +543,27 @@ status_t AudioHardware::setParameters(const String8& keyValuePairs) LOGV("AudioHardware::setParameters() Turning FM Radio OFF"); if (mMixer != NULL) { + // Disable FM radio flag to allow the codec to be turned off + // (the flag is automatically set by the kernel driver when FM is enabled) + // No need to turn off the FM Radio path as the kernel driver will handle that TRACE_DRIVER_IN(DRV_MIXER_GET) - struct mixer_ctl *ctl= mixer_get_control(mMixer, "FM Radio Path", 0); + struct mixer_ctl *ctl = mixer_get_control(mMixer, "Codec Status", 0); TRACE_DRIVER_OUT if (ctl != NULL) { TRACE_DRIVER_IN(DRV_MIXER_SEL) - mixer_ctl_select(ctl, "FMR_MIX_OFF"); - TRACE_DRIVER_OUT - - TRACE_DRIVER_IN(DRV_MIXER_SEL) - mixer_ctl_select(ctl, "FMR_OFF"); + mixer_ctl_select(ctl, "FMR_FLAG_CLEAR"); TRACE_DRIVER_OUT } + closeMixer_l(); closePcmOut_l(); } + + if (mFmFd > 0) { + close(mFmFd); + mFmFd = -1; + } } param.remove(key); #endif @@ -645,6 +661,21 @@ status_t AudioHardware::setMasterVolume(float volume) return -1; } +#ifdef HAVE_FM_RADIO +status_t AudioHardware::setFmVolume(float v) +{ + if (mFmFd > 0) { + __u8 fmVolume = (AudioSystem::logToLinear(v) + 5) / 7; + LOGD("%s %f %d", __func__, v, (int) fmVolume); + if (ioctl(mFmFd, Si4709_IOC_VOLUME_SET, &fmVolume) < 0) { + LOGE("set_volume_fm error."); + return -EIO; + } + } + return NO_ERROR; +} +#endif + static const int kDumpLockRetries = 50; static const int kDumpLockSleep = 20000; @@ -828,7 +859,22 @@ status_t AudioHardware::setFMRadioPath_l(uint32_t device) mixer_ctl_select(ctl, fmpath); TRACE_DRIVER_OUT } else { - LOGE("setFMRadioPath_l() could not get mixer ctl"); + LOGE("setFMRadioPath_l() could not get FM Radio Path mixer ctl"); + } + + TRACE_DRIVER_IN(DRV_MIXER_GET) + ctl = mixer_get_control(mMixer, "Playback Path", 0); + TRACE_DRIVER_OUT + + const char *route = getOutputRouteFromDevice(device); + LOGV("setFMRadioPath_l() Playpack Path, (%s)", route); + if (ctl) { + TRACE_DRIVER_IN(DRV_MIXER_SEL) + mixer_ctl_select(ctl, route); + TRACE_DRIVER_OUT + } + else { + LOGE("setFMRadioPath_l() could not get Playback Path mixer ctl"); } } else { LOGE("setFMRadioPath_l() mixer is not open"); diff --git a/libaudio/AudioHardware.h b/libaudio/AudioHardware.h index 71f11e7..b50e273 100644 --- a/libaudio/AudioHardware.h +++ b/libaudio/AudioHardware.h @@ -86,6 +86,9 @@ public: virtual status_t setVoiceVolume(float volume); virtual status_t setMasterVolume(float volume); +#ifdef HAVE_FM_RADIO + virtual status_t setFmVolume(float volume); +#endif virtual status_t setMode(int mode); @@ -177,6 +180,10 @@ private: void loadRILD(void); status_t connectRILDIfRequired(void); +#ifdef HAVE_FM_RADIO + int mFmFd; +#endif + // trace driver operations for dump int mDriverOp; -- cgit v1.1