Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1a9b7c0f authored by vivek mehta's avatar vivek mehta Committed by Eric Laurent
Browse files

hal: post_proc: add volume based audio calibration support

- add new effect module to listen to volume and device change
- based on volume levels of all streams active over speaker
  compute gain based calibration level and communicate
  with audio HAL to send the same to ACDB loader
- make audio HAL singleton

Bug: 22100304.

Change-Id: If74bf66d32def85022d79ccb9f84c3b85c8a2dc9
parent a0a75dad
Loading
Loading
Loading
Loading
+59 −13
Original line number Diff line number Diff line
@@ -181,6 +181,30 @@ static const struct string_to_enum out_channels_name_to_enum_table[] = {
};

static int set_voice_volume_l(struct audio_device *adev, float volume);
static struct audio_device *adev = NULL;
static pthread_mutex_t adev_init_lock;
static unsigned int audio_device_ref_count;

__attribute__ ((visibility ("default")))
bool audio_hw_send_gain_dep_calibration(int level) {
    bool ret_val = false;
    ALOGV("%s: enter ... ", __func__);

    pthread_mutex_lock(&adev_init_lock);

    if (adev != NULL && adev->platform != NULL) {
        pthread_mutex_lock(&adev->lock);
        ret_val = platform_send_gain_dep_cal(adev->platform, level);
        pthread_mutex_unlock(&adev->lock);
    } else {
        ALOGE("%s: %s is NULL", __func__, adev == NULL ? "adev" : "adev->platform");
    }

    pthread_mutex_unlock(&adev_init_lock);

    ALOGV("%s: exit with ret_val %d ", __func__, ret_val);
    return ret_val;
}

