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

Commit 429eb457 authored by Dhananjay Kumar's avatar Dhananjay Kumar Committed by Dhanalakshmi Siddani
Browse files

hal: add support to set custom channel configs

Add generic implementation to set custom channel configs
as per usecase config present in platform info xml.
Each usecase identified by usecase id, input channels,
output channels, snd_device and feature id can have
a separate channel config.

Change-Id: I957b5b06adbcd17f65ed49b839327bf8e9e8b318
parent 31195059
Loading
Loading
Loading
Loading
+151 −0
Original line number Diff line number Diff line
@@ -363,6 +363,157 @@ static void audio_extn_ext_disp_set_parameters(const struct audio_device *adev,
    }
}

static int update_custom_mtmx_coefficients(struct audio_device *adev,
                                           struct audio_custom_mtmx_params *params,
                                           int pcm_device_id)
{
    struct mixer_ctl *ctl = NULL;
    char *mixer_name_prefix = "AudStr";
    char *mixer_name_suffix = "ChMixer Weight Ch";
    char mixer_ctl_name[128] = {0};
    struct audio_custom_mtmx_params_info *pinfo = &params->info;
    int i = 0, err = 0;

    ALOGI("%s: ip_channels %d, op_channels %d, pcm_device_id %d",
          __func__, pinfo->ip_channels, pinfo->op_channels, pcm_device_id);

    for (i = 0; i < (int)pinfo->op_channels; i++) {
         snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "%s %d %s %d",
                  mixer_name_prefix, pcm_device_id, mixer_name_suffix, i+1);
         ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
         if (!ctl) {
             ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
                   __func__, mixer_ctl_name);
             return -EINVAL;
         }

         err = mixer_ctl_set_array(ctl,
                                   &params->coeffs[pinfo->ip_channels * i],
                                   pinfo->ip_channels);
         if (err) {
             ALOGE("%s: ERROR. Mixer ctl set failed", __func__);
             return -EINVAL;
         }
    }
    return 0;
}

static void set_custom_mtmx_params(struct audio_device *adev,
                                   struct audio_custom_mtmx_params_info *pinfo,
                                   int pcm_device_id, bool enable)
{
    struct mixer_ctl *ctl = NULL;
    char *mixer_name_prefix = "AudStr";
    char *mixer_name_suffix = "ChMixer Cfg";
    char mixer_ctl_name[128] = {0};
    int chmixer_cfg[5] = {0}, len = 0;
    int be_id = -1, err = 0;

    be_id = platform_get_snd_device_backend_index(pinfo->snd_device);

    ALOGI("%s: ip_channels %d,op_channels %d,pcm_device_id %d,be_id %d",
          __func__, pinfo->ip_channels, pinfo->op_channels, pcm_device_id, be_id);

    snprintf(mixer_ctl_name, sizeof(mixer_ctl_name),
             "%s %d %s", mixer_name_prefix, pcm_device_id, mixer_name_suffix);
    ctl = mixer_get_ctl_by_name(adev->mixer, mixer_ctl_name);
    if (!ctl) {
        ALOGE("%s: ERROR. Could not get ctl for mixer cmd - %s",
              __func__, mixer_ctl_name);
        return;
    }
    chmixer_cfg[len++] = enable ? 1 : 0;
    chmixer_cfg[len++] = 0; /* rule index */
    chmixer_cfg[len++] = pinfo->ip_channels;
    chmixer_cfg[len++] = pinfo->op_channels;
    chmixer_cfg[len++] = be_id + 1;

    err = mixer_ctl_set_array(ctl, chmixer_cfg, len);
    if (err)
        ALOGE("%s: ERROR. Mixer ctl set failed", __func__);
}

