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

Commit 95333359 authored by Apoorv Raghuvanshi's avatar Apoorv Raghuvanshi Committed by Gerrit - the friendly Code Review server
Browse files

hal: Add codec EC reference support

- We need to set codec EC reference instead of MSM/AFE
  EC ref for Native audio usecase along with other
  usecases running on 48K port. In this scenario we
  will run two AFE ports, one regular port and the
  other port running at 44.1KHz and mixing done in codec.
  So set appropriate codec EC reference.

- One example of such usecase is VoIP over audio path
  and a 44.1KHz stream playback. But this change is generic
  enough to accommodate other possible usecases if any.

CRs-Fixed: 877363
Change-Id: Ib980e36d111c1671303abe2b19341568d9fd2331
parent 6f90f6e5
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
/* hfp.c
Copyright (c) 2012-2014, The Linux Foundation. All rights reserved.
Copyright (c) 2012-2015, The Linux Foundation. All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
@@ -271,7 +271,7 @@ static int32_t stop_hfp(struct audio_device *adev)
    }

    /* 2. Disable echo reference while stopping hfp */
    platform_set_echo_reference(adev->platform, false);
    platform_set_echo_reference(adev, false, uc_info->devices);

    /* 3. Get and set stream specific mixer controls */
    disable_audio_route(adev, uc_info);
+2 −2
Original line number Diff line number Diff line
@@ -900,7 +900,7 @@ int select_devices(struct audio_device *adev, audio_usecase_t uc_id)
                     adev->active_input->source == AUDIO_SOURCE_MIC)) &&
                     adev->primary_output && !adev->primary_output->standby) {
                    out_device = adev->primary_output->devices;
                    platform_set_echo_reference(adev->platform, false);
                    platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);
                } else if (usecase->id == USECASE_AUDIO_RECORD_AFE_PROXY) {
                    out_device = AUDIO_DEVICE_OUT_TELEPHONY_TX;
                }
@@ -3552,7 +3552,7 @@ static void adev_close_input_stream(struct audio_hw_device *dev,
    ALOGD("%s: enter:stream_handle(%p)",__func__, in);

    /* Disable echo reference while closing input stream */
    platform_set_echo_reference(adev->platform, false);
    platform_set_echo_reference(adev, false, AUDIO_DEVICE_NONE);

    if (in->usecase == USECASE_COMPRESS_VOIP_CALL) {
        pthread_mutex_lock(&adev->lock);
+49 −31
Original line number Diff line number Diff line
@@ -247,6 +247,7 @@ struct platform_data {
    void *edid_info;
    bool edid_valid;
    codec_backend_cfg_t current_backend_cfg[MAX_CODEC_BACKENDS];
    char ec_ref_mixer_path[64];
};

static bool is_external_codec = false;
@@ -968,6 +969,41 @@ static void query_platform(const char *snd_card_name,
    }
}

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;
    snd_device_t snd_device = SND_DEVICE_NONE;
    struct stream_out out;

    out.devices = out_device;

    if (strcmp(my_data->ec_ref_mixer_path, "")) {
        ALOGV("%s: disabling %s", __func__, my_data->ec_ref_mixer_path);
        audio_route_reset_and_update_path(adev->audio_route,
            my_data->ec_ref_mixer_path);
    }

    if (enable) {
        snd_device = platform_get_output_snd_device(adev->platform, &out);

        if (adev->snd_dev_ref_cnt[SND_DEVICE_OUT_HEADPHONES_44_1] > 0)
            strlcpy(my_data->ec_ref_mixer_path, "echo-reference headphones-44.1",
                sizeof(my_data->ec_ref_mixer_path));
        else if ((snd_device == SND_DEVICE_OUT_SPEAKER_VBAT) ||
                 (snd_device == SND_DEVICE_OUT_SPEAKER_PROTECTED_VBAT))
            strlcpy(my_data->ec_ref_mixer_path, "vbat-speaker echo-reference",
                sizeof(my_data->ec_ref_mixer_path));
        else
            strlcpy(my_data->ec_ref_mixer_path, "echo-reference",
                sizeof(my_data->ec_ref_mixer_path));


        ALOGD("%s: enabling %s", __func__, my_data->ec_ref_mixer_path);
        audio_route_apply_and_update_path(adev->audio_route,
            my_data->ec_ref_mixer_path);
    }
}
void platform_set_gsm_mode(void *platform, bool enable)
{
    struct platform_data *my_data = (struct platform_data *)platform;
@@ -986,27 +1022,7 @@ void platform_set_gsm_mode(void *platform, bool enable)
    }
}

