hal: Support the audio amplifier hook
* Original legacy HAL commit:
Ib236598a5888b2af19bcfb81e285f644a0e84c0d
* Example: http://review.cyanogenmod.org/38221
(cyanogen: Refactored to be an audio_extn)
Change-Id: Ic944a9f7059c78b79322dae9c787cdd8bb029cff
audio: add amplifier stream start/standby operations
Change-Id: I5de7ad7a0467e7cf822c9c0870a755c03d05e884
hal: Convert libaudioamp to audio_amplifier HAL
Change-Id: I1d0f63a46989d1792d7a5e08d2bdb6344ebafa31
hal: Notify amplifier of device enable/disable
Change-Id: Ice808c9b55a9e3bc8bafe5ca3ff555377d38dd8f
hal: enable amplifier earlier
Change-Id: Id876e8f836e3ce1ee5f8186ca9c0e6ef5f37182c
hal: only open the amplifier once
Change-Id: Ie9bbff74123e90b71e95809a84dcb3bbe9ba82fe
hal: notify amplifier of parameter changes
Change-Id: Iecc020c0347ae7c43d27183186e06dcefef7a0dd
hal: Clean up audio amplifier usage
* Externalize it into an extension file similar to the rest.
Change-Id: I03de7efa9bab8870099028170fa471dfffe1ce84
audio: add amplifier hooks for stream parameter manipulation
Change-Id: I16a76475cb58a710d229648d77024379bfc499d5
diff --git a/hal/Android.mk b/hal/Android.mk
index d5aa190..302d5e2 100644
--- a/hal/Android.mk
+++ b/hal/Android.mk
@@ -336,6 +336,12 @@
LOCAL_SHARED_LIBRARIES += vendor.qti.hardware.audiohalext@1.0
endif
+ifneq ($(strip $(AUDIO_FEATURE_ENABLED_EXT_AMPLIFIER)),false)
+ LOCAL_CFLAGS += -DEXT_AMPLIFIER_ENABLED
+ LOCAL_SRC_FILES += audio_extn/audio_amplifier.c
+ LOCAL_SHARED_LIBRARIES += libhardware
+endif
+
ifeq ($(strip $(AUDIO_FEATURE_ELLIPTIC_ULTRASOUND_SUPPORT)),true)
LOCAL_CFLAGS += -DELLIPTIC_ULTRASOUND_ENABLED
LOCAL_SRC_FILES += audio_extn/ultrasound.c
diff --git a/hal/audio_extn/audio_amplifier.c b/hal/audio_extn/audio_amplifier.c
new file mode 100644
index 0000000..a3e0263
--- /dev/null
+++ b/hal/audio_extn/audio_amplifier.c
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2016 The CyanogenMod Project
+ *
+ * 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.
+ */
+
+#define LOG_TAG "audio_amplifier"
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <cutils/log.h>
+
+#include "audio_hw.h"
+#include "platform.h"
+
+struct amplifier_data {
+ struct audio_device *adev;
+ amplifier_device_t *hw;
+};
+
+struct amplifier_data amp;
+
+int amplifier_open(void* adev)
+{
+ int rc;
+ amplifier_module_t *module;
+ amp.adev = (struct audio_device *)adev;
+
+ 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, &.hw);
+ if (rc) {
+ ALOGV("%s: Failed to open amplifier hardware device: %s\n",
+ __func__, strerror(-rc));
+ amp.hw = NULL;
+
+ return -ENODEV;
+ }
+
+ return 0;
+}
+
+int amplifier_set_input_devices(uint32_t devices)
+{
+ if (amp.hw && amp.hw->set_input_devices)
+ return amp.hw->set_input_devices(amp.hw, devices);
+
+ return 0;
+}
+
+int amplifier_set_output_devices(uint32_t devices)
+{
+ if (amp.hw && amp.hw->set_output_devices)
+ return amp.hw->set_output_devices(amp.hw, devices);
+
+ return 0;
+}
+
+int amplifier_enable_devices(uint32_t devices, bool enable)
+{
+ bool is_output = devices < SND_DEVICE_OUT_END;
+
+ if (amp.hw && amp.hw->enable_output_devices && is_output)
+ return amp.hw->enable_output_devices(amp.hw, devices, enable);
+
+ if (amp.hw && amp.hw->enable_input_devices && !is_output)
+ return amp.hw->enable_input_devices(amp.hw, devices, enable);
+
+ return 0;
+}
+
+int amplifier_set_mode(audio_mode_t mode)
+{
+ if (amp.hw && amp.hw->set_mode)
+ return amp.hw->set_mode(amp.hw, mode);
+
+ return 0;
+}
+
+int amplifier_output_stream_start(struct audio_stream_out *stream,
+ bool offload)
+{
+ if (amp.hw && amp.hw->output_stream_start)
+ return amp.hw->output_stream_start(amp.hw, stream, offload);
+
+ return 0;
+}
+
+int amplifier_input_stream_start(struct audio_stream_in *stream)
+{
+ if (amp.hw && amp.hw->input_stream_start)
+ return amp.hw->input_stream_start(amp.hw, stream);
+
+ return 0;
+}
+
+int amplifier_output_stream_standby(struct audio_stream_out *stream)
+{
+ if (amp.hw && amp.hw->output_stream_standby)
+ return amp.hw->output_stream_standby(amp.hw, stream);
+
+ return 0;
+}
+
+int amplifier_input_stream_standby(struct audio_stream_in *stream)
+{
+ if (amp.hw && amp.hw->input_stream_standby)
+ return amp.hw->input_stream_standby(amp.hw, stream);
+
+ return 0;
+}
+
+int amplifier_set_parameters(struct str_parms *parms)
+{
+ if (amp.hw && amp.hw->set_parameters)
+ return amp.hw->set_parameters(amp.hw, parms);
+
+ return 0;
+}
+
+int amplifier_out_set_parameters(struct str_parms *parms)
+{
+ if (amp.hw && amp.hw->out_set_parameters)
+ return amp.hw->out_set_parameters(amp.hw, parms);
+
+ return 0;
+}
+
+int amplifier_in_set_parameters(struct str_parms *parms)
+{
+ if (amp.hw && amp.hw->in_set_parameters)
+ return amp.hw->in_set_parameters(amp.hw, parms);
+
+ return 0;
+}
+
+int amplifier_close(void)
+{
+ if (amp.hw)
+ amplifier_device_close(amp.hw);
+
+ amp.hw = NULL;
+
+ return 0;
+}
diff --git a/hal/audio_extn/audio_amplifier.h b/hal/audio_extn/audio_amplifier.h
new file mode 100644
index 0000000..641f023
--- /dev/null
+++ b/hal/audio_extn/audio_amplifier.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2016 The CyanogenMod Project
+ *
+ * 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 EXTN_AMPLIFIER_H
+#define EXTN_AMPLIFIER_H
+
+#ifndef EXT_AMPLIFIER_ENABLED
+#define amplifier_open(adev) (0)
+#define amplifier_set_input_devices(devices) (0)
+#define amplifier_set_output_devices(devices) (0)
+#define amplifier_enable_devices(devices, enable) (0)
+#define amplifier_set_mode(mode) (0)
+#define amplifier_output_stream_start(stream, offload) (0)
+#define amplifier_input_stream_start(stream) (0)
+#define amplifier_output_stream_standby(stream) (0)
+#define amplifier_input_stream_standby(stream) (0)
+#define amplifier_set_parameters(parms) (0)
+#define amplifier_out_set_parameters(parms) (0)
+#define amplifier_in_set_parameters(parms) (0)
+#define amplifier_close() (0)
+#else
+
+int amplifier_open(void* adev);
+int amplifier_set_input_devices(uint32_t devices);
+int amplifier_set_output_devices(uint32_t devices);
+int amplifier_enable_devices(uint32_t devices, bool enable);
+int amplifier_set_mode(audio_mode_t mode);
+int amplifier_output_stream_start(struct audio_stream_out *stream,
+ bool offload);
+int amplifier_input_stream_start(struct audio_stream_in *stream);
+int amplifier_output_stream_standby(struct audio_stream_out *stream);
+int amplifier_input_stream_standby(struct audio_stream_in *stream);
+int amplifier_set_parameters(struct str_parms *parms);
+int amplifier_out_set_parameters(struct str_parms *parms);
+int amplifier_in_set_parameters(struct str_parms *parms);
+int amplifier_close(void);
+#endif
+
+#endif
diff --git a/hal/audio_hw.c b/hal/audio_hw.c
index 27e2fa3..59d1888 100644
--- a/hal/audio_hw.c
+++ b/hal/audio_hw.c
@@ -75,6 +75,7 @@
#include "audio_extn.h"
#include "voice_extn.h"
#include "ip_hdlr_intf.h"
+#include "audio_amplifier.h"
#include "ultrasound.h"
#include "sound/compress_params.h"
@@ -1328,6 +1329,7 @@
goto err;
}
audio_extn_dev_arbi_acquire(snd_device);
+ amplifier_enable_devices(snd_device, true);
audio_route_apply_and_update_path(adev->audio_route, device_name);
if (SND_DEVICE_OUT_HEADPHONES == snd_device &&
@@ -1400,6 +1402,7 @@
platform_set_speaker_gain_in_combo(adev, snd_device, false);
} else {
audio_route_reset_and_update_path(adev->audio_route, device_name);
+ amplifier_enable_devices(snd_device, false);
}
if (snd_device == SND_DEVICE_OUT_BT_A2DP)
@@ -2746,6 +2749,10 @@
voice_set_sidetone(adev, out_snd_device, true);
}
+ /* 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);
+
/* Applicable only on the targets that has external modem.
* Enable device command should be sent to modem only after
* enabling voice call mixer controls
@@ -4191,6 +4198,9 @@
stop_compressed_output_l(out);
pthread_mutex_lock(&adev->lock);
+
+ amplifier_output_stream_standby((struct audio_stream_out *) stream);
+
out->standby = true;
if (out->usecase == USECASE_COMPRESS_VOIP_CALL) {
voice_extn_compress_voip_close_output_stream(stream);
@@ -4449,6 +4459,9 @@
parms = str_parms_create_str(kvpairs);
if (!parms)
goto error;
+
+ amplifier_out_set_parameters(parms);
+
err = str_parms_get_str(parms, AUDIO_PARAMETER_STREAM_ROUTING, value, sizeof(value));
if (err >= 0) {
val = atoi(value);
@@ -5445,6 +5458,11 @@
ret = voice_extn_compress_voip_start_output_stream(out);
else
ret = start_output_stream(out);
+
+ if (ret == 0)
+ amplifier_output_stream_start(stream,
+ is_offload_usecase(out->usecase));
+
pthread_mutex_unlock(&adev->lock);
/* ToDo: If use case is compress offload should return 0 */
if (ret != 0) {
@@ -6274,6 +6292,9 @@
adev->adm_deregister_stream(adev->adm_data, in->capture_handle);
pthread_mutex_lock(&adev->lock);
+
+ amplifier_input_stream_standby((struct audio_stream_in *) stream);
+
in->standby = true;
if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
do_stop = false;
@@ -6384,6 +6405,9 @@
if (!parms)
goto error;
+
+ amplifier_in_set_parameters(parms);
+
lock_input_stream(in);
pthread_mutex_lock(&adev->lock);
@@ -6581,6 +6605,10 @@
ret = start_input_stream(in);
if (!ret && in->source == AUDIO_SOURCE_VOICE_RECOGNITION)
adev->num_va_sessions++;
+
+ if (ret == 0)
+ amplifier_input_stream_start(stream);
+
pthread_mutex_unlock(&adev->lock);
if (ret != 0) {
goto exit;
@@ -8381,6 +8409,7 @@
}
}
+ amplifier_set_parameters(parms);
audio_extn_set_parameters(adev, parms);
done:
str_parms_destroy(parms);
@@ -8507,6 +8536,8 @@
pthread_mutex_lock(&adev->lock);
if (adev->mode != mode) {
ALOGD("%s: mode %d\n", __func__, mode);
+ if (amplifier_set_mode(mode) != 0)
+ ALOGE("Failed setting amplifier mode");
adev->mode = mode;
if (voice_is_in_call(adev) &&
(mode == AUDIO_MODE_NORMAL ||
@@ -9368,6 +9399,8 @@
if ((--audio_device_ref_count) == 0) {
if (audio_extn_spkr_prot_is_enabled())
audio_extn_spkr_prot_deinit();
+ if (amplifier_close() != 0)
+ ALOGE("Amplifier close failed");
audio_extn_snd_mon_unregister_listener(adev);
audio_extn_sound_trigger_deinit(adev);
audio_extn_listen_deinit(adev);
@@ -9787,6 +9820,9 @@
audio_extn_ds2_enable(adev);
+ if (amplifier_open(adev) != 0)
+ ALOGE("Amplifier initialization failed");
+
us_init(adev);
*device = &adev->device.common;
diff --git a/hal/audio_hw.h b/hal/audio_hw.h
index dc62f83..33ee477 100644
--- a/hal/audio_hw.h
+++ b/hal/audio_hw.h
@@ -41,6 +41,7 @@
#include <stdlib.h>
#include <cutils/str_parms.h>
#include <cutils/list.h>
+#include <hardware/audio_amplifier.h>
#include <hardware/audio.h>
#include <tinyalsa/asoundlib.h>
#include <tinycompress/tinycompress.h>
@@ -683,6 +684,8 @@
bool adm_routing_changed;
struct listnode audio_patch_record_list;
unsigned int audio_patch_index;
+
+ amplifier_device_t *amp;
};
struct audio_patch_record {