void audio_extn_set_custom_mtmx_params(struct audio_device *adev,
                                        struct audio_usecase *usecase,
                                        bool enable)
{
    struct audio_custom_mtmx_params_info info = {0};
    struct audio_custom_mtmx_params *params = NULL;
    int num_devices = 0, pcm_device_id = -1, i = 0, ret = 0;
    snd_device_t new_snd_devices[SND_DEVICE_OUT_END] = {0};
    struct audio_backend_cfg backend_cfg = {0};
    uint32_t feature_id = 0;

    switch(usecase->type) {
    case PCM_PLAYBACK:
        if (usecase->stream.out) {
            pcm_device_id =
                platform_get_pcm_device_id(usecase->id, PCM_PLAYBACK);
            if (platform_split_snd_device(adev->platform,
                                          usecase->out_snd_device,
                                          &num_devices, new_snd_devices)) {
                new_snd_devices[0] = usecase->out_snd_device;
                num_devices = 1;
            }
        } else {
            ALOGE("%s: invalid output stream for playback usecase id:%d",
                  __func__, usecase->id);
            return;
        }
        break;
    case PCM_CAPTURE:
        if (usecase->stream.in) {
            pcm_device_id =
                platform_get_pcm_device_id(usecase->id, PCM_CAPTURE);
            if (platform_split_snd_device(adev->platform,
                                          usecase->in_snd_device,
                                          &num_devices, new_snd_devices)) {
                new_snd_devices[0] = usecase->in_snd_device;
                num_devices = 1;
            }
        } else {
            ALOGE("%s: invalid input stream for capture usecase id:%d",
                  __func__, usecase->id);
            return;
        }
        break;
    default:
        ALOGV("%s: unsupported usecase id:%d", __func__, usecase->id);
        return;
    }

    /*
     * check and update feature_id before this assignment,
     * if features like dual_mono is enabled and overrides the default(i.e. 0).
     */
    info.id = feature_id;
    info.usecase_id = usecase->id;
    for (i = 0, ret = 0; i < num_devices; i++) {
         info.snd_device = new_snd_devices[i];
         platform_get_codec_backend_cfg(adev, info.snd_device, &backend_cfg);
         if (usecase->type == PCM_PLAYBACK) {
             info.ip_channels = audio_channel_count_from_out_mask(
                                    usecase->stream.out->channel_mask);
             info.op_channels = backend_cfg.channels;
         } else {
             info.ip_channels = backend_cfg.channels;
             info.op_channels = audio_channel_count_from_in_mask(
                                    usecase->stream.in->channel_mask);
         }

         params = platform_get_custom_mtmx_params(adev->platform, &info);
         if (params) {
             if (enable)
                 ret = update_custom_mtmx_coefficients(adev, params,
                                                       pcm_device_id);
             if (ret < 0)
                 ALOGE("%s: error updating mtmx coeffs err:%d", __func__, ret);
             else
                 set_custom_mtmx_params(adev, &info, pcm_device_id, enable);
         }
    }
}

#ifndef DTS_EAGLE
#define audio_extn_hpx_set_parameters(adev, parms)         (0)
#define audio_extn_hpx_get_parameters(query, reply)  (0)
+3 −0
Original line number Diff line number Diff line
@@ -1205,4 +1205,7 @@ void audio_extn_send_dual_mono_mixing_coefficients(struct stream_out *out);
void audio_extn_set_cpu_affinity();
bool audio_extn_is_record_play_concurrency_enabled();
bool audio_extn_is_concurrent_capture_enabled();
void audio_extn_set_custom_mtmx_params(struct audio_device *adev,
                                        struct audio_usecase *usecase,
                                        bool enable);
#endif /* AUDIO_EXTN_H */
+2 −0
Original line number Diff line number Diff line
@@ -1069,6 +1069,7 @@ int enable_audio_route(struct audio_device *adev,
        if (out && out->compr)
            audio_extn_utils_compress_set_clk_rec_mode(usecase);
    }
    audio_extn_set_custom_mtmx_params(adev, usecase, true);

    strlcpy(mixer_path, use_case_table[usecase->id], MIXER_PATH_MAX_LENGTH);
    platform_add_backend_name(mixer_path, snd_device, usecase);
@@ -1105,6 +1106,7 @@ int disable_audio_route(struct audio_device *adev,
    audio_route_reset_and_update_path(adev->audio_route, mixer_path);
    audio_extn_sound_trigger_update_stream_status(usecase, ST_EVENT_STREAM_FREE);
    audio_extn_listen_update_stream_status(usecase, LISTEN_EVENT_STREAM_FREE);
    audio_extn_set_custom_mtmx_params(adev, usecase, false);
    ALOGV("%s: exit", __func__);
    return 0;
}
+72 −0
Original line number Diff line number Diff line
@@ -309,6 +309,7 @@ struct platform_data {
    struct snd_device_to_mic_map mic_map[SND_DEVICE_MAX];
    struct  spkr_device_chmap *spkr_ch_map;
    bool use_sprk_default_sample_rate;
    struct listnode custom_mtmx_params_list;
};

struct  spkr_device_chmap {
@@ -2399,6 +2400,7 @@ void *platform_init(struct audio_device *adev)
        my_data->hifi_audio = true;

