audio: Initial support for amplifier HALs
Change-Id: I04ef5b89ca595a0df02f6a4a68748bd0d0cdb245
(cherry picked from commit 7a82a0e691d884045c78d1cb9f7ab0dd51a5d871)
diff --git a/audio/Android.mk b/audio/Android.mk
index 9ececd2..3d9b14a 100644
--- a/audio/Android.mk
+++ b/audio/Android.mk
@@ -32,6 +32,7 @@
liblog \
libcutils \
libaudioutils \
+ libhardware \
libtinyalsa \
libtinycompress \
libaudioroute \
@@ -43,6 +44,7 @@
$(LOCAL_PATH)/include \
external/tinyalsa/include \
external/tinycompress/include \
+ hardware/libhardware/include \
hardware/samsung/ril/libsecril-client \
$(call include-path-for, audio-utils) \
$(call include-path-for, audio-route) \
diff --git a/audio/audio_hw.c b/audio/audio_hw.c
index 9a94e61..7b6d642 100644
--- a/audio/audio_hw.c
+++ b/audio/audio_hw.c
@@ -246,6 +246,136 @@
STRING_TO_ENUM(AUDIO_CHANNEL_OUT_7POINT1),
};
+static struct audio_device *adev = NULL;
+
+static amplifier_device_t * get_amplifier_device(void)
+{
+ if (adev)
+ return adev->amp;
+
+ return NULL;
+}
+
+static int amplifier_open(void)
+{
+ int rc;
+ amplifier_module_t *module;
+
+ rc = hw_get_module(AMPLIFIER_HARDWARE_MODULE_ID,
+ (const hw_module_t **) &module);
+ if (rc) {
+ ALOGV("%s: Failed to obtain reference to amplifier module: %s\n",
+ __func__, strerror(-rc));
+ return -ENODEV;
+ }
+
+ rc = amplifier_device_open((const hw_module_t *) module, &adev->amp);
+ if (rc) {
+ ALOGV("%s: Failed to open amplifier hardware device: %s\n",
+ __func__, strerror(-rc));
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+static int amplifier_set_input_devices(uint32_t devices)
+{
+ amplifier_device_t *amp = get_amplifier_device();
+ if (amp && amp->set_input_devices)
+ return amp->set_input_devices(amp, devices);
+
+ return 0;
+}
+
+static int amplifier_set_output_devices(uint32_t devices)
+{
+ amplifier_device_t *amp = get_amplifier_device();
+ if (amp && amp->set_output_devices)
+ return amp->set_output_devices(amp, devices);
+
+ return 0;
+}
+
+static int amplifier_enable_devices(uint32_t devices, bool enable)
+{
+ amplifier_device_t *amp = get_amplifier_device();
+ bool is_output = devices > SND_DEVICE_OUT_BEGIN &&
+ devices < SND_DEVICE_OUT_END;
+
+ if (amp && amp->enable_output_devices && is_output)
+ return amp->enable_output_devices(amp, devices, enable);
+
+ if (amp && amp->enable_input_devices && !is_output)
+ return amp->enable_input_devices(amp, devices, enable);
+
+ return 0;
+}
+
+static int amplifier_set_mode(audio_mode_t mode)
+{
+ amplifier_device_t *amp = get_amplifier_device();
+ if (amp && amp->set_mode)
+ return amp->set_mode(amp, mode);
+
+ return 0;
+}
+
+static int amplifier_output_stream_start(struct audio_stream_out *stream,
+ bool offload)
+{
+ amplifier_device_t *amp = get_amplifier_device();
+ if (amp && amp->output_stream_start)
+ return amp->output_stream_start(amp, stream, offload);
+
+ return 0;
+}
+
+static int amplifier_input_stream_start(struct audio_stream_in *stream)
+{
+ amplifier_device_t *amp = get_amplifier_device();
+ if (amp && amp->input_stream_start)
+ return amp->input_stream_start(amp, stream);
+
+ return 0;
+}
+
+static int amplifier_output_stream_standby(struct audio_stream_out *stream)
+{
+ amplifier_device_t *amp = get_amplifier_device();
+ if (amp && amp->output_stream_standby)
+ return amp->output_stream_standby(amp, stream);
+
+ return 0;
+}
+
+static int amplifier_input_stream_standby(struct audio_stream_in *stream)
+{
+ amplifier_device_t *amp = get_amplifier_device();
+ if (amp && amp->input_stream_standby)
+ return amp->input_stream_standby(amp, stream);
+
+ return 0;
+}
+
+static int amplifier_set_parameters(struct str_parms *parms)
+{
+ amplifier_device_t *amp = get_amplifier_device();
+ if (amp && amp->set_parameters)
+ return amp->set_parameters(amp, parms);
+
+ return 0;
+}
+
+static int amplifier_close(void)
+{
+ amplifier_device_t *amp = get_amplifier_device();
+ if (amp)
+ amplifier_device_close(amp);
+
+ return 0;
+}
+
struct timespec time_spec_diff(struct timespec time1, struct timespec time0) {
struct timespec ret;
int xsec = 0;
@@ -831,6 +961,9 @@
}
update_mixer = true;
#endif /* DSP_POWEROFF_DELAY */
+
+ amplifier_enable_devices(snd_device, true);
+
audio_route_apply_path(mixer_card->audio_route, snd_device_name);
if (update_mixer) {
audio_route_update_mixer(mixer_card->audio_route);
@@ -876,6 +1009,8 @@
if (update_mixer) {
audio_route_update_mixer(mixer_card->audio_route);
}
+
+ amplifier_enable_devices(snd_device, false);
#ifdef DSP_POWEROFF_DELAY
clock_gettime(CLOCK_MONOTONIC, &(mixer_card->dsp_poweroff_time));
#endif /* DSP_POWEROFF_DELAY */
@@ -1000,6 +1135,10 @@
usecase->in_snd_device = in_snd_device;
usecase->out_snd_device = out_snd_device;
+ /* Rely on amplifier_set_devices to distinguish between in/out devices */
+ amplifier_set_input_devices(in_snd_device);
+ amplifier_set_output_devices(out_snd_device);
+
return 0;
}
@@ -2682,6 +2821,7 @@
lock_output_stream(out);
if (!out->standby) {
pthread_mutex_lock(&adev->lock);
+ amplifier_output_stream_standby((struct audio_stream_out *) stream);
do_out_standby_l(out);
pthread_mutex_unlock(&adev->lock);
}
@@ -2819,6 +2959,8 @@
pthread_mutex_unlock(&adev->lock_inputs);
}
+ amplifier_set_parameters(parms);
+
if (out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD) {
parse_compress_metadata(out, parms);
}
@@ -2966,6 +3108,10 @@
#endif
pthread_mutex_lock(&adev->lock);
ret = start_output_stream(out);
+ if (ret == 0) {
+ amplifier_output_stream_start(stream, out->usecase == USECASE_AUDIO_PLAYBACK_OFFLOAD);
+ }
+
/* ToDo: If use case is compress offload should return 0 */
if (ret != 0) {
pthread_mutex_unlock(&adev->lock);
@@ -3382,6 +3528,7 @@
lock_input_stream(in);
if (!in->standby) {
pthread_mutex_lock(&adev->lock);
+ amplifier_input_stream_standby((struct audio_stream_in *) in);
status = do_in_standby_l(in);
pthread_mutex_unlock(&adev->lock);
}
@@ -3547,8 +3694,12 @@
}
pthread_mutex_lock(&adev->lock);
ret = start_input_stream(in);
+ if (ret == 0) {
+ amplifier_input_stream_start(stream);
+ }
pthread_mutex_unlock(&adev->lock);
pthread_mutex_unlock(&adev->lock_inputs);
+
if (ret != 0) {
goto exit;
}
@@ -4120,6 +4271,9 @@
pthread_mutex_lock(&adev->lock);
if (adev->mode != mode) {
ALOGI("%s mode = %d", __func__, mode);
+ if (amplifier_set_mode(mode) != 0) {
+ ALOGE("Failed setting amplifier mode");
+ }
adev->mode = mode;
}
pthread_mutex_unlock(&adev->lock);
@@ -4320,10 +4474,17 @@
struct audio_device *adev = (struct audio_device *)device;
voice_session_deinit(adev->voice.session);
audio_device_ref_count--;
+ if (audio_device_ref_count == 0) {
+ if (amplifier_close() != 0) {
+ ALOGE("Amplifier close failed");
+ }
+ }
free(adev->snd_dev_ref_cnt);
free_mixer_list(adev);
free(device);
+ adev = NULL;
+
return 0;
}
@@ -4348,8 +4509,6 @@
static int adev_open(const hw_module_t *module, const char *name,
hw_device_t **device)
{
- struct audio_device *adev;
-
ALOGV("%s: enter", __func__);
if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;
@@ -4464,6 +4623,10 @@
return -EINVAL;
}
+ if (amplifier_open() != 0) {
+ ALOGE("Amplifier initialization failed");
+ }
+
*device = &adev->device.common;
audio_device_ref_count++;
diff --git a/audio/audio_hw.h b/audio/audio_hw.h
index d05acde..f1de6e8 100644
--- a/audio/audio_hw.h
+++ b/audio/audio_hw.h
@@ -20,6 +20,7 @@
#include <cutils/list.h>
#include <hardware/audio.h>
+#include <hardware/audio_amplifier.h>
#include <tinyalsa/asoundlib.h>
#include <tinycompress/tinycompress.h>
@@ -428,6 +429,7 @@
int (*sound_trigger_close_for_streaming)(int);
pthread_mutex_t lock_inputs; /* see note below on mutex acquisition order */
+ amplifier_device_t *amp;
};
/*