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

Commit f23619b4 authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "hal: Add support to get speaker FTM parameters" into av-userspace.lnx.1.0-dev.1.0

parents 3abfee28 4ffc926a
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -764,6 +764,7 @@ void audio_extn_set_parameters(struct audio_device *adev,
   audio_extn_hpx_set_parameters(adev, parms);
   audio_extn_pm_set_parameters(parms);
   audio_extn_source_track_set_parameters(adev, parms);
   audio_extn_fbsp_set_parameters(parms);
   check_and_set_hdmi_connection_status(parms);
   if (adev->offload_effects_set_parameters != NULL)
       adev->offload_effects_set_parameters(parms);
@@ -781,6 +782,7 @@ void audio_extn_get_parameters(const struct audio_device *adev,
    audio_extn_dts_eagle_get_parameters(adev, query, reply);
    audio_extn_hpx_get_parameters(query, reply);
    audio_extn_source_track_get_parameters(adev, query, reply);
    audio_extn_fbsp_get_parameters(query, reply);
    if (adev->offload_effects_get_parameters != NULL)
        adev->offload_effects_get_parameters(query, reply);

+5 −0
Original line number Diff line number Diff line
@@ -298,6 +298,8 @@ int32_t audio_extn_read_xml(struct audio_device *adev, uint32_t mixer_card,
#define audio_extn_spkr_prot_stop_processing(snd_device)     (0)
#define audio_extn_spkr_prot_is_enabled() (false)
#define audio_extn_spkr_prot_set_parameters(parms, value, len)   (0)
#define audio_extn_fbsp_set_parameters(parms)   (0)
#define audio_extn_fbsp_get_parameters(query, reply)   (0)
#else
void audio_extn_spkr_prot_init(void *adev);
int audio_extn_spkr_prot_start_processing(snd_device_t snd_device);
@@ -306,6 +308,9 @@ bool audio_extn_spkr_prot_is_enabled();
void audio_extn_spkr_prot_calib_cancel(void *adev);
void audio_extn_spkr_prot_set_parameters(struct str_parms *parms,
                                         char *value, int len);
int audio_extn_fbsp_set_parameters(struct str_parms *parms);
int audio_extn_fbsp_get_parameters(struct str_parms *query,
                                   struct str_parms *reply);
#endif

#ifndef COMPRESS_CAPTURE_ENABLED
+358 −34
Original line number Diff line number Diff line
@@ -103,6 +103,12 @@
#define AUDIO_PARAMETER_KEY_SPKR_TZ_1     "spkr_1_tz_name"
#define AUDIO_PARAMETER_KEY_SPKR_TZ_2     "spkr_2_tz_name"

#define AUDIO_PARAMETER_KEY_FBSP_TRIGGER_SPKR_CAL   "trigger_spkr_cal"
#define AUDIO_PARAMETER_KEY_FBSP_GET_SPKR_CAL       "get_spkr_cal"
#define AUDIO_PARAMETER_KEY_FBSP_CFG_WAIT_TIME      "fbsp_cfg_wait_time"
#define AUDIO_PARAMETER_KEY_FBSP_CFG_FTM_TIME       "fbsp_cfg_ftm_time"
#define AUDIO_PARAMETER_KEY_FBSP_GET_FTM_PARAM      "get_ftm_param"

/*Modes of Speaker Protection*/
enum speaker_protection_mode {
    SPKR_PROTECTION_DISABLED = -1,
@@ -138,6 +144,9 @@ struct speaker_prot_session {
    bool wsa_found;
    int spkr_1_tzn;
    int spkr_2_tzn;
    bool trigger_cal;
    pthread_mutex_t cal_wait_cond_mutex;
    pthread_cond_t cal_wait_condition;
};

static struct pcm_config pcm_config_skr_prot = {
@@ -276,6 +285,7 @@ static bool is_speaker_in_use(unsigned long *sec)
    }
    if (handle.spkr_in_use) {
        *sec = 0;
        handle.trigger_cal = false;
        return true;
    } else {
        clock_gettime(CLOCK_BOOTTIME, &temp);
@@ -537,15 +547,6 @@ static int spkr_calibrate(int t0_spk_1, int t0_spk_2)
                ALOGD("%s: spkr_prot_thread calib Success R0 %d %d",
                 __func__, status.r0[SP_V2_SPKR_1], status.r0[SP_V2_SPKR_2]);
                FILE *fp;

                vi_feed_no_channels = vi_feed_get_channels(adev);
                ALOGD("%s: vi_feed_no_channels %d", __func__, vi_feed_no_channels);
                if (vi_feed_no_channels < 0) {
                    ALOGE("%s: no of channels negative !!", __func__);
                    /* limit the number of channels to 2*/
                    vi_feed_no_channels = 2;
                }

                fp = fopen(CALIB_FILE,"wb");
                if (!fp) {
                    ALOGE("%s: spkr_prot_thread File open failed %s",
@@ -636,6 +637,19 @@ exit:
    return status.status;
}

static void spkr_calibrate_wait()
{
    struct timespec ts;

    clock_gettime(CLOCK_REALTIME, &ts);
    ts.tv_sec += WAKEUP_MIN_IDLE_CHECK;
    ts.tv_nsec = 0;
    pthread_mutex_lock(&handle.cal_wait_cond_mutex);
    pthread_cond_timedwait(&handle.cal_wait_condition,
                           &handle.cal_wait_cond_mutex, &ts);
    pthread_mutex_unlock(&handle.cal_wait_cond_mutex);
}

static void* spkr_calibration_thread()
{
    unsigned long sec = 0;
@@ -689,14 +703,6 @@ static void* spkr_calibration_thread()
    if (fp) {
        int i;
        bool spkr_calibrated = true;
        /* HAL for speaker protection is always calibrating for stereo usecase*/
        vi_feed_no_channels = vi_feed_get_channels(adev);
        ALOGD("%s: vi_feed_no_channels %d", __func__, vi_feed_no_channels);
        if (vi_feed_no_channels < 0) {
            ALOGE("%s: no of channels negative !!", __func__);
            /* limit the number of channels to 2*/
            vi_feed_no_channels = 2;
        }
        for (i = 0; i < vi_feed_no_channels; i++) {
            fread(&protCfg.r0[i], sizeof(protCfg.r0[i]), 1, fp);
            fread(&protCfg.t0[i], sizeof(protCfg.t0[i]), 1, fp);
@@ -741,13 +747,13 @@ static void* spkr_calibration_thread()
            if (is_speaker_in_use(&sec)) {
                ALOGV("%s: WSA Speaker in use retry calibration", __func__);
                pthread_mutex_unlock(&adev->lock);
                sleep(WAKEUP_MIN_IDLE_CHECK);
                spkr_calibrate_wait();
                continue;
            } else {
                ALOGD("%s: wsa speaker idle %ld,minimum time %ld", __func__, sec, min_idle_time);
                if (sec < min_idle_time) {
                if (!(sec > min_idle_time || handle.trigger_cal)) {
                    pthread_mutex_unlock(&adev->lock);
                    sleep(WAKEUP_MIN_IDLE_CHECK);
                    spkr_calibrate_wait();
                    continue;
               }
               goahead = true;
@@ -755,7 +761,7 @@ static void* spkr_calibration_thread()
           if (!list_empty(&adev->usecase_list)) {
                ALOGD("%s: Usecase active re-try calibration", __func__);
                pthread_mutex_unlock(&adev->lock);
                sleep(WAKEUP_MIN_IDLE_CHECK);
                spkr_calibrate_wait();
                continue;
           }
           if (goahead) {
@@ -776,7 +782,7 @@ static void* spkr_calibration_thread()
                   if (t0_spk_1 < TZ_TEMP_MIN_THRESHOLD ||
                       t0_spk_1 > TZ_TEMP_MAX_THRESHOLD) {
                       pthread_mutex_unlock(&adev->lock);
                       sleep(WAKEUP_MIN_IDLE_CHECK);
                       spkr_calibrate_wait();
                       continue;
                   }
                   ALOGD("%s: temp T0 for spkr1 %d\n", __func__, t0_spk_1);
@@ -799,7 +805,7 @@ static void* spkr_calibration_thread()
                   if (t0_spk_2 < TZ_TEMP_MIN_THRESHOLD ||
                       t0_spk_2 > TZ_TEMP_MAX_THRESHOLD) {
                       pthread_mutex_unlock(&adev->lock);
                       sleep(WAKEUP_MIN_IDLE_CHECK);
                       spkr_calibrate_wait();
                       continue;
                   }
                   ALOGD("%s: temp T0 for spkr2 %d\n", __func__, t0_spk_2);
@@ -836,12 +842,12 @@ static void* spkr_calibration_thread()
        if (is_speaker_in_use(&sec)) {
            ALOGV("%s: Speaker in use retry calibration", __func__);
            pthread_mutex_unlock(&adev->lock);
            sleep(WAKEUP_MIN_IDLE_CHECK);
            spkr_calibrate_wait();
            continue;
        } else {
            if (sec < min_idle_time) {
            if (!(sec > min_idle_time || handle.trigger_cal)) {
                pthread_mutex_unlock(&adev->lock);
                sleep(WAKEUP_MIN_IDLE_CHECK);
                spkr_calibrate_wait();
                continue;
            }
            goahead = true;
@@ -850,7 +856,7 @@ static void* spkr_calibration_thread()
            ALOGD("%s: Usecase active re-try calibration", __func__);
            goahead = false;
            pthread_mutex_unlock(&adev->lock);
            sleep(WAKEUP_MIN_IDLE_CHECK);
            spkr_calibrate_wait();
            continue;
        }
        if (goahead) {
@@ -923,6 +929,319 @@ void audio_extn_spkr_prot_set_parameters(struct str_parms *parms,
          tz_names.spkr_1_name, tz_names.spkr_2_name);
}

static int spkr_vi_channels(struct audio_device *adev)
{
    int vi_channels;

    vi_channels = vi_feed_get_channels(adev);
    ALOGD("%s: vi_channels %d", __func__, vi_channels);
    if (vi_channels < 0 || vi_channels > SP_V2_NUM_MAX_SPKRS) {
        /* limit the number of channels to SP_V2_NUM_MAX_SPKRS */
        vi_channels = SP_V2_NUM_MAX_SPKRS;
    }
    return vi_channels;
}

static void get_spkr_prot_thermal_cal(char *param)
{
    int i, status = 0;
    int r0[SP_V2_NUM_MAX_SPKRS] = {0}, t0[SP_V2_NUM_MAX_SPKRS] = {0};
    double dr0[SP_V2_NUM_MAX_SPKRS] = {0}, dt0[SP_V2_NUM_MAX_SPKRS] = {0};

    FILE *fp = fopen(CALIB_FILE,"rb");
    if (fp) {
        for (i = 0; i < vi_feed_no_channels; i++) {
            fread(&r0[i], sizeof(int), 1, fp);
            fread(&t0[i], sizeof(int), 1, fp);
            /* Convert from ADSP format to readable format */
            dr0[i] = ((double)r0[i])/(1 << 24);
            dt0[i] = ((double)t0[i])/(1 << 6);
        }
        ALOGV("%s: R0= %lf, %lf, T0= %lf, %lf",
              __func__, dr0[0], dr0[1], dt0[0], dt0[1]);
        fclose(fp);
    } else {
        ALOGE("%s: failed to open cal file\n", __func__);
        status = -EINVAL;
    }
    sprintf(param, "SpkrCalStatus: %d; R0: %lf, %lf; T0: %lf, %lf",
            status, dr0[SP_V2_SPKR_1], dr0[SP_V2_SPKR_2],
            dt0[SP_V2_SPKR_1], dt0[SP_V2_SPKR_2]);
    ALOGD("%s:: param = %s\n", __func__, param);

    return;
}

#ifdef MSM_SPKR_PROT_IN_FTM_MODE

static int set_spkr_prot_ftm_cfg(int wait_time, int ftm_time)
{
    int ret = 0;
    struct audio_cal_sp_th_vi_ftm_cfg th_cal_data;
    struct audio_cal_sp_ex_vi_ftm_cfg ex_cal_data;

    int cal_fd = open("/dev/msm_audio_cal",O_RDWR | O_NONBLOCK);
    if (cal_fd < 0) {
        ALOGE("%s: open msm_acdb failed", __func__);
        ret = -ENODEV;
        goto done;
    }

    memset(&th_cal_data, 0, sizeof(th_cal_data));
    th_cal_data.hdr.data_size = sizeof(th_cal_data);
    th_cal_data.hdr.version = VERSION_0_0;
    th_cal_data.hdr.cal_type = AFE_FB_SPKR_PROT_TH_VI_CAL_TYPE;
    th_cal_data.hdr.cal_type_size = sizeof(th_cal_data.cal_type);
    th_cal_data.cal_type.cal_hdr.version = VERSION_0_0;
    th_cal_data.cal_type.cal_hdr.buffer_number = 0;
    th_cal_data.cal_type.cal_info.wait_time[SP_V2_SPKR_1] = wait_time;
    th_cal_data.cal_type.cal_info.wait_time[SP_V2_SPKR_2] = wait_time;
    th_cal_data.cal_type.cal_info.ftm_time[SP_V2_SPKR_1] = ftm_time;
    th_cal_data.cal_type.cal_info.ftm_time[SP_V2_SPKR_2] = ftm_time;
    th_cal_data.cal_type.cal_info.mode = MSM_SPKR_PROT_IN_FTM_MODE; // FTM mode
    th_cal_data.cal_type.cal_data.mem_handle = -1;

    if (ioctl(cal_fd, AUDIO_SET_CALIBRATION, &th_cal_data))
        ALOGE("%s: failed to set TH VI FTM_CFG, errno = %d", __func__, errno);

    memset(&ex_cal_data, 0, sizeof(ex_cal_data));
    ex_cal_data.hdr.data_size = sizeof(ex_cal_data);
    ex_cal_data.hdr.version = VERSION_0_0;
    ex_cal_data.hdr.cal_type = AFE_FB_SPKR_PROT_EX_VI_CAL_TYPE;
    ex_cal_data.hdr.cal_type_size = sizeof(ex_cal_data.cal_type);
    ex_cal_data.cal_type.cal_hdr.version = VERSION_0_0;
    ex_cal_data.cal_type.cal_hdr.buffer_number = 0;
    ex_cal_data.cal_type.cal_info.wait_time[SP_V2_SPKR_1] = wait_time;
    ex_cal_data.cal_type.cal_info.wait_time[SP_V2_SPKR_2] = wait_time;
    ex_cal_data.cal_type.cal_info.ftm_time[SP_V2_SPKR_1] = ftm_time;
    ex_cal_data.cal_type.cal_info.ftm_time[SP_V2_SPKR_2] = ftm_time;
    ex_cal_data.cal_type.cal_info.mode = MSM_SPKR_PROT_IN_FTM_MODE; // FTM mode
    ex_cal_data.cal_type.cal_data.mem_handle = -1;

    if (ioctl(cal_fd, AUDIO_SET_CALIBRATION, &ex_cal_data))
        ALOGE("%s: failed to set EX VI FTM_CFG, ret = %d", __func__, errno);

    if (cal_fd > 0)
        close(cal_fd);
done:
    return ret;
}

static void get_spkr_prot_ftm_param(char *param)
{
    struct audio_cal_sp_th_vi_param th_vi_cal_data;
    struct audio_cal_sp_ex_vi_param ex_vi_cal_data;
    int i;
    int ftm_status[SP_V2_NUM_MAX_SPKRS];
    double rdc[SP_V2_NUM_MAX_SPKRS], temp[SP_V2_NUM_MAX_SPKRS];
    double f[SP_V2_NUM_MAX_SPKRS], r[SP_V2_NUM_MAX_SPKRS], q[SP_V2_NUM_MAX_SPKRS];

    int cal_fd = open("/dev/msm_audio_cal",O_RDWR | O_NONBLOCK);
    if (cal_fd < 0) {
        ALOGE("%s: open msm_acdb failed", __func__);
        goto done;
    }

    memset(&th_vi_cal_data, 0, sizeof(th_vi_cal_data));
    th_vi_cal_data.cal_type.cal_info.status[SP_V2_SPKR_1] = -EINVAL;
    th_vi_cal_data.cal_type.cal_info.status[SP_V2_SPKR_2] = -EINVAL;
    th_vi_cal_data.hdr.data_size = sizeof(th_vi_cal_data);
    th_vi_cal_data.hdr.version = VERSION_0_0;
    th_vi_cal_data.hdr.cal_type = AFE_FB_SPKR_PROT_TH_VI_CAL_TYPE;
    th_vi_cal_data.hdr.cal_type_size = sizeof(th_vi_cal_data.cal_type);
    th_vi_cal_data.cal_type.cal_hdr.version = VERSION_0_0;
    th_vi_cal_data.cal_type.cal_hdr.buffer_number = 0;
    th_vi_cal_data.cal_type.cal_data.mem_handle = -1;

    if (ioctl(cal_fd, AUDIO_GET_CALIBRATION, &th_vi_cal_data))
        ALOGE("%s: Error %d in getting th_vi_cal_data", __func__, errno);

    memset(&ex_vi_cal_data, 0, sizeof(ex_vi_cal_data));
    ex_vi_cal_data.cal_type.cal_info.status[SP_V2_SPKR_1] = -EINVAL;
    ex_vi_cal_data.cal_type.cal_info.status[SP_V2_SPKR_2] = -EINVAL;
    ex_vi_cal_data.hdr.data_size = sizeof(ex_vi_cal_data);
    ex_vi_cal_data.hdr.version = VERSION_0_0;
    ex_vi_cal_data.hdr.cal_type = AFE_FB_SPKR_PROT_EX_VI_CAL_TYPE;
    ex_vi_cal_data.hdr.cal_type_size = sizeof(ex_vi_cal_data.cal_type);
    ex_vi_cal_data.cal_type.cal_hdr.version = VERSION_0_0;
    ex_vi_cal_data.cal_type.cal_hdr.buffer_number = 0;
    ex_vi_cal_data.cal_type.cal_data.mem_handle = -1;

    if (ioctl(cal_fd, AUDIO_GET_CALIBRATION, &ex_vi_cal_data))
        ALOGE("%s: Error %d in getting ex_vi_cal_data", __func__, errno);

    for (i = 0; i < vi_feed_no_channels; i++) {
        /* Convert from ADSP format to readable format */
        rdc[i] = ((double)th_vi_cal_data.cal_type.cal_info.r_dc_q24[i])/(1<<24);
        temp[i] = ((double)th_vi_cal_data.cal_type.cal_info.temp_q22[i])/(1<<22);
        f[i] = ((double)ex_vi_cal_data.cal_type.cal_info.freq_q20[i])/(1<<20);
        r[i] = ((double)ex_vi_cal_data.cal_type.cal_info.resis_q24[i])/(1<<24);
        q[i] = ((double)ex_vi_cal_data.cal_type.cal_info.qmct_q24[i])/(1<<24);

        if (th_vi_cal_data.cal_type.cal_info.status[i] == 0 &&
            ex_vi_cal_data.cal_type.cal_info.status[i] == 0) {
            ftm_status[i] = 0;
        } else if (th_vi_cal_data.cal_type.cal_info.status[i] == -EAGAIN &&
                   ex_vi_cal_data.cal_type.cal_info.status[i] == -EAGAIN) {
            ftm_status[i] = -EAGAIN;
        } else {
            ftm_status[i] = -EINVAL;
        }
    }
    sprintf(param, "SpkrParamStatus: %d, %d; Rdc: %lf, %lf; Temp: %lf, %lf;"
            " Freq: %lf, %lf; Rect: %lf, %lf; Qmct: %lf, %lf",
            ftm_status[SP_V2_SPKR_1], ftm_status[SP_V2_SPKR_2],
            rdc[SP_V2_SPKR_1], rdc[SP_V2_SPKR_2], temp[SP_V2_SPKR_1],
            temp[SP_V2_SPKR_2], f[SP_V2_SPKR_1], f[SP_V2_SPKR_2],
            r[SP_V2_SPKR_1], r[SP_V2_SPKR_2], q[SP_V2_SPKR_1], q[SP_V2_SPKR_2]);
    ALOGD("%s:: param = %s\n", __func__, param);

    if (cal_fd > 0)
        close(cal_fd);
done:
    return;
}

#else

static void get_spkr_prot_ftm_param(char *param __unused)
{

    ALOGD("%s: not supported", __func__);
    return;
}

static int set_spkr_prot_ftm_cfg(int wait_time __unused, int ftm_time __unused)
{
    ALOGD("%s: not supported", __func__);
    return -ENOSYS;
}
#endif

static void spkr_calibrate_signal()
{
    pthread_mutex_lock(&handle.cal_wait_cond_mutex);
    pthread_cond_signal(&handle.cal_wait_condition);
    pthread_mutex_unlock(&handle.cal_wait_cond_mutex);
}

int audio_extn_fbsp_set_parameters(struct str_parms *parms)
{
    int ret= 0 , err;
    char *str;
    char *value = NULL;
    int val, len, i;
    char *test_r = NULL;
    char *cfg_str;
    int wait_time, ftm_time;
    char *kv_pairs = str_parms_to_str(parms);

    if(kv_pairs == NULL) {
        ret = -ENOMEM;
        ALOGE("[%s] key-value pair is NULL",__func__);
        goto done;
    }
    ALOGV_IF(kv_pairs != NULL, "%s: enter: %s", __func__, kv_pairs);

    len = strlen(kv_pairs);
    value = (char*)calloc(len, sizeof(char));
    if(value == NULL) {
        ret = -ENOMEM;
        ALOGE("[%s] failed to allocate memory",__func__);
        goto done;
    }
    if (!handle.spkr_prot_enable) {
        ALOGD("%s: Speaker protection disabled", __func__);
        goto done;
    }

    err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_FBSP_TRIGGER_SPKR_CAL, value,
                            len);
    if (err >= 0) {
        str_parms_del(parms, AUDIO_PARAMETER_KEY_FBSP_TRIGGER_SPKR_CAL);
        if ((strcmp(value, "true") == 0) || (strcmp(value, "yes") == 0)) {
            handle.trigger_cal = true;
            spkr_calibrate_signal();
        }
        goto done;
    }

    /* Expected key value pair is in below format:
     * AUDIO_PARAM_FBSP_CFG_WAIT_TIME=waittime;AUDIO_PARAM_FBSP_CFG_FTM_TIME=ftmtime;
     * Parse waittime and ftmtime from it.
     */
    err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_FBSP_CFG_WAIT_TIME,
                            value, len);
    if (err >= 0) {
        str_parms_del(parms, AUDIO_PARAMETER_KEY_FBSP_CFG_WAIT_TIME);
        cfg_str = strtok_r(value, ";", &test_r);
        if (cfg_str == NULL) {
            ALOGE("%s: incorrect wait time cfg_str", __func__);
            ret = -EINVAL;
            goto done;
        }
        wait_time = atoi(cfg_str);
        ALOGV(" %s: cfg_str = %s, wait_time = %d", __func__, cfg_str, wait_time);

        err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_FBSP_CFG_FTM_TIME,
                                value, len);
        if (err >= 0) {
            str_parms_del(parms, AUDIO_PARAMETER_KEY_FBSP_CFG_FTM_TIME);
            cfg_str = strtok_r(value, ";", &test_r);
            if (cfg_str == NULL) {
                ALOGE("%s: incorrect ftm time cfg_str", __func__);
                ret = -EINVAL;
                goto done;
            }
            ftm_time = atoi(cfg_str);
            ALOGV(" %s: cfg_str = %s, ftm_time = %d", __func__, cfg_str, ftm_time);

            ret = set_spkr_prot_ftm_cfg(wait_time, ftm_time);
            if (ret < 0) {
                ALOGE("%s: set_spkr_prot_ftm_cfg failed", __func__);
                goto done;
            }
        }
    }

done:
    ALOGV("%s: exit with code(%d)", __func__, ret);

    if(kv_pairs != NULL)
        free(kv_pairs);
    if(value != NULL)
        free(value);

    return ret;
}

int audio_extn_fbsp_get_parameters(struct str_parms *query,
                                   struct str_parms *reply)
{
    int err = 0;
    char value[1024] = {0};

    if (!handle.spkr_prot_enable) {
        ALOGD("%s: Speaker protection disabled", __func__);
        return -EINVAL;
    }

    err = str_parms_get_str(query, AUDIO_PARAMETER_KEY_FBSP_GET_SPKR_CAL, value,
                                                          sizeof(value));
    if (err >= 0) {
        get_spkr_prot_thermal_cal(value);
        str_parms_add_str(reply, AUDIO_PARAMETER_KEY_FBSP_GET_SPKR_CAL, value);
    }
    err = str_parms_get_str(query, AUDIO_PARAMETER_KEY_FBSP_GET_FTM_PARAM, value,
                            sizeof(value));
    if (err >= 0) {
        get_spkr_prot_ftm_param(value);
        str_parms_add_str(reply, AUDIO_PARAMETER_KEY_FBSP_GET_FTM_PARAM, value);
    }
done:
    return err;
}

void audio_extn_spkr_prot_init(void *adev)
{
    char value[PROPERTY_VALUE_MAX];
@@ -944,6 +1263,11 @@ void audio_extn_spkr_prot_init(void *adev)
    handle.spkr_prot_mode = MSM_SPKR_PROT_DISABLED;
    handle.spkr_processing_state = SPKR_PROCESSING_IN_IDLE;
    handle.spkr_prot_t0 = -1;
    handle.trigger_cal = false;
    /* HAL for speaker protection is always calibrating for stereo usecase*/
    vi_feed_no_channels = spkr_vi_channels(adev);
    pthread_cond_init(&handle.cal_wait_condition, NULL);
    pthread_mutex_init(&handle.cal_wait_cond_mutex, NULL);

    if (is_wsa_present()) {
        if (platform_spkr_prot_is_wsa_analog_mode(adev) == 1) {