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

Commit bb3ed764 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "hal: Add support to capture mic and ec reference data"

parents eca77a2f c9f9971a
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
@@ -1269,7 +1269,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