void platform_set_echo_reference(void *platform, bool enable)
{
    struct platform_data *my_data = (struct platform_data *)platform;
    struct audio_device *adev = my_data->adev;
    char *mixer_path_name = "echo-reference";

    if(my_data->is_vbat_speaker)
       mixer_path_name = "vbat-speaker echo-reference";

    if (my_data->ec_ref_enabled) {
        my_data->ec_ref_enabled = false;
        ALOGV("%s: disabling echo-reference", __func__);
        audio_route_reset_and_update_path(adev->audio_route, mixer_path_name);
    }

    if (enable) {
         my_data->ec_ref_enabled = true;
         ALOGD("%s: enabling echo-reference", __func__);
         audio_route_apply_and_update_path(adev->audio_route, mixer_path_name);
    }
}

static struct csd_data *open_csd_client()
{
@@ -2679,7 +2695,7 @@ snd_device_t platform_get_input_snd_device(void *platform, audio_devices_t out_d
                my_data->fluence_in_voice_call == false) {
                snd_device = SND_DEVICE_IN_HANDSET_MIC;
                if (audio_extn_hfp_is_active(adev))
                    platform_set_echo_reference(adev->platform, true);
                    platform_set_echo_reference(adev, true, out_device);
            } else {
                snd_device = SND_DEVICE_IN_VOICE_DMIC;
                adev->acdb_settings |= DMIC_FLAG;
@@ -2687,7 +2703,7 @@ snd_device_t platform_get_input_snd_device(void *platform, audio_devices_t out_d
        } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
            snd_device = SND_DEVICE_IN_VOICE_HEADSET_MIC;
            if (audio_extn_hfp_is_active(adev))
                platform_set_echo_reference(adev->platform, true);
                platform_set_echo_reference(adev, true, out_device);
        } else if (out_device & AUDIO_DEVICE_OUT_ALL_SCO) {
            if (adev->bt_wb_speech_enabled) {
                if (adev->bluetooth_nrec)
@@ -2717,7 +2733,7 @@ snd_device_t platform_get_input_snd_device(void *platform, audio_devices_t out_d
            } else {
                snd_device = SND_DEVICE_IN_VOICE_SPEAKER_MIC;
                if (audio_extn_hfp_is_active(adev))
                    platform_set_echo_reference(adev->platform, true);
                    platform_set_echo_reference(adev, true, out_device);
            }
        } else if (out_device & AUDIO_DEVICE_OUT_TELEPHONY_TX)
            snd_device = SND_DEVICE_IN_VOICE_RX;
@@ -2775,7 +2791,7 @@ snd_device_t platform_get_input_snd_device(void *platform, audio_devices_t out_d
                } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
                    snd_device = SND_DEVICE_IN_HEADSET_MIC_FLUENCE;
                }
                platform_set_echo_reference(adev->platform, true);
                platform_set_echo_reference(adev, true, out_device);
            } else if (my_data->fluence_type != FLUENCE_NONE &&
                       adev->active_input->enable_aec) {
                if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
@@ -2800,7 +2816,7 @@ snd_device_t platform_get_input_snd_device(void *platform, audio_devices_t out_d
                } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
                    snd_device = SND_DEVICE_IN_HEADSET_MIC_FLUENCE;
                }
                platform_set_echo_reference(adev->platform, true);
                platform_set_echo_reference(adev, true, out_device);
            } else if (my_data->fluence_type != FLUENCE_NONE &&
                       adev->active_input->enable_ns) {
                if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
@@ -2825,9 +2841,9 @@ snd_device_t platform_get_input_snd_device(void *platform, audio_devices_t out_d
                } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
                    snd_device = SND_DEVICE_IN_HEADSET_MIC_FLUENCE;
                }
                platform_set_echo_reference(adev->platform,false);
                platform_set_echo_reference(adev, false, out_device);
            } else
                platform_set_echo_reference(adev->platform, false);
                platform_set_echo_reference(adev, false, out_device);
        }
    } else if (source == AUDIO_SOURCE_MIC) {
        if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC &&
@@ -2835,10 +2851,10 @@ snd_device_t platform_get_input_snd_device(void *platform, audio_devices_t out_d
            if(my_data->fluence_in_audio_rec) {
                if(my_data->fluence_type & FLUENCE_QUAD_MIC) {
                    snd_device = SND_DEVICE_IN_HANDSET_QMIC;
                    platform_set_echo_reference(adev->platform, true);
                    platform_set_echo_reference(adev, true, out_device);
                } else if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
                    snd_device = SND_DEVICE_IN_HANDSET_DMIC;
                    platform_set_echo_reference(adev->platform, true);
                    platform_set_echo_reference(adev, true, out_device);
                }
            }
        }