static bool is_supported_format(audio_format_t format)
{
@@ -1593,7 +1617,7 @@ exit:

    if (ret != 0) {
        if (out->pcm)
            ALOGE("%s: error %d - %s", __func__, ret, pcm_get_error(out->pcm));
            ALOGE("%s: error %zu - %s", __func__, ret, pcm_get_error(out->pcm));
        out_standby(&out->stream.common);
        usleep(bytes * 1000000 / audio_stream_out_frame_size(stream) /
               out_get_sample_rate(&out->stream.common));
@@ -1660,7 +1684,7 @@ static int out_get_presentation_position(const struct audio_stream_out *stream,
        }
    } else {
        if (out->pcm) {
            size_t avail;
            unsigned int avail;
            if (pcm_get_htimestamp(out->pcm, &avail, timestamp) == 0) {
                size_t kernel_buffer_size = out->config.period_size * out->config.period_count;
                int64_t signed_frames = out->written - kernel_buffer_size + avail;
@@ -2694,6 +2718,13 @@ static int adev_close(hw_device_t *device)
{
    size_t i;
    struct audio_device *adev = (struct audio_device *)device;

    if (!adev)
        return 0;

    pthread_mutex_lock(&adev_init_lock);

    if ((--audio_device_ref_count) == 0) {
        audio_route_free(adev->audio_route);
        free(adev->snd_dev_ref_cnt);
        platform_deinit(adev->platform);
@@ -2703,6 +2734,9 @@ static int adev_close(hw_device_t *device)
            pcm_params_free(adev->use_case_table[i]);
        }
        free(device);
    }

    pthread_mutex_unlock(&adev_init_lock);
    return 0;
}

@@ -2730,12 +2764,19 @@ static int 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;
    int i, ret;

    ALOGD("%s: enter", __func__);
    if (strcmp(name, AUDIO_HARDWARE_INTERFACE) != 0) return -EINVAL;

    pthread_mutex_lock(&adev_init_lock);
    if (audio_device_ref_count != 0) {
        *device = &adev->device.common;
        audio_device_ref_count++;
        ALOGV("%s: returning existing instance of adev", __func__);
        ALOGV("%s: exit", __func__);
        pthread_mutex_unlock(&adev_init_lock);
        return 0;
    }
    adev = calloc(1, sizeof(struct audio_device));

    pthread_mutex_init(&adev->lock, (const pthread_mutexattr_t *) NULL);
@@ -2783,6 +2824,7 @@ static int adev_open(const hw_module_t *module, const char *name,
        free(adev);
        ALOGE("%s: Failed to init platform data, aborting.", __func__);
        *device = NULL;
        pthread_mutex_unlock(&adev_init_lock);
        return -EINVAL;
    }

@@ -2825,6 +2867,7 @@ static int adev_open(const hw_module_t *module, const char *name,
    adev->enable_voicerx = false;

    *device = &adev->device.common;

    if (k_enable_extended_precision)
        adev_verify_devices(adev);

@@ -2846,6 +2889,9 @@ static int adev_open(const hw_module_t *module, const char *name,
        }
    }

    audio_device_ref_count++;
    pthread_mutex_unlock(&adev_init_lock);

    ALOGV("%s: exit", __func__);
    return 0;
}
+3 −1
Original line number Diff line number Diff line
@@ -1008,7 +1008,9 @@ int platform_set_snd_device_backend(snd_device_t device __unused,
    return -ENOSYS;
}

void platform_set_echo_reference(struct audio_device *adev, bool enable, audio_devices_t out_device)
void platform_set_echo_reference(struct audio_device *adev __unused,
                                 bool enable __unused,
                                 audio_devices_t out_device __unused)
{
    return;
}
+69 −0
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@
#include <platform_api.h>
#include "platform.h"
#include "audio_extn.h"
#include <linux/msm_audio.h>

#define MIXER_XML_PATH "/system/etc/mixer_paths.xml"
#define LIB_ACDB_LOADER "libacdbloader.so"
@@ -54,12 +55,20 @@
#define RETRY_US 500000
#define MAX_SND_CARD 8

#define DEFAULT_APP_TYPE_RX_PATH  0x11130

struct audio_block_header
{
    int reserved;
    int length;
};

enum {
    CAL_MODE_SEND           = 0x1,
    CAL_MODE_PERSIST        = 0x2,
    CAL_MODE_RTAC           = 0x4
};

/* Audio calibration related functions */
typedef void (*acdb_deallocate_t)();
#ifdef PLATFORM_MSM8084
@@ -70,6 +79,7 @@ typedef int (*acdb_init_t)();
typedef void (*acdb_send_audio_cal_t)(int, int);
typedef void (*acdb_send_voice_cal_t)(int, int);
typedef int (*acdb_reload_vocvoltable_t)(int);
typedef int (*acdb_send_gain_dep_cal_t)(int, int, int, int, int);

/* Audio calibration related functions */
struct platform_data {
@@ -87,6 +97,7 @@ struct platform_data {
    acdb_send_audio_cal_t      acdb_send_audio_cal;
    acdb_send_voice_cal_t      acdb_send_voice_cal;
    acdb_reload_vocvoltable_t  acdb_reload_vocvoltable;
    acdb_send_gain_dep_cal_t   acdb_send_gain_dep_cal;
    struct csd_data *csd;
    bool ext_speaker;
    bool ext_earpiece;
@@ -431,6 +442,57 @@ bool is_operator_tmus()
    return is_tmus;
}

bool platform_send_gain_dep_cal(void *platform, int level)
{
    bool ret_val = false;
    struct platform_data *my_data = (struct platform_data *)platform;
    struct audio_device *adev = my_data->adev;
    int acdb_dev_id, app_type;
    int acdb_dev_type = MSM_SNDDEV_CAP_RX;
    int mode = CAL_MODE_RTAC;
    struct listnode *node;
    struct audio_usecase *usecase;
	snd_device_t snd_device;

    if (my_data->acdb_send_gain_dep_cal == NULL) {
        ALOGE("%s: dlsym error for acdb_send_gain_dep_cal", __func__);
        return ret_val;
    }

    if (!voice_is_in_call(adev)) {
        ALOGV("%s: Not Voice call usecase, apply new cal for level %d",
               __func__, level);
        app_type = DEFAULT_APP_TYPE_RX_PATH;

        // find the current active sound device
        list_for_each(node, &adev->usecase_list) {
            usecase = node_to_item(node, struct audio_usecase, list);

            if (usecase != NULL &&
                usecase->type == PCM_PLAYBACK &&
                (usecase->stream.out->devices == AUDIO_DEVICE_OUT_SPEAKER)) {

                ALOGV("%s: out device is %d", __func__,  usecase->out_snd_device);
                snd_device = audio_extn_spkr_prot_get_acdb_id(usecase->out_snd_device);
                acdb_dev_id = acdb_device_table[snd_device];
                if (!my_data->acdb_send_gain_dep_cal(acdb_dev_id, app_type,
                                                     acdb_dev_type, mode, level)) {
                    // set ret_val true if at least one calibration is set successfully
                    ret_val = true;
                } else {
                    ALOGE("%s: my_data->acdb_send_gain_dep_cal failed ", __func__);
                }
            } else {
                ALOGW("%s: Usecase list is empty", __func__);
            }
        }
    } else {
        ALOGW("%s: Voice call in progress .. ignore setting new cal",
              __func__);
    }
    return ret_val;
}

void platform_set_echo_reference(struct audio_device *adev, bool enable, audio_devices_t out_device)
{
    struct platform_data *my_data = (struct platform_data *)adev->platform;
@@ -821,6 +883,13 @@ void *platform_init(struct audio_device *adev)
        if (!my_data->acdb_reload_vocvoltable)
            ALOGE("%s: Could not find the symbol acdb_loader_reload_vocvoltable from %s",
                  __func__, LIB_ACDB_LOADER);

        my_data->acdb_send_gain_dep_cal = (acdb_send_gain_dep_cal_t)dlsym(my_data->acdb_handle,
                                                    "acdb_loader_send_gain_dep_cal");
        if (!my_data->acdb_send_gain_dep_cal)
            ALOGV("%s: Could not find the symbol acdb_loader_send_gain_dep_cal from %s",
                  __func__, LIB_ACDB_LOADER);

#ifdef PLATFORM_MSM8084
        my_data->acdb_init = (acdb_init_t)dlsym(my_data->acdb_handle,
                                                    "acdb_loader_init_v2");
+1 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ void platform_deinit(void *platform);
const char *platform_get_snd_device_name(snd_device_t snd_device);
void platform_add_backend_name(void *platform, char *mixer_path,
                                                    snd_device_t snd_device);
bool platform_send_gain_dep_cal(void *platform, int level);
int platform_get_pcm_device_id(audio_usecase_t usecase, int device_type);
int platform_get_snd_device_index(char *snd_device_index_name);
int platform_set_snd_device_acdb_id(snd_device_t snd_device, unsigned int acdb_id);
+27 −0
Original line number Diff line number Diff line
@@ -28,6 +28,33 @@ LOCAL_C_INCLUDES := \
	external/tinyalsa/include \
	$(call include-path-for, audio-effects)

include $(BUILD_SHARED_LIBRARY)
endif

################################################################################

ifneq ($(filter msm8992 msm8994,$(TARGET_BOARD_PLATFORM)),)

include $(CLEAR_VARS)

LOCAL_CFLAGS := -DLIB_AUDIO_HAL="/system/lib/hw/audio.primary."$(TARGET_BOARD_PLATFORM)".so"

LOCAL_SRC_FILES:= \
	volume_listener.c

LOCAL_CFLAGS+= -O2 -fvisibility=hidden

LOCAL_SHARED_LIBRARIES := \
	libcutils \
	liblog \
	libdl

LOCAL_MODULE_RELATIVE_PATH := soundfx
LOCAL_MODULE:= libvolumelistener

LOCAL_C_INCLUDES := \
	$(call include-path-for, audio-effects)

include $(BUILD_SHARED_LIBRARY)

endif
Loading