diff options
author | Laxminath Kasam <lkasam@codeaurora.org> | 2019-02-20 14:34:31 +0530 |
---|---|---|
committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2019-03-01 01:25:01 -0800 |
commit | e33b7d6be5e97e6efa2267d9da610cf4d61b0435 (patch) | |
tree | 27b213d915250d111ab29bd064ae04062315ee0b /hal/audio_extn | |
parent | 224842f1c2d547fa68b5c31c7445312fa4898034 (diff) | |
download | hardware_qcom_audio-e33b7d6be5e97e6efa2267d9da610cf4d61b0435.tar.gz hardware_qcom_audio-e33b7d6be5e97e6efa2267d9da610cf4d61b0435.tar.bz2 hardware_qcom_audio-e33b7d6be5e97e6efa2267d9da610cf4d61b0435.zip |
hal: spk_prot: add custom support to trigger v-validation
For v-validation thread can be invoked as part
of set param call.
Two setparams are required to be set :
1. "fbsp_v_vali_wait_time=xxx;fbsp_v_vali_vali_time=xxx;"
- to config v-vali params wait time(100 to 1000ms),
validation time (1000 to 3000ms).
2. "trigger_v_vali" to true - to start v-validation
Change-Id: I16ccc132242a21948beeceb0382c15ef88c0b431
Diffstat (limited to 'hal/audio_extn')
-rw-r--r-- | hal/audio_extn/spkr_protection.c | 305 |
1 files changed, 289 insertions, 16 deletions
diff --git a/hal/audio_extn/spkr_protection.c b/hal/audio_extn/spkr_protection.c index be83d70f..54c1e5aa 100644 --- a/hal/audio_extn/spkr_protection.c +++ b/hal/audio_extn/spkr_protection.c @@ -125,6 +125,12 @@ enum sp_version { /* In wsa analog mode vi feedback DAI supports at max 2 channels*/ #define WSA_ANALOG_MODE_CHANNELS 2 +/* v-validation parameters */ +#define SPKR_V_VALI_TEMP_MASK 0xFFFE +#define SPKR_V_VALI_DEFAULT_WAIT_TIME 500 +#define SPKR_V_VALI_DEFAULT_VALI_TIME 2000 +#define SPKR_V_VALI_SUCCESS 1 + #define MAX_PATH (256) #define MAX_STR_SIZE (1024) #define THERMAL_SYSFS "/sys/devices/virtual/thermal" @@ -140,7 +146,11 @@ enum sp_version { #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" +#define AUDIO_PARAMETER_KEY_FBSP_TRIGGER_V_VALI "trigger_v_vali" +#define AUDIO_PARAMETER_KEY_FBSP_V_VALI_WAIT_TIME "fbsp_v_vali_wait_time" +#define AUDIO_PARAMETER_KEY_FBSP_V_VALI_VALI_TIME "fbsp_v_vali_vali_time" +static int get_spkr_prot_v_vali_param(int cal_fd, int *status, int *vrms); /*Modes of Speaker Protection*/ enum speaker_protection_mode { SPKR_PROTECTION_DISABLED = -1, @@ -159,6 +169,7 @@ struct speaker_prot_session { int thermal_client_handle; pthread_mutex_t mutex_spkr_prot; pthread_t spkr_calibration_thread; + pthread_t spkr_v_vali_thread; pthread_mutex_t spkr_prot_thermalsync_mutex; pthread_cond_t spkr_prot_thermalsync; int cancel_spkr_calib; @@ -166,6 +177,7 @@ struct speaker_prot_session { pthread_mutex_t spkr_calib_cancelack_mutex; pthread_cond_t spkr_calibcancel_ack; pthread_t speaker_prot_threadid; + pthread_t v_vali_threadid; void *thermal_handle; void *adev_handle; int spkr_prot_t0; @@ -183,6 +195,7 @@ struct speaker_prot_session { int spkr_1_tzn; int spkr_2_tzn; bool trigger_cal; + bool trigger_v_vali; bool apply_cal; pthread_mutex_t cal_wait_cond_mutex; pthread_cond_t cal_wait_condition; @@ -190,7 +203,10 @@ struct speaker_prot_session { volatile bool thread_exit; unsigned int sp_version; int limiter_th[SP_V2_NUM_MAX_SPKRS]; + int v_vali_wait_time; + int v_vali_vali_time; bool cal_thrd_created; + bool v_vali_thrd_created; }; static struct pcm_config pcm_config_skr_prot = { @@ -380,7 +396,8 @@ void audio_extn_spkr_prot_calib_cancel(void *adev) struct audio_usecase *uc_info; threadid = pthread_self(); ALOGV("%s: Entry", __func__); - if (pthread_equal(handle.speaker_prot_threadid, threadid) || !adev) { + if (pthread_equal(handle.speaker_prot_threadid, threadid) || !adev || + pthread_equal(handle.v_vali_threadid, threadid)) { ALOGE("%s: Invalid params", __func__); return; } @@ -743,12 +760,15 @@ static int spkr_calibrate(int t0_spk_1, int t0_spk_2) struct audio_device *adev = handle.adev_handle; struct audio_cal_info_spk_prot_cfg protCfg; struct audio_cal_info_msm_spk_prot_status status; + int status_v_vali[SP_V2_NUM_MAX_SPKRS], vrms[SP_V2_NUM_MAX_SPKRS]; bool cleanup = false, disable_rx = false, disable_tx = false; int acdb_fd = -1; struct audio_usecase *uc_info_rx = NULL, *uc_info_tx = NULL; int32_t pcm_dev_rx_id = -1, pcm_dev_tx_id = -1; struct timespec ts; + unsigned long total_time; bool acquire_device = false; + bool v_validation = false; memset(&status, 0, sizeof(status)); memset(&protCfg, 0, sizeof(protCfg)); @@ -760,12 +780,26 @@ static int spkr_calibrate(int t0_spk_1, int t0_spk_2) ALOGD("%s: Usecase present retry speaker protection", __func__); return -EAGAIN; } + if (t0_spk_1 == SPKR_V_VALI_TEMP_MASK && + t0_spk_2 == SPKR_V_VALI_TEMP_MASK) { + ALOGD("%s: v-validation start", __func__); + v_validation = true; + } acdb_fd = open("/dev/msm_audio_cal",O_RDWR | O_NONBLOCK); if (acdb_fd < 0) { ALOGE("%s: spkr_prot_thread open msm_acdb failed", __func__); return -ENODEV; } else { protCfg.mode = MSM_SPKR_PROT_CALIBRATION_IN_PROGRESS; + if (v_validation) { + if (handle.spkr_prot_mode == MSM_SPKR_PROT_CALIBRATED) { + t0_spk_1 = handle.sp_r0t0_cal.t0[SP_V2_SPKR_1]; + t0_spk_2 = handle.sp_r0t0_cal.t0[SP_V2_SPKR_2]; + } else { + t0_spk_1 = SAFE_SPKR_TEMP_Q6; + t0_spk_2 = SAFE_SPKR_TEMP_Q6; + } + } protCfg.t0[SP_V2_SPKR_1] = t0_spk_1; protCfg.t0[SP_V2_SPKR_2] = t0_spk_2; if (set_spkr_prot_cal(acdb_fd, &protCfg)) { @@ -858,7 +892,13 @@ static int spkr_calibrate(int t0_spk_1, int t0_spk_2) } cleanup = true; clock_gettime(CLOCK_MONOTONIC, &ts); - ts.tv_sec += (SLEEP_AFTER_CALIB_START/1000); + if (!v_validation) { + ts.tv_sec += (SLEEP_AFTER_CALIB_START/1000); + } else { + total_time = (handle.v_vali_wait_time + handle.v_vali_vali_time); + ts.tv_sec += (total_time/1000); + ts.tv_nsec += ((total_time%1000) * 1000000); + } pthread_mutex_lock(&handle.mutex_spkr_prot); pthread_mutex_unlock(&adev->lock); acquire_device = true; @@ -873,6 +913,23 @@ static int spkr_calibrate(int t0_spk_1, int t0_spk_2) } if (acdb_fd > 0) { status.status = -EINVAL; + if (v_validation) { + if (!get_spkr_prot_v_vali_param(acdb_fd, status_v_vali, vrms)) { + int i; + + for (i = 0; i < vi_feed_no_channels; i++) { + if ((status_v_vali[i] != SPKR_V_VALI_SUCCESS)) { + ALOGE("%s: failed in v-validation, retry\n", __func__); + goto exit; + } else { + ALOGD("%s: spkr_v_validation success vrms %d", + __func__, vrms[i]); + } + } + status.status = 0; + } + goto exit; + } while (!get_spkr_prot_cal(acdb_fd, &status)) { /*sleep for 200 ms to check for status check*/ if (!status.status) { @@ -920,19 +977,21 @@ exit: if (handle.pcm_tx) pcm_close(handle.pcm_tx); handle.pcm_tx = NULL; - if (!status.status) { - protCfg.mode = MSM_SPKR_PROT_CALIBRATED; - protCfg.r0[SP_V2_SPKR_1] = status.r0[SP_V2_SPKR_1]; - protCfg.r0[SP_V2_SPKR_2] = status.r0[SP_V2_SPKR_2]; - if (set_spkr_prot_cal(acdb_fd, &protCfg)) - ALOGE("%s: spkr_prot_thread disable calib mode", __func__); - else - handle.spkr_prot_mode = MSM_SPKR_PROT_CALIBRATED; - } else { - protCfg.mode = MSM_SPKR_PROT_NOT_CALIBRATED; - handle.spkr_prot_mode = MSM_SPKR_PROT_NOT_CALIBRATED; - if (set_spkr_prot_cal(acdb_fd, &protCfg)) - ALOGE("%s: spkr_prot_thread disable calib mode failed", __func__); + if (!v_validation) { + if (!status.status) { + protCfg.mode = MSM_SPKR_PROT_CALIBRATED; + protCfg.r0[SP_V2_SPKR_1] = status.r0[SP_V2_SPKR_1]; + protCfg.r0[SP_V2_SPKR_2] = status.r0[SP_V2_SPKR_2]; + if (set_spkr_prot_cal(acdb_fd, &protCfg)) + ALOGE("%s: spkr_prot_thread disable calib mode", __func__); + else + handle.spkr_prot_mode = MSM_SPKR_PROT_CALIBRATED; + } else { + protCfg.mode = MSM_SPKR_PROT_NOT_CALIBRATED; + handle.spkr_prot_mode = MSM_SPKR_PROT_NOT_CALIBRATED; + if (set_spkr_prot_cal(acdb_fd, &protCfg)) + ALOGE("%s: spkr_prot_thread disable calib mode failed", __func__); + } } if (acdb_fd > 0) close(acdb_fd); @@ -1443,6 +1502,11 @@ static void get_spkr_prot_ftm_param(char *param) 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; +#ifdef MSM_SPKR_PROT_IN_V_VALI_MODE + /* for v-validation, same cal type is used. + * need this mode info to differentiate feature under test */ + th_vi_cal_data.cal_type.cal_info.mode = MSM_SPKR_PROT_IN_FTM_MODE; // FTM mode +#endif if (ioctl(cal_fd, AUDIO_GET_CALIBRATION, &th_vi_cal_data)) ALOGE("%s: Error %d in getting th_vi_cal_data", __func__, errno); @@ -1510,6 +1574,129 @@ static int set_spkr_prot_ftm_cfg(int wait_time __unused, int ftm_time __unused) } #endif +#ifdef MSM_SPKR_PROT_IN_V_VALI_MODE + +static int set_spkr_prot_v_vali_cfg(int wait_time, int vali_time) +{ + int ret = 0; + struct audio_cal_sp_th_vi_v_vali_cfg 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(&cal_data, 0, sizeof(cal_data)); + cal_data.hdr.data_size = sizeof(cal_data); + cal_data.hdr.version = VERSION_0_0; + cal_data.hdr.cal_type = AFE_FB_SPKR_PROT_TH_VI_CAL_TYPE; + cal_data.hdr.cal_type_size = sizeof(cal_data.cal_type); + cal_data.cal_type.cal_hdr.version = VERSION_0_0; + cal_data.cal_type.cal_hdr.buffer_number = 0; + cal_data.cal_type.cal_info.wait_time[SP_V2_SPKR_1] = wait_time; + cal_data.cal_type.cal_info.wait_time[SP_V2_SPKR_2] = wait_time; + cal_data.cal_type.cal_info.vali_time[SP_V2_SPKR_1] = vali_time; + cal_data.cal_type.cal_info.vali_time[SP_V2_SPKR_2] = vali_time; + cal_data.cal_type.cal_info.mode = MSM_SPKR_PROT_IN_V_VALI_MODE; // V-VALI mode + cal_data.cal_type.cal_data.mem_handle = -1; + handle.v_vali_wait_time = wait_time; + handle.v_vali_vali_time = vali_time; + + if (ioctl(cal_fd, AUDIO_SET_CALIBRATION, &cal_data)) + ALOGE("%s: failed to set TH VI V_VALI_CFG, errno = %d", __func__, errno); + + if (cal_fd > 0) + close(cal_fd); +done: + return ret; +} + +static int get_spkr_prot_v_vali_param(int cal_fd, int *status, int *vrms) +{ + struct audio_cal_sp_th_vi_v_vali_param cal_data; + int ret = 0; + + if (cal_fd < 0) { + ALOGE("%s: Error: cal_fd = %d", __func__, cal_fd); + ret = -EINVAL; + goto done; + } + + if (status == NULL || vrms == NULL) { + ALOGE("%s: Error: status or vrms NULL", __func__); + ret = -EINVAL; + goto done; + } + + memset(&cal_data, 0, sizeof(cal_data)); + cal_data.cal_type.cal_info.status[SP_V2_SPKR_1] = -EINVAL; + cal_data.cal_type.cal_info.status[SP_V2_SPKR_2] = -EINVAL; + cal_data.hdr.data_size = sizeof(cal_data); + cal_data.hdr.version = VERSION_0_0; + cal_data.hdr.cal_type = AFE_FB_SPKR_PROT_TH_VI_CAL_TYPE; + cal_data.hdr.cal_type_size = sizeof(cal_data.cal_type); + cal_data.cal_type.cal_hdr.version = VERSION_0_0; + cal_data.cal_type.cal_hdr.buffer_number = 0; + cal_data.cal_type.cal_data.mem_handle = -1; + cal_data.cal_type.cal_info.mode = MSM_SPKR_PROT_IN_V_VALI_MODE; // V-VALI mode + + if (ioctl(cal_fd, AUDIO_GET_CALIBRATION, &cal_data)) { + ALOGE("%s: Error %d in getting V-VALI cal_data", __func__, errno); + ret = -ENODEV; + goto done; + } + + ALOGD("%s:: vrms = %d %d, status = %d %d\n", __func__, + cal_data.cal_type.cal_info.vrms_q24[SP_V2_SPKR_1], + cal_data.cal_type.cal_info.vrms_q24[SP_V2_SPKR_2], + cal_data.cal_type.cal_info.status[SP_V2_SPKR_1], + cal_data.cal_type.cal_info.status[SP_V2_SPKR_2]); + + vrms[SP_V2_SPKR_1] = cal_data.cal_type.cal_info.vrms_q24[SP_V2_SPKR_1]; + vrms[SP_V2_SPKR_2] = cal_data.cal_type.cal_info.vrms_q24[SP_V2_SPKR_2]; + status[SP_V2_SPKR_1] = cal_data.cal_type.cal_info.status[SP_V2_SPKR_1]; + status[SP_V2_SPKR_2] = cal_data.cal_type.cal_info.status[SP_V2_SPKR_2]; + +done: + return ret; +} +#else + +static int set_spkr_prot_v_vali_cfg(int wait_time __unused, int vali_time __unused) +{ + ALOGD("%s: not supported", __func__); + return -ENOSYS; +} + +static int get_spkr_prot_v_vali_param(int cal_fd __unused, int *status __unused, + int *vrms __unused) +{ + ALOGD("%s: not supported", __func__); + return -ENOSYS; +} +#endif + +static void* spkr_v_vali_thread() +{ + int ret = 0; + handle.v_vali_threadid = pthread_self(); + + if (!handle.v_vali_wait_time) + handle.v_vali_wait_time = SPKR_V_VALI_DEFAULT_WAIT_TIME;/*set default if not setparam */ + if (!handle.v_vali_vali_time) + handle.v_vali_vali_time = SPKR_V_VALI_DEFAULT_VALI_TIME;/*set default if not setparam */ + set_spkr_prot_v_vali_cfg(handle.v_vali_wait_time, handle.v_vali_vali_time); + ret = spkr_calibrate(SPKR_V_VALI_TEMP_MASK, + SPKR_V_VALI_TEMP_MASK);/*use 0xfffe as temp to initiate v_vali*/ + if (ret) + ALOGE("%s: failed, retry again\n", __func__); + pthread_exit(0); + handle.trigger_v_vali = false; + return NULL; +} + static void spkr_calibrate_signal() { pthread_mutex_lock(&handle.cal_wait_cond_mutex); @@ -1540,6 +1727,33 @@ static void spkr_calib_thread_create() handle.cal_thrd_created = true; } else { ALOGE("%s: speaker calibration thread creation failed", __func__); + handle.trigger_cal = false; + } +} + +static void spkr_v_vali_thread_create() +{ + int result = 0; + + if (!handle.spkr_prot_enable) { + ALOGD("%s: Speaker protection disabled", __func__); + return; + } + if (handle.v_vali_thrd_created) { + result = pthread_join(handle.spkr_v_vali_thread, (void **) NULL); + if (result < 0) { + ALOGE("%s:Unable to join the v-vali thread", __func__); + return; + } + handle.v_vali_thrd_created = false; + } + result = pthread_create(&handle.spkr_v_vali_thread, + (const pthread_attr_t *) NULL, spkr_v_vali_thread, &handle); + if (result == 0) { + handle.v_vali_thrd_created = true; + } else { + ALOGE("%s: failed to create v_vali thread\n", __func__); + handle.trigger_v_vali = false; } } @@ -1550,7 +1764,7 @@ int audio_extn_fbsp_set_parameters(struct str_parms *parms) int len; char *test_r = NULL; char *cfg_str; - int wait_time, ftm_time; + int wait_time, ftm_time, vali_time; char *kv_pairs = str_parms_to_str(parms); if(kv_pairs == NULL) { @@ -1599,6 +1813,19 @@ int audio_extn_fbsp_set_parameters(struct str_parms *parms) } goto done; } + + err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_FBSP_TRIGGER_V_VALI, value, + len); + if (err >= 0) { + str_parms_del(parms, AUDIO_PARAMETER_KEY_FBSP_TRIGGER_V_VALI); + if ((strcmp(value, "true") == 0) || (strcmp(value, "yes") == 0)) { + if (handle.trigger_v_vali) + goto done; + handle.trigger_v_vali = true; + spkr_v_vali_thread_create(); + } + 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. @@ -1636,6 +1863,43 @@ int audio_extn_fbsp_set_parameters(struct str_parms *parms) } } } + /* Expected key value pair is in below format: + * AUDIO_PARAM_FBSP_V_VALI_WAIT_TIME=waittime;AUDIO_PARAM_FBSP_V_VALI_VALI_TIME=valitime; + * Parse waittime and validationtime from it. + */ + err = str_parms_get_str(parms, AUDIO_PARAMETER_KEY_FBSP_V_VALI_WAIT_TIME, + value, len); + if (err >= 0) { + str_parms_del(parms, AUDIO_PARAMETER_KEY_FBSP_V_VALI_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_V_VALI_VALI_TIME, + value, len); + if (err >= 0) { + str_parms_del(parms, AUDIO_PARAMETER_KEY_FBSP_V_VALI_VALI_TIME); + cfg_str = strtok_r(value, ";", &test_r); + if (cfg_str == NULL) { + ALOGE("%s: incorrect validation time cfg_str", __func__); + ret = -EINVAL; + goto done; + } + vali_time = atoi(cfg_str); + ALOGV(" %s: cfg_str = %s, vali_time = %d", __func__, cfg_str, vali_time); + + ret = set_spkr_prot_v_vali_cfg(wait_time, vali_time); + if (ret < 0) { + ALOGE("%s: set_spkr_prot_v_vali_cfg failed", __func__); + goto done; + } + } + } done: ALOGV("%s: exit with code(%d)", __func__, ret); @@ -1810,6 +2074,15 @@ int audio_extn_spkr_prot_deinit() } handle.cal_thrd_created = false; } + if (handle.v_vali_thrd_created) { + result = pthread_join(handle.spkr_v_vali_thread, + (void **) NULL); + if (result < 0) { + ALOGE("%s:Unable to join the v_vali thread", __func__); + return -1; + } + handle.v_vali_thrd_created = false; + } destroy_thread_params(); memset(&handle, 0, sizeof(handle)); return 0; |