summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libaudio/AudioHardware.cpp60
-rw-r--r--libaudio/AudioHardware.h7
2 files changed, 60 insertions, 7 deletions
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;