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

Commit c9f9971a authored by Chaithanya Krishna Bacharaju's avatar Chaithanya Krishna Bacharaju
Browse files

hal: Add support to capture mic and ec reference data

Add support to capture mic and ec reference data in single stream.
Add changes to update custom matrix params to configure PSPD.

Change-Id: I29f38c0d778d44217a9e0d59e4b1324f4ee81fdd
parent 479bb9c2
Loading
Loading
Loading
Loading
+398 −12
Original line number Diff line number Diff line
@@ -366,7 +366,7 @@ static void audio_extn_ext_disp_set_parameters(const struct audio_device *adev,
    }
}

static int update_custom_mtmx_coefficients(struct audio_device *adev,
static int update_custom_mtmx_coefficients_v2(struct audio_device *adev,
                                              struct audio_custom_mtmx_params *params,
                                              int pcm_device_id)
{
@@ -430,7 +430,7 @@ static int update_custom_mtmx_coefficients(struct audio_device *adev,
    return 0;
}

static void set_custom_mtmx_params(struct audio_device *adev,
static void set_custom_mtmx_params_v2(struct audio_device *adev,
                                      struct audio_custom_mtmx_params_info *pinfo,
                                      int pcm_device_id, bool enable)
{
@@ -465,7 +465,7 @@ static void set_custom_mtmx_params(struct audio_device *adev,
        ALOGE("%s: ERROR. Mixer ctl set failed", __func__);
}

void audio_extn_set_custom_mtmx_params(struct audio_device *adev,
void audio_extn_set_custom_mtmx_params_v2(struct audio_device *adev,
                                        struct audio_usecase *usecase,
                                        bool enable)
{
@@ -535,16 +535,402 @@ void audio_extn_set_custom_mtmx_params(struct audio_device *adev,
        params = platform_get_custom_mtmx_params(adev->platform, &info);
        if (params) {
            if (enable)
                ret = update_custom_mtmx_coefficients(adev, params,
                ret = update_custom_mtmx_coefficients_v2(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);
                set_custom_mtmx_params_v2(adev, &info, pcm_device_id, enable);
        }
    }
}

static int set_custom_mtmx_output_channel_map(struct audio_device *adev,
                                              char *mixer_name_prefix,
                                              uint32_t ch_count,
                                              bool enable)
{
    struct mixer_ctl *ctl = NULL;
    char mixer_ctl_name[128] = {0};
    int ret = 0;
    int channel_map[AUDIO_MAX_DSP_CHANNELS] = {0};

    ALOGV("%s channel_count %d", __func__, ch_count);

    if (!enable) {
        ALOGV("%s: reset output channel map", __func__);
        goto exit;
    }

    switch (ch_count) {
    case 2:
        channel_map[0] = PCM_CHANNEL_FL;
        channel_map[1] = PCM_CHANNEL_FR;
        break;
    case 4:
        channel_map[0] = PCM_CHANNEL_FL;
        channel_map[1] = PCM_CHANNEL_FR;
        channel_map[2] = PCM_CHANNEL_LS;
        channel_map[3] = PCM_CHANNEL_RS;
        break;
    case 6:
        channel_map[0] = PCM_CHANNEL_FL;
        channel_map[1] = PCM_CHANNEL_FR;
        channel_map[2] = PCM_CHANNEL_FC;
        channel_map[3] = PCM_CHANNEL_LFE;
        channel_map[4] = PCM_CHANNEL_LS;
        channel_map[5] = PCM_CHANNEL_RS;
        break;
    case 8:
        channel_map[0] = PCM_CHANNEL_FL;
        channel_map[1] = PCM_CHANNEL_FR;
        channel_map[2] = PCM_CHANNEL_FC;
        channel_map[3] = PCM_CHANNEL_LFE;
        channel_map[4] = PCM_CHANNEL_LB;
        channel_map[5] = PCM_CHANNEL_RB;
        channel_map[6] = PCM_CHANNEL_LS;
        channel_map[7] = PCM_CHANNEL_RS;
        break;
    case 10:
        channel_map[0] = PCM_CHANNEL_FL;
        channel_map[1] = PCM_CHANNEL_FR;
        channel_map[2] = PCM_CHANNEL_LFE;
        channel_map[3] = PCM_CHANNEL_FC;
        channel_map[4] = PCM_CHANNEL_LB;
        channel_map[5] = PCM_CHANNEL_RB;
        channel_map[6] = PCM_CHANNEL_LS;
        channel_map[7] = PCM_CHANNEL_RS;
        channel_map[8] = PCM_CHANNEL_TFL;
        channel_map[9] = PCM_CHANNEL_TFR;
        break;
    case 12:
        channel_map[0] = PCM_CHANNEL_FL;
        channel_map[1] = PCM_CHANNEL_FR;
        channel_map[2] = PCM_CHANNEL_FC;
        channel_map[3] = PCM_CHANNEL_LFE;
        channel_map[4] = PCM_CHANNEL_LB;
        channel_map[5] = PCM_CHANNEL_RB;
        channel_map[6] = PCM_CHANNEL_LS;
        channel_map[7] = PCM_CHANNEL_RS;
        channel_map[8] = PCM_CHANNEL_TFL;
        channel_map[9] = PCM_CHANNEL_TFR;
        channel_map[10] = PCM_CHANNEL_TSL;
        channel_map[11] = PCM_CHANNEL_TSR;
        break;
    case 14:
        channel_map[0] = PCM_CHANNEL_FL;
        channel_map[1] = PCM_CHANNEL_FR;
        channel_map[2] = PCM_CHANNEL_LFE;
        channel_map[3] = PCM_CHANNEL_FC;
        channel_map[4] = PCM_CHANNEL_LB;
        channel_map[5] = PCM_CHANNEL_RB;
        channel_map[6] = PCM_CHANNEL_LS;
        channel_map[7] = PCM_CHANNEL_RS;
        channel_map[8] = PCM_CHANNEL_TFL;
        channel_map[9] = PCM_CHANNEL_TFR;
        channel_map[10] = PCM_CHANNEL_TSL;
        channel_map[11] = PCM_CHANNEL_TSR;
        channel_map[12] = PCM_CHANNEL_FLC;
        channel_map[13] = PCM_CHANNEL_FRC;
        break;
    case 16:
        channel_map[0] = PCM_CHANNEL_FL;
        channel_map[1] = PCM_CHANNEL_FR;
        channel_map[2] = PCM_CHANNEL_FC;
        channel_map[3] = PCM_CHANNEL_LFE;
        channel_map[4] = PCM_CHANNEL_LB;
        channel_map[5] = PCM_CHANNEL_RB;
        channel_map[6] = PCM_CHANNEL_LS;
        channel_map[7] = PCM_CHANNEL_RS;
        channel_map[8] = PCM_CHANNEL_TFL;
        channel_map[9] = PCM_CHANNEL_TFR;
        channel_map[10] = PCM_CHANNEL_TSL;
        channel_map[11] = PCM_CHANNEL_TSR;
        channel_map[12] = PCM_CHANNEL_FLC;
        channel_map[13] = PCM_CHANNEL_FRC;
        channel_map[14] = PCM_CHANNEL_RLC;
        channel_map[15] = PCM_CHANNEL_RRC;
        break;
    default:
        ALOGE("%s: unsupported channels(%d) for setting channel map",
               __func__, ch_count);
        return -EINVAL;
    }

exit:
    snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "%s %s",
             mixer_name_prefix, "Output Channel Map");

    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;
    }

    ret = mixer_ctl_set_array(ctl, channel_map, ch_count);
    return ret;
}

static int update_custom_mtmx_coefficients_v1(struct audio_device *adev,
                                           struct audio_custom_mtmx_params *params,
                                           struct audio_custom_mtmx_in_params *in_params,
                                           int pcm_device_id,
                                           usecase_type_t type,
                                           bool enable)
{
    struct mixer_ctl *ctl = NULL;
    char mixer_ctl_name[128] = {0};
    struct audio_custom_mtmx_params_info *pinfo = &params->info;
    char mixer_name_prefix[100];
    int i = 0, err = 0, rule = 0;
    uint32_t mtrx_row_cnt = 0, mtrx_column_cnt = 0;
    int reset_coeffs[AUDIO_MAX_DSP_CHANNELS] = {0};

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

    if (!strcmp(pinfo->fe_name, "")) {
        ALOGE("%s: Error. no front end defined", __func__);
        return -EINVAL;
    }

    strlcpy(mixer_name_prefix, pinfo->fe_name, sizeof(mixer_name_prefix));

    /*
     * Enable/Disable channel mixer.
     * If enable, use params and in_params to configure mixer.
     * If disable, reset previously configured mixer.
    */
    snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "%s %s",
             mixer_name_prefix, "Channel Mixer");

    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;
    }

    if (enable)
        err = mixer_ctl_set_enum_by_string(ctl, "Enable");
    else
        err = mixer_ctl_set_enum_by_string(ctl, "Disable");

    if (err) {
        ALOGE("%s: ERROR. %s channel mixer failed", __func__,
              enable ? "Enable" : "Disable");
        return -EINVAL;
    }

    /* Configure output channels of channel mixer */
    snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "%s %s",
             mixer_name_prefix, "Channels");

    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;
    }

    mtrx_row_cnt = pinfo->op_channels;
    mtrx_column_cnt = pinfo->ip_channels;

    if (enable)
        err = mixer_ctl_set_value(ctl, 0, mtrx_row_cnt);
    else
        err = mixer_ctl_set_value(ctl, 0, 0);

    if (err) {
        ALOGE("%s: ERROR. %s mixer output channels failed", __func__,
              enable ? "Set" : "Reset");
        return -EINVAL;
    }


    /* To keep output channel map in sync with asm driver channel mapping */
    err = set_custom_mtmx_output_channel_map(adev, mixer_name_prefix, mtrx_row_cnt,
                                       enable);
    if (err) {
        ALOGE("%s: ERROR. %s mtmx output channel map failed", __func__,
              enable ? "Set" : "Reset");
        return -EINVAL;
    }

    /* Send channel mixer rule */
    snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "%s %s",
             mixer_name_prefix, "Channel Rule");

    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;
    }

    mixer_ctl_set_value(ctl, 0, rule);

    /* Send channel coefficients for each output channel */
    for (i = 0; i < mtrx_row_cnt; i++) {
        snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "%s %s%d",
                 mixer_name_prefix, "Output Channel", 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;
        }

        if (enable)
            err = mixer_ctl_set_array(ctl,
                                  &params->coeffs[mtrx_column_cnt * i],
                                  mtrx_column_cnt);
        else
            err = mixer_ctl_set_array(ctl,
                                  reset_coeffs,
                                  mtrx_column_cnt);
        if (err) {
            ALOGE("%s: ERROR. %s coefficients failed for output channel %d",
                   __func__, enable ? "Set" : "Reset", i);
            return -EINVAL;
        }
    }

    /* Configure backend interfaces with information provided in xml */
    i = 0;
    while (in_params->in_ch_info[i].ch_count != 0) {
        snprintf(mixer_ctl_name, sizeof(mixer_ctl_name), "%s %s%d",
                 mixer_name_prefix, "Channel", 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;
        }
        if (enable) {
            ALOGD("%s: mixer %s, interface %s", __func__, mixer_ctl_name,
                   in_params->in_ch_info[i].hw_interface);
            err = mixer_ctl_set_enum_by_string(ctl,
                      in_params->in_ch_info[i].hw_interface);
        } else {
            err = mixer_ctl_set_enum_by_string(ctl, "ZERO");
        }

        if (err) {
            ALOGE("%s: ERROR. %s channel backend interface failed", __func__,
                   enable ? "Set" : "Reset");
            return -EINVAL;
        }
        i++;
    }

    return 0;
}


