audio: Initial support for amplifier HALs
authorChristopher N. Hesse <raymanfx@gmail.com>
Fri, 4 Aug 2017 19:17:55 +0000 (21:17 +0200)
committerChristopher N. Hesse <raymanfx@gmail.com>
Tue, 21 Nov 2017 19:55:14 +0000 (19:55 +0000)
Change-Id: I04ef5b89ca595a0df02f6a4a68748bd0d0cdb245

audio/Android.mk
audio/audio_hw.c
audio/audio_hw.h

index 9ececd2275783456d193eb551cfa0e4630567abf..3d9b14a77cfd0a9c0ba0d7b4ec36ad35320c5641 100644 (file)
@@ -32,6 +32,7 @@ LOCAL_SHARED_LIBRARIES := \
        liblog \
        libcutils \
        libaudioutils \
+       libhardware \
        libtinyalsa \
        libtinycompress \
        libaudioroute \
@@ -43,6 +44,7 @@ LOCAL_C_INCLUDES += \
        $(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) \
index 9a94e61a96ab0874830a4a9e25d50106eb19adad..7b6d642f3e656fa5a4c8f087bdb8bab53a663cd1 100644 (file)
@@ -246,6 +246,136 @@ static const struct string_to_enum out_channels_name_to_enum_table[] = {
     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 @@ static int enable_snd_device(struct audio_device *adev,
         }
         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 @@ int disable_snd_device(struct audio_device *adev,
             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 @@ static int select_devices(struct audio_device *adev,
     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 @@ static int out_standby(struct audio_stream *stream)
     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 @@ static int out_set_parameters(struct audio_stream *stream, const char *kvpairs)
         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 @@ static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
 #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 @@ static int in_standby_l(struct stream_in *in)
     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 @@ static ssize_t in_read(struct audio_stream_in *stream, void *buffer,
         }
         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 @@ static int adev_set_mode(struct audio_hw_device *dev, audio_mode_t mode)
     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 @@ static int adev_close(hw_device_t *device)
     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 bool period_size_is_plausible_for_low_latency(int period_size)
 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 @@ static int adev_open(const hw_module_t *module, const char *name,
         return -EINVAL;
     }
 
+    if (amplifier_open() != 0) {
+        ALOGE("Amplifier initialization failed");
+    }
+
     *device = &adev->device.common;
 
     audio_device_ref_count++;
index d05acded642efe78dc750026111f56866501e8e8..f1de6e824ce73badc2b0b6bb5a6d369ed2eedb04 100644 (file)
@@ -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 @@ struct audio_device {
     int                     (*sound_trigger_close_for_streaming)(int);
 
     pthread_mutex_t         lock_inputs; /* see note below on mutex acquisition order */
+    amplifier_device_t      *amp;
 };
 
 /*