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

Commit c89321b3 authored by jasmine cha's avatar jasmine cha Committed by Jasmine Cha
Browse files

audio: Add API to set audio calibration



 - add API of setting audio calibration only on platform

Bug: 74360112
Test: manual test
Change-Id: Ie0520f31cd1834fcb6faa1205b839336e9233678
Signed-off-by: default avatarjasmine cha <chajasmine@android.com>
parent 0f0aa55d
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ 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);
typedef int (*acdb_send_custom_top_t) (void);
typedef int (*acdb_set_audio_cal_t) (void *, void *, uint32_t);

struct meta_key_list {
    struct listnode list;
+175 −4
Original line number Diff line number Diff line
@@ -34,6 +34,8 @@
#include <sound/devdep_params.h>
#endif

#include <resolv.h>

#define MIXER_XML_DEFAULT_PATH "mixer_paths.xml"
#define MIXER_XML_BASE_STRING "mixer_paths"
#define TOMTOM_8226_SND_CARD_NAME "msm8226-tomtom-snd-card"
@@ -105,6 +107,21 @@ struct be_dai_name_struct {
static struct listnode operator_info_list;
static struct listnode *operator_specific_device_table[SND_DEVICE_MAX];

#define AUDIO_PARAMETER_KEY_AUD_CALDATA "cal_data"

typedef struct acdb_audio_cal_cfg {
    uint32_t             persist;
    uint32_t             snd_dev_id;
    audio_devices_t      dev_id;
    int32_t              acdb_dev_id;
    uint32_t             app_type;
    uint32_t             topo_id;
    uint32_t             sampling_rate;
    uint32_t             cal_type;
    uint32_t             module_id;
    uint32_t             param_id;
} acdb_audio_cal_cfg_t;

/* Audio calibration related functions */
typedef void (*acdb_send_audio_cal_v3_t)(int, int, int, int, int);

@@ -130,6 +147,7 @@ struct platform_data {
    acdb_deallocate_t          acdb_deallocate;
    acdb_send_audio_cal_t      acdb_send_audio_cal;
    acdb_send_audio_cal_v3_t   acdb_send_audio_cal_v3;
    acdb_set_audio_cal_t       acdb_set_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;
@@ -741,6 +759,139 @@ inline bool platform_supports_app_type_cfg()
#endif
}

static int parse_audiocal_cfg(struct str_parms *parms, acdb_audio_cal_cfg_t *cal)
{
    int err;
    char value[64];
    int ret = 0;

    if (parms == NULL || cal == NULL)
        return ret;

    err = str_parms_get_str(parms, "cal_persist", value, sizeof(value));
    if (err >= 0) {
        str_parms_del(parms, "cal_persist");
        cal->persist = (uint32_t)strtoul(value, NULL, 0);
        ret = ret | 0x1;
    }
    err = str_parms_get_str(parms, "cal_apptype", value, sizeof(value));
    if (err >= 0) {
        str_parms_del(parms, "cal_apptype");
        cal->app_type = (uint32_t)strtoul(value, NULL, 0);
        ret = ret | 0x2;
    }
    err = str_parms_get_str(parms, "cal_caltype", value, sizeof(value));
    if (err >= 0) {
        str_parms_del(parms, "cal_caltype");
        cal->cal_type = (uint32_t)strtoul(value, NULL, 0);
        ret = ret | 0x4;
    }
    err = str_parms_get_str(parms, "cal_samplerate", value, sizeof(value));
    if (err >= 0) {
        str_parms_del(parms, "cal_samplerate");
        cal->sampling_rate = (uint32_t)strtoul(value, NULL, 0);
        ret = ret | 0x8;
    }
    err = str_parms_get_str(parms, "cal_devid", value, sizeof(value));
    if (err >= 0) {
        str_parms_del(parms, "cal_devid");
        cal->dev_id = (uint32_t)strtoul(value, NULL, 0);
        ret = ret | 0x10;
    }
    err = str_parms_get_str(parms, "cal_snddevid", value, sizeof(value));
    if (err >= 0) {
        str_parms_del(parms, "cal_snddevid");
        cal->snd_dev_id = (uint32_t)strtoul(value, NULL, 0);
        ret = ret | 0x20;
    }
    err = str_parms_get_str(parms, "cal_topoid", value, sizeof(value));
    if (err >= 0) {
        str_parms_del(parms, "cal_topoid");
        cal->topo_id = (uint32_t)strtoul(value, NULL, 0);
        ret = ret | 0x40;
    }
    err = str_parms_get_str(parms, "cal_moduleid", value, sizeof(value));
    if (err >= 0) {
        str_parms_del(parms, "cal_moduleid");
        cal->module_id = (uint32_t)strtoul(value, NULL, 0);
        ret = ret | 0x80;
    }
    err = str_parms_get_str(parms, "cal_paramid", value, sizeof(value));
    if (err >= 0) {
        str_parms_del(parms, "cal_paramid");
        cal->param_id = (uint32_t)strtoul(value, NULL, 0);
        ret = ret | 0x100;
    }
    return ret;
}

static void set_audiocal(void *platform, struct str_parms *parms, char *value, int len)
{
    struct platform_data *my_data = (struct platform_data *)platform;
    acdb_audio_cal_cfg_t cal;
    uint8_t *dptr = NULL;
    int32_t dlen = 0;
    int err ,ret;

    if (value == NULL || platform == NULL || parms == NULL) {
        ALOGE("[%s] received null pointer, failed", __func__);
        goto done_key_audcal;
    }

    memset(&cal, 0, sizeof(acdb_audio_cal_cfg_t));
    /* parse audio calibration keys */
    ret = parse_audiocal_cfg(parms, &cal);

    /* handle audio calibration data now */
    err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_AUD_CALDATA, value, len);
    if (err >= 0) {
        str_parms_del(parms, AUDIO_PARAMETER_KEY_AUD_CALDATA);
        dlen = strlen(value);
        if (dlen <= 0) {
            ALOGE("[%s] null data received", __func__);
            goto done_key_audcal;
        }
        /*
           The base64 encoded string is always larger than the binary data,
           so b64_pton will always output less data than provided (around 1/3
           less than the input data). That's why we can allocate input buffer
           length and then get function work.
        */
        dptr = (uint8_t *)calloc(dlen, sizeof(uint8_t));
        if (dptr == NULL) {
            ALOGE("[%s] memory allocation failed for %d", __func__, dlen);
            goto done_key_audcal;
        }
        dlen = b64_pton(value, dptr, dlen);
        if (dlen <= 0) {
            ALOGE("[%s] data decoding failed %d", __func__, dlen);
            goto done_key_audcal;
        }

        if (cal.dev_id) {
            if (audio_is_input_device(cal.dev_id)) {
                cal.snd_dev_id = platform_get_input_snd_device(platform, cal.dev_id);
            } else {
                cal.snd_dev_id = platform_get_output_snd_device(platform, cal.dev_id);
            }
        }
        cal.acdb_dev_id = platform_get_snd_device_acdb_id(cal.snd_dev_id);
        ALOGD("Setting audio calibration for snd_device(%d) acdb_id(%d)",
                cal.snd_dev_id, cal.acdb_dev_id);
        if (cal.acdb_dev_id == -EINVAL) {
            ALOGE("[%s] Invalid acdb_device id %d for snd device id %d",
                       __func__, cal.acdb_dev_id, cal.snd_dev_id);
            goto done_key_audcal;
        }
        if (my_data->acdb_set_audio_cal) {
            ret = my_data->acdb_set_audio_cal((void *)&cal, (void *)dptr, dlen);
        }
    }
done_key_audcal:
    if (dptr != NULL)
        free(dptr);
}

bool platform_send_gain_dep_cal(void *platform, int level)
{
    bool ret_val = false;
@@ -1598,6 +1749,12 @@ void *platform_init(struct audio_device *adev)
            ALOGE("%s: Could not find the symbol acdb_get_default_app_type from %s",
                  __func__, LIB_ACDB_LOADER);

        my_data->acdb_set_audio_cal = (acdb_set_audio_cal_t)dlsym(my_data->acdb_handle,
                                                    "acdb_loader_set_audio_cal_v2");
        if (!my_data->acdb_set_audio_cal)
            ALOGE("%s: Could not find the symbol acdb_set_audio_cal_v2 from %s",
                  __func__, LIB_ACDB_LOADER);

        int result = acdb_init(adev->snd_card);
        if (!result) {
            my_data->acdb_initialized = true;
@@ -3139,8 +3296,9 @@ int platform_stop_incall_music_usecase(void *platform)
int platform_set_parameters(void *platform, struct str_parms *parms)
{
    struct platform_data *my_data = (struct platform_data *)platform;
    char value[128];
    char *value = NULL;
    char *kv_pairs = str_parms_to_str(parms);
    int len;
    int ret = 0, err;

    if (kv_pairs == NULL) {
@@ -3151,8 +3309,16 @@ int platform_set_parameters(void *platform, struct str_parms *parms)

    ALOGV("%s: enter: %s", __func__, kv_pairs);

    len = strlen(kv_pairs);
    value = (char*)calloc(len+1, sizeof(char));
    if (value == NULL) {
        ret = -ENOMEM;
        ALOGE("[%s] failed to allocate memory",__func__);
        goto done;
    }

    err = str_parms_get_str(parms, PLATFORM_CONFIG_KEY_SOUNDCARD_NAME,
                            value, sizeof(value));
                            value, len);
    if (err >= 0) {
        str_parms_del(parms, PLATFORM_CONFIG_KEY_SOUNDCARD_NAME);
        my_data->snd_card_name = strdup(value);
@@ -3160,7 +3326,7 @@ int platform_set_parameters(void *platform, struct str_parms *parms)
    }

    err = str_parms_get_str(parms, PLATFORM_CONFIG_KEY_OPERATOR_INFO,
                            value, sizeof(value));
                            value, len);
    if (err >= 0) {
        struct operator_info *info;
        char *str = value;
@@ -3178,19 +3344,24 @@ int platform_set_parameters(void *platform, struct str_parms *parms)

    memset(value, 0, sizeof(value));
    err = str_parms_get_str(parms, PLATFORM_CONFIG_KEY_MAX_MIC_COUNT,
                            value, sizeof(value));
                            value, len);
    if (err >= 0) {
        str_parms_del(parms, PLATFORM_CONFIG_KEY_MAX_MIC_COUNT);
        my_data->max_mic_count = atoi(value);
        ALOGV("%s: max_mic_count %s/%d", __func__, value, my_data->max_mic_count);
    }

    /* handle audio calibration parameters */
    set_audiocal(platform, parms, value, len);

    // to-do: disable setting sidetone gain, will revist this later
    // audio_extn_usb_set_sidetone_gain(parms, value, len);
done:
    ALOGV("%s: exit with code(%d)", __func__, ret);
    if (kv_pairs != NULL)
        free(kv_pairs);
    if (value != NULL)
        free(value);

    return ret;
}