    list_init(&my_data->acdb_meta_key_list);
    list_init(&my_data->custom_mtmx_params_list);

    set_platform_defaults(my_data);

@@ -2769,6 +2771,75 @@ acdb_init_fail:
    return my_data;
}

struct audio_custom_mtmx_params *
    platform_get_custom_mtmx_params(void *platform,
                                    struct audio_custom_mtmx_params_info *info)
{
    struct platform_data *my_data = (struct platform_data *)platform;
    struct listnode *node = NULL;
    struct audio_custom_mtmx_params *params = NULL;

    list_for_each(node, &my_data->custom_mtmx_params_list) {
        params = node_to_item(node, struct audio_custom_mtmx_params, list);
        if (params &&
            params->info.id == info->id &&
            params->info.ip_channels == info->ip_channels &&
            params->info.op_channels == info->op_channels &&
            params->info.usecase_id == info->usecase_id &&
            params->info.snd_device == info->snd_device) {
            ALOGV("%s: found params with ip_ch %d op_ch %d uc_id %d snd_dev %d",
                  __func__, info->ip_channels, info->op_channels,
                  info->usecase_id, info->snd_device);
            return params;
        }
    }
    ALOGI("%s: no matching param with id %d ip_ch %d op_ch %d uc_id %d snd_dev %d",
          __func__, info->id, info->ip_channels, info->op_channels,
          info->usecase_id, info->snd_device);
    return NULL;
}

int platform_add_custom_mtmx_params(void *platform,
                                    struct audio_custom_mtmx_params_info *info)
{
    struct platform_data *my_data = (struct platform_data *)platform;
    struct audio_custom_mtmx_params *params = NULL;
    uint32_t size = sizeof(*params);

    if (info->ip_channels > AUDIO_CHANNEL_COUNT_MAX ||
        info->op_channels > AUDIO_CHANNEL_COUNT_MAX) {
        ALOGE("%s: unusupported channels in %d, out %d",
              __func__, info->ip_channels, info->op_channels);
        return -EINVAL;
    }

    size += sizeof(params->coeffs[0]) * info->ip_channels * info->op_channels;
    params = (struct audio_custom_mtmx_params *) calloc(1, size);
    if (!params) {
        ALOGE("%s: failed to add custom mtmx params", __func__);
        return -ENOMEM;
    }

    ALOGI("%s: adding mtmx params with id %d ip_ch %d op_ch %d uc_id %d snd_dev %d",
          __func__, info->id, info->ip_channels, info->op_channels,
          info->usecase_id, info->snd_device);

    params->info = *info;
    list_add_tail(&my_data->custom_mtmx_params_list, &params->list);
    return 0;
}

static void platform_release_custom_mtmx_params(void *platform)
{
    struct platform_data *my_data = (struct platform_data *)platform;
    struct listnode *node = NULL, *tempnode = NULL;

    list_for_each_safe(node, tempnode, &my_data->custom_mtmx_params_list) {
        list_remove(node);
        free(node_to_item(node, struct audio_custom_mtmx_params, list));
    }
}

void platform_release_acdb_metainfo_key(void *platform)
{
    struct platform_data *my_data = (struct platform_data *)platform;
@@ -2854,6 +2925,7 @@ void platform_deinit(void *platform)

    /* free acdb_meta_key_list */
    platform_release_acdb_metainfo_key(platform);
    platform_release_custom_mtmx_params(platform);

    if (my_data->acdb_deallocate)
        my_data->acdb_deallocate();
+22 −1
Original line number Diff line number Diff line
/*
 * Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
 * Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
 * Not a contribution.
 *
 * Copyright (C) 2013 The Android Open Source Project
@@ -353,6 +353,27 @@ void *platform_init(struct audio_device *adev)
    return my_data;
}

struct audio_custom_mtmx_params *
    platform_get_custom_mtmx_params
    (
        void *platform __unused,
        struct audio_custom_mtmx_params_info *info __unused
    )
{
    ALOGW("%s: not implemented!", __func__);
    return NULL;
}

int platform_add_custom_mtmx_params
    (
        void *platform __unused,
        struct audio_custom_mtmx_params_info *info __unused
    )
{
    ALOGW("%s: not implemented!", __func__);
    return -ENOSYS;
}

void platform_deinit(void *platform)
{
    struct platform_data *my_data = (struct platform_data *)platform;
Loading