void audio_extn_set_custom_mtmx_params_v1(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;
    struct audio_custom_mtmx_in_params_info in_info = {0};
    struct audio_custom_mtmx_in_params *in_params = NULL;
    int pcm_device_id = -1, ret = 0;
    uint32_t feature_id = 0;

    switch(usecase->type) {
    case PCM_CAPTURE:
        if (usecase->stream.in) {
            pcm_device_id =
                platform_get_pcm_device_id(usecase->id, PCM_CAPTURE);
            info.snd_device = usecase->in_snd_device;
        } else {
            ALOGE("%s: invalid input stream for capture usecase id:%d",
                  __func__, usecase->id);
            return;
        }
        break;
    case PCM_PLAYBACK:
    default:
        ALOGV("%s: unsupported usecase id:%d", __func__, usecase->id);
        return;
    }

    ALOGD("%s: snd device %d", __func__, info.snd_device);
    info.id = feature_id;
    info.usecase_id = usecase->id;
    info.op_channels = audio_channel_count_from_in_mask(
                                usecase->stream.in->channel_mask);

    in_info.usecase_id = info.usecase_id;
    in_info.op_channels = info.op_channels;
    in_params = platform_get_custom_mtmx_in_params(adev->platform, &in_info);
    if (!in_params) {
        ALOGE("%s: Could not get in params for usecase %d, channels %d",
               __func__, in_info.usecase_id, in_info.op_channels);
        return;
    }

    info.ip_channels = in_params->ip_channels;
    ALOGD("%s: ip channels %d, op channels %d", __func__, info.ip_channels, info.op_channels);

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

snd_device_t audio_extn_get_loopback_snd_device(struct audio_device *adev,
                                                struct audio_usecase *usecase,
                                                int channel_count)
{
    snd_device_t snd_device = SND_DEVICE_NONE;
    struct audio_custom_mtmx_in_params_info in_info = {0};
    struct audio_custom_mtmx_in_params *in_params = NULL;

    if (!adev || !usecase) {
        ALOGE("%s: Invalid params", __func__);
        return snd_device;
    }

    in_info.usecase_id = usecase->id;
    in_info.op_channels = channel_count;
    in_params = platform_get_custom_mtmx_in_params(adev->platform, &in_info);
    if (!in_params) {
        ALOGE("%s: Could not get in params for usecase %d, channels %d",
               __func__, in_info.usecase_id, in_info.op_channels);
        return snd_device;
    }

    switch(in_params->mic_ch) {
    case 2:
        snd_device = SND_DEVICE_IN_HANDSET_DMIC_AND_EC_REF_LOOPBACK;
        break;
    case 4:
        snd_device = SND_DEVICE_IN_HANDSET_QMIC_AND_EC_REF_LOOPBACK;
        break;
    case 6:
        snd_device = SND_DEVICE_IN_HANDSET_6MIC_AND_EC_REF_LOOPBACK;
        break;
    case 8:
        snd_device = SND_DEVICE_IN_HANDSET_8MIC_AND_EC_REF_LOOPBACK;
        break;
    default:
        ALOGE("%s: Unsupported mic channels %d",
               __func__, in_params->mic_ch);
        break;
    }

    ALOGD("%s: return snd device %d", __func__, snd_device);
    return snd_device;
}

#ifndef DTS_EAGLE
#define audio_extn_hpx_set_parameters(adev, parms)         (0)
#define audio_extn_hpx_get_parameters(query, reply)  (0)
@@ -2893,10 +3279,10 @@ static int audio_extn_set_multichannel_mask(struct audio_device *adev,
    *channel_mask_updated = false;

    int max_mic_count = platform_get_max_mic_count(adev->platform);
    /* validate input params*/
    /* validate input params. Avoid updated channel mask if loopback device */
    if ((channel_count == 6) &&
        (in->format == AUDIO_FORMAT_PCM_16_BIT)) {

        (in->format == AUDIO_FORMAT_PCM_16_BIT) &&
        (!is_loopback_input_device(in->device))) {
        switch (max_mic_count) {
            case 4:
                config->channel_mask = AUDIO_CHANNEL_INDEX_MASK_4;
+7 −1
Original line number Diff line number Diff line
@@ -1266,7 +1266,13 @@ 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,
void audio_extn_set_custom_mtmx_params_v2(struct audio_device *adev,
                                        struct audio_usecase *usecase,
                                        bool enable);
void audio_extn_set_custom_mtmx_params_v1(struct audio_device *adev,
                                        struct audio_usecase *usecase,
                                        bool enable);
snd_device_t audio_extn_get_loopback_snd_device(struct audio_device *adev,
                                                struct audio_usecase *usecase,
                                                int channel_count);
#endif /* AUDIO_EXTN_H */
+34 −3
Original line number Diff line number Diff line
@@ -1081,6 +1081,7 @@ int enable_audio_route(struct audio_device *adev,
    snd_device_t snd_device;
    char mixer_path[MIXER_PATH_MAX_LENGTH];
    struct stream_out *out = NULL;
    struct stream_in *in = NULL;
    int ret = 0;

    if (usecase == NULL)
@@ -1139,7 +1140,16 @@ 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);

    if (usecase->type == PCM_CAPTURE) {
        in = usecase->stream.in;
        if (in && is_loopback_input_device(in->device)) {
            ALOGD("%s: set custom mtmx params v1", __func__);
            audio_extn_set_custom_mtmx_params_v1(adev, usecase, true);
        }
    } else {
        audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
    }

    // we shouldn't truncate mixer_path
    ALOGW_IF(strlcpy(mixer_path, use_case_table[usecase->id], sizeof(mixer_path))
@@ -1164,6 +1174,7 @@ int disable_audio_route(struct audio_device *adev,
{
    snd_device_t snd_device;
    char mixer_path[MIXER_PATH_MAX_LENGTH];
    struct stream_in *in = NULL;

    if (usecase == NULL || usecase->id == USECASE_INVALID)
        return -EINVAL;
@@ -1189,10 +1200,21 @@ int disable_audio_route(struct audio_device *adev,
    }
    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);

    if (usecase->type == PCM_CAPTURE) {
        in = usecase->stream.in;
        if (in && is_loopback_input_device(in->device)) {
            ALOGD("%s: reset custom mtmx params v1", __func__);
            audio_extn_set_custom_mtmx_params_v1(adev, usecase, false);
        }
    } else {
        audio_extn_set_custom_mtmx_params_v2(adev, usecase, false);
    }

    if ((usecase->type == PCM_PLAYBACK) &&
            (usecase->stream.out != NULL))
        usecase->stream.out->pspd_coeff_sent = false;

    ALOGV("%s: exit", __func__);
    return 0;
}
@@ -2790,6 +2812,9 @@ static int stop_input_stream(struct stream_in *in)
    /* 2. Disable the tx device */
    disable_snd_device(adev, uc_info->in_snd_device);

    if (is_loopback_input_device(in->device))
        audio_extn_keep_alive_stop(KEEP_ALIVE_OUT_PRIMARY);

    list_remove(&uc_info->list);
    free(uc_info);

@@ -2977,6 +3002,9 @@ int start_input_stream(struct stream_in *in)
    audio_extn_audiozoom_set_microphone_direction(in, in->zoom);
    audio_extn_audiozoom_set_microphone_field_dimension(in, in->direction);

    if (is_loopback_input_device(in->device))
        audio_extn_keep_alive_start(KEEP_ALIVE_OUT_PRIMARY);

done_open:
    audio_streaming_hint_end();
    audio_extn_perf_lock_release(&adev->perf_lock_handle);
@@ -3834,6 +3862,9 @@ static int check_input_parameters(uint32_t sample_rate,
    case 4:
    case 6:
    case 8:
    case 10:
    case 12:
    case 14:
        break;
    default:
        ret = -EINVAL;
@@ -5397,7 +5428,7 @@ static ssize_t out_write(struct audio_stream_out *stream, const void *buffer,
         */
        usecase = get_usecase_from_list(adev, out->usecase);
        if (usecase != NULL) {
            audio_extn_set_custom_mtmx_params(adev, usecase, true);
            audio_extn_set_custom_mtmx_params_v2(adev, usecase, true);
            out->pspd_coeff_sent = true;
        }
    }
+8 −0
Original line number Diff line number Diff line
@@ -729,6 +729,14 @@ size_t get_output_period_size(uint32_t sample_rate,
            __FILE__ ":" LITERAL_TO_STRING(__LINE__)\
            " ASSERT_FATAL(" #condition ") failed.")

static inline bool is_loopback_input_device(audio_devices_t device) {
    if (!audio_is_output_device(device) &&
         ((device & AUDIO_DEVICE_IN_LOOPBACK) == AUDIO_DEVICE_IN_LOOPBACK))
        return true;
    else
        return false;
}

/*
 * NOTE: when multiple mutexes have to be acquired, always take the
 * stream_in or stream_out mutex first, followed by the audio_device mutex.
+14 −0
Original line number Diff line number Diff line
@@ -2845,6 +2845,20 @@ static void platform_release_custom_mtmx_params(void *platform)
    }
}

struct audio_custom_mtmx_in_params *platform_get_custom_mtmx_in_params(void *platform,
                                   struct audio_custom_mtmx_in_params_info *info)
{
    ALOGW("%s: not implemented!", __func__);
    return -ENOSYS;
}

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

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