diff --git a/audio/Android.mk b/audio/Android.mk index 9ececd22..3d9b14a7 100644 --- a/audio/Android.mk +++ b/audio/Android.mk @@ -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) \ diff --git a/audio/audio_hw.c b/audio/audio_hw.c index 9a94e61a..7b6d642f 100644 --- a/audio/audio_hw.c +++ b/audio/audio_hw.c @@ -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++; diff --git a/audio/audio_hw.h b/audio/audio_hw.h index d05acded..f1de6e82 100644 --- a/audio/audio_hw.h +++ b/audio/audio_hw.h @@ -20,6 +20,7 @@ #include #include +#include #include #include @@ -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; }; /*