@@ -3925,9 +3941,11 @@ bool platform_check_codec_backend_cfg(struct audio_device* adev,
    ALOGI("%s Codec selected backend: %d current bit width: %d and sample rate: %d",
               __func__, backend_idx, bit_width, sample_rate);

    // For voice calls use default configuration
    // For voice calls use default configuration i.e. 16b/48K, only applicable to
    // default backend
    // force routing is not required here, caller will do it anyway
    if (voice_is_in_call(adev) || adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
    if ((voice_is_in_call(adev) || adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
        backend_idx == DEFAULT_CODEC_BACKEND) {
        ALOGW("%s:Use default bw and sr for voice/voip calls ",__func__);
        bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
        sample_rate =  CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+42 −22
Original line number Diff line number Diff line
@@ -214,6 +214,7 @@ struct platform_data {
    struct csd_data *csd;
    void *edid_info;
    bool edid_valid;
    char ec_ref_mixer_path[64];
    codec_backend_cfg_t current_backend_cfg[MAX_CODEC_BACKENDS];
};

@@ -698,23 +699,39 @@ static int msm_be_id_array_len =
#define DEEP_BUFFER_PLATFORM_DELAY (29*1000LL)
#define LOW_LATENCY_PLATFORM_DELAY (13*1000LL)

void platform_set_echo_reference(void *platform, bool enable)
void platform_set_echo_reference(struct audio_device *adev, bool enable,
    audio_devices_t out_device)
{
    struct platform_data *my_data = (struct platform_data *)platform;
    struct audio_device *adev = my_data->adev;
    struct platform_data *my_data = (struct platform_data *)adev->platform;
    snd_device_t snd_device = SND_DEVICE_NONE;
    struct stream_out out;

    out.devices = out_device;

    if (my_data->ec_ref_enabled) {
        my_data->ec_ref_enabled = false;
        ALOGV("%s: disabling echo-reference", __func__);
        audio_route_reset_and_update_path(adev->audio_route, "echo-reference");
    if (strcmp(my_data->ec_ref_mixer_path, "")) {
        ALOGV("%s: disabling %s", __func__, my_data->ec_ref_mixer_path);
        audio_route_reset_and_update_path(adev->audio_route,
            my_data->ec_ref_mixer_path);
    }

    if (enable) {
         my_data->ec_ref_enabled = true;
         ALOGD("%s: enabling echo-reference", __func__);
         audio_route_apply_and_update_path(adev->audio_route, "echo-reference");
    }
        strlcpy(my_data->ec_ref_mixer_path, "echo-reference",
            sizeof(my_data->ec_ref_mixer_path));
        snd_device = platform_get_output_snd_device(adev->platform, &out);
        /*
         * If native audio device reference count > 0, then apply codec EC otherwise
         * fallback to headphones if so or default
         */
        if (adev->snd_dev_ref_cnt[SND_DEVICE_OUT_HEADPHONES_44_1] > 0)
            platform_add_backend_name(my_data->ec_ref_mixer_path,
                SND_DEVICE_OUT_HEADPHONES_44_1);
        else
            platform_add_backend_name(my_data->ec_ref_mixer_path, snd_device);

        ALOGD("%s: enabling %s", __func__, my_data->ec_ref_mixer_path);
        audio_route_apply_and_update_path(adev->audio_route,
            my_data->ec_ref_mixer_path);
    }
}

static struct csd_data *open_csd_client(bool i2s_ext_modem)
@@ -2258,14 +2275,14 @@ snd_device_t platform_get_input_snd_device(void *platform, audio_devices_t out_d
                my_data->fluence_in_voice_call == false) {
                snd_device = SND_DEVICE_IN_HANDSET_MIC;
                if (audio_extn_hfp_is_active(adev))
                    platform_set_echo_reference(adev->platform, true);
                    platform_set_echo_reference(adev, true, out_device);
            } else {
                snd_device = SND_DEVICE_IN_VOICE_DMIC;
            }
        } else if (out_device & AUDIO_DEVICE_OUT_WIRED_HEADSET) {
            snd_device = SND_DEVICE_IN_VOICE_HEADSET_MIC;
            if (audio_extn_hfp_is_active(adev))
                platform_set_echo_reference(adev->platform, true);
                platform_set_echo_reference(adev, true, out_device);
        } else if (out_device & AUDIO_DEVICE_OUT_ALL_SCO) {
            if (adev->bt_wb_speech_enabled) {
                if (adev->bluetooth_nrec)
@@ -2293,7 +2310,7 @@ snd_device_t platform_get_input_snd_device(void *platform, audio_devices_t out_d
            } else {
                snd_device = SND_DEVICE_IN_VOICE_SPEAKER_MIC;
                if (audio_extn_hfp_is_active(adev))
                    platform_set_echo_reference(adev->platform, true);
                    platform_set_echo_reference(adev, true, out_device);
            }
        } else if (out_device & AUDIO_DEVICE_OUT_TELEPHONY_TX)
            snd_device = SND_DEVICE_IN_VOICE_RX;
@@ -2341,7 +2358,7 @@ snd_device_t platform_get_input_snd_device(void *platform, audio_devices_t out_d
                } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
                    snd_device = SND_DEVICE_IN_HEADSET_MIC_FLUENCE;
                }
                platform_set_echo_reference(adev->platform, true);
                platform_set_echo_reference(adev, true, out_device);
            } else if (adev->active_input->enable_aec) {
                if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
                    if (my_data->fluence_in_spkr_mode) {
@@ -2363,7 +2380,7 @@ snd_device_t platform_get_input_snd_device(void *platform, audio_devices_t out_d
                } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
                    snd_device = SND_DEVICE_IN_HEADSET_MIC_FLUENCE;
                }
                platform_set_echo_reference(adev->platform, true);
                platform_set_echo_reference(adev, true, out_device);
            } else if (adev->active_input->enable_ns) {
                if (in_device & AUDIO_DEVICE_IN_BACK_MIC) {
                    if (my_data->fluence_in_spkr_mode) {
@@ -2385,9 +2402,9 @@ snd_device_t platform_get_input_snd_device(void *platform, audio_devices_t out_d
                } else if (in_device & AUDIO_DEVICE_IN_WIRED_HEADSET) {
                    snd_device = SND_DEVICE_IN_HEADSET_MIC_FLUENCE;
                }
                platform_set_echo_reference(adev->platform, false);
                platform_set_echo_reference(adev, false, out_device);
            } else
                platform_set_echo_reference(adev->platform, false);
                platform_set_echo_reference(adev, false, out_device);
        }
    } else if (source == AUDIO_SOURCE_MIC) {
        if (in_device & AUDIO_DEVICE_IN_BUILTIN_MIC &&
@@ -2395,10 +2412,10 @@ snd_device_t platform_get_input_snd_device(void *platform, audio_devices_t out_d
            if(my_data->fluence_in_audio_rec) {
                if(my_data->fluence_type & FLUENCE_QUAD_MIC) {
                    snd_device = SND_DEVICE_IN_HANDSET_QMIC;
                    platform_set_echo_reference(adev->platform, true);
                    platform_set_echo_reference(adev, true, out_device);
                } else if (my_data->fluence_type & FLUENCE_DUAL_MIC) {
                    snd_device = SND_DEVICE_IN_HANDSET_DMIC;
                    platform_set_echo_reference(adev->platform, true);
                    platform_set_echo_reference(adev, true, out_device);
                }
            }
        }
@@ -3362,9 +3379,12 @@ bool platform_check_codec_backend_cfg(struct audio_device* adev,

    ALOGI("%s Codec selected backend: %d current bit width: %d and sample rate: %d",
               __func__, backend_idx, bit_width, sample_rate);
    // For voice calls use default configuration

    // For voice calls use default configuration i.e. 16b/48K, only applicable to
    // default backend
    // force routing is not required here, caller will do it anyway
    if (voice_is_in_call(adev) || adev->mode == AUDIO_MODE_IN_COMMUNICATION) {
    if ((voice_is_in_call(adev) || adev->mode == AUDIO_MODE_IN_COMMUNICATION) &&
        backend_idx == DEFAULT_CODEC_BACKEND) {
        ALOGW("%s:Use default bw and sr for voice/voip calls ",__func__);
        bit_width = CODEC_BACKEND_DEFAULT_BIT_WIDTH;
        sample_rate =  CODEC_BACKEND_DEFAULT_SAMPLE_RATE;
+1 −1
Original line number Diff line number Diff line
@@ -101,7 +101,7 @@ bool platform_check_and_set_codec_backend_cfg(struct audio_device* adev,
                   struct audio_usecase *usecase, snd_device_t snd_device);
int platform_get_usecase_index(const char * usecase);
int platform_set_usecase_pcm_id(audio_usecase_t usecase, int32_t type, int32_t pcm_id);
void platform_set_echo_reference(void *platform, bool enable);
void platform_set_echo_reference(struct audio_device *adev, bool enable, audio_devices_t out_device);
void platform_get_device_to_be_id_map(int **be_id_map, int *length);

int platform_set_channel_allocation(void *platform, int channel_alloc);