Point computeVfromM() { /* Knowing M(X, Y, Z), V(x, y, z) is defined by the three following equations : (1) x² + y² + z² = upperArmLength² (2) (x - X)² + (y - Y)² + (z - Z)² = lowerArmLength² (3) Xy = Yx The last one imply that the whole arm is in a vertical plane. The system as two solutions, we want the one with the biggest z coordinate. RESOLUTION: We substitue (1) in (2) and the system become (with no nul M coord) (1) x² + y² + z² = upperArmLength² (2) z = (A - xX - yY) / Z where A = (X² + Y² + Z² + upperArmLength² - lowerArmLength²) / 2 (3) y = Y/X * x We then obtains the following 2nd degree equation in x : x² + Y²/X² * x² + (A - xX - Y²/X * x)² / Z² = upperArmLength² => (1 + Y²/X² + (X + Y²/X)²/Z²) * x² - 2A(X + Y²/X)/Z² * x + A²/Z² - upperArmLength² = 0 If (x == 0) (1) y² + z² = upperArmLength² (2) y = (A - zZ) / Y => (1 + Z²/Y²) * z² - 2AZ/Y² * z + A² / Y² - upperArmLength² = 0 */ float X2 = M.x * M.x, Y2 = M.y * M.y; if (F_EQUAL(M.z, 0)) { return Point(M.x / 2, M.y / 2, static_cast<float>(sqrt( upperArmLength * upperArmLength - X2 / 4 - Y2 / 4))); } float Z2 = M.z * M.z, A = (X2 + Y2 + Z2 + upperArmLength * upperArmLength - lowerArmLength * lowerArmLength) / 2; if (F_EQUAL(M.x, 0)) { float dumb = 0, z = 0; sol2ndDegree(1 + Z2 / Y2, -2 * A * M.z / Y2, A * A / Y2 - upperArmLength * upperArmLength, dumb, z); return Point(0, (A - z * M.z) / M.y, z); } else if (F_EQUAL(M.y, 0)) { float dumb = 0, z = 0; sol2ndDegree(1 + Z2 / X2, -2 * A * M.z / X2, A * A / X2 - upperArmLength * upperArmLength, dumb, z); return Point((A - z * M.z) / M.x, 0, z); } float x1 = 0, x2 = 0; sol2ndDegree( 1 + Y2 / X2 + (M.x + Y2 / M.x) * (M.x + Y2 / M.x) / Z2, -2 * A * (M.x + Y2 / M.x) / Z2, A * A / Z2 - upperArmLength * upperArmLength, x1, x2); float z1 = (A - x1 * M.x - x1 * Y2 / M.x) / M.z, z2 = (A - x2 * M.x - x2 * Y2 / M.x) / M.z; if (z1 > z2) return Point(x1, x1 * M.y / M.x, z1); else return Point(x2, x2 * M.y / M.x, z2); }
/** color_correct_set_effect: * @mod: pointer to instance private data * @in_params: input data * @in_params_size: size of input data * * Set effect. * * This function executes in ISP thread context * * Return 0 on success. **/ static int color_correct_set_effect(isp_color_correct_mod_t *mod, isp_hw_pix_setting_params_t *in_params, uint32_t in_param_size) { int type; float s; if (in_param_size != sizeof(isp_hw_pix_setting_params_t)) { /* size mismatch */ CDBG_ERROR("%s: size mismatch, expecting = %d, received = %d", __func__, sizeof(isp_hw_pix_setting_params_t), in_param_size); return -1; } if (!mod->enable) { ISP_DBG(ISP_MOD_COLOR_CORRECT, "%s: CC not enabled", __func__); return 0; } type = in_params->effects.effect_type_mask; SET_UNITY_MATRIX(mod->effects_matrix, 3); if (type & (1 << ISP_EFFECT_SATURATION)) { s = 2.0 * in_params->effects.saturation; if (F_EQUAL(in_params->effects.hue, 0)) util_color_correct_populate_matrix(mod->effects_matrix, s); } if (type & (1 << ISP_EFFECT_HUE)) { s = 2.0 * in_params->effects.hue; if (!F_EQUAL(in_params->effects.saturation, .5)) util_color_correct_populate_matrix(mod->effects_matrix, s); } mod->hw_update_pending = TRUE; return 0; } /*color_correct_set_effect*/
/*=========================================================================== * FUNCTION vfe_wb_trigger_update * * DESCRIPTION *==========================================================================*/ vfe_status_t vfe_wb_trigger_update(int mod_id, void *mod_wb, void *vparms) { vfe_status_t status = VFE_SUCCESS; wb_mod_t* mod = (wb_mod_t*)mod_wb; vfe_params_t* params = (vfe_params_t*)vparms; int is_snap = IS_SNAP_MODE(params); int index = (is_snap) ? SNAP : PREV; int update = FALSE; if (!mod->enable) { CDBG("%s: WB not enabled", __func__); return VFE_SUCCESS; } if (!mod->trigger_enable) { CDBG("%s: WB trigger not enabled", __func__); return VFE_SUCCESS; } if (params->demosaic_wb_not_present && is_snap) { CDBG("%s: WB update not required in snapshot, hardcode the values", __func__); INIT_WB_GAIN(mod->awb_gain[SNAP], 1.0, 1.0, 1.0); return VFE_SUCCESS; } CDBG("%s: snap %d old %f %f %f new %f %f %f", __func__, is_snap, mod->awb_gain[index].g_gain, mod->awb_gain[index].b_gain, mod->awb_gain[index].r_gain, params->awb_params.gain.g_gain, params->awb_params.gain.b_gain, params->awb_params.gain.r_gain); if ((is_snap || !IS_MANUAL_WB(params)) && !WB_GAIN_EQUAL(params->awb_params.gain, mod->awb_gain[index]) && !WB_GAIN_EQ_ZERO(params->awb_params.gain)) { mod->awb_gain[index].g_gain = params->awb_params.gain.g_gain; mod->awb_gain[index].b_gain = params->awb_params.gain.b_gain; mod->awb_gain[index].r_gain = params->awb_params.gain.r_gain; params->awb_gain_update = TRUE; update = TRUE; } if (!F_EQUAL(params->aec_gain_adj.wb_gain_adj, mod->dig_gain[index])) { mod->dig_gain[index] = params->aec_gain_adj.wb_gain_adj; update = TRUE; } if (!update) { CDBG("%s: No update required", __func__); return VFE_SUCCESS; } mod->update = TRUE; CDBG("%s: updated", __func__); return status; } /* vfe_wb_trigger_update */
// Utility function giving in order solutions of a 2nd degree polynom void sol2ndDegree(float a, float b, float c, float& sMin, float& sMax) { bool aIsNull = F_EQUAL(a, 0); float delta = b * b - 4 * a *c; if (delta < 0 || (aIsNull && F_EQUAL(b, 0))) { TRACE_("ERROR: no solution in \'sol2ndDegree\' with" << "\n a = " << a << "\n b = " << b << "\n c = " << c); exit(13); } if (aIsNull) { sMin = sMax = c / b; } else { sMin = (-b - static_cast<float>(sqrt(delta))) / 2 / a; sMax = (-b + static_cast<float>(sqrt(delta))) / 2 / a; } }
/** color_conversion_set_effect: * * @mod: * @in_params: * @in_param_size: * * Set special effect * **/ static int color_conversion_set_effect(isp_color_conversion_mod_t *mod, isp_hw_pix_setting_params_t *in_params, uint32_t in_param_size) { if (in_param_size != sizeof(isp_hw_pix_setting_params_t)) { CDBG_ERROR("%s: size mismatch, expecting = %d, received = %d", __func__, sizeof(isp_hw_pix_setting_params_t), in_param_size); return -1; } int i = 0, j = 0; ISP_DBG(ISP_MOD_COLOR_CONV, "%s",__func__); float hue_matrix[2][2]; float sat_matrix[2][2]; float s, hue_in_radian; int type; int status= 0; if (in_params->bestshot_mode != CAM_SCENE_MODE_OFF) { ISP_DBG(ISP_MOD_COLOR_CONV, "%s: Best shot enabled, skip set effect", __func__); return 0; } s = 2.0 * in_params->effects.saturation; hue_in_radian = DEGREE_TO_RADIAN(in_params->effects.hue * 10); //ryan need to define in pix_common.h type = in_params->effects.effect_type_mask; if(type & (1 << ISP_EFFECT_SPECIAL)) { status = color_conversion_set_spl_effect(mod, in_params, in_param_size); if (status) goto END; } if(type & (1 << ISP_EFFECT_SATURATION)) { SET_UNITY_MATRIX(mod->effects_matrix, 2); SET_SAT_MATRIX(sat_matrix, s); } if(type & (1 << ISP_EFFECT_HUE)) { if (F_EQUAL(in_params->effects.hue, 0)) { SET_UNITY_MATRIX(hue_matrix, 2); } else { SET_HUE_MATRIX(hue_matrix, hue_in_radian); } MATRIX_MULT(sat_matrix, hue_matrix, mod->effects_matrix, 2, 2, 2); } #ifdef ENABLE_CV_LOGGING PRINT_2D_MATRIX(2, 2, mod->effects_matrix); #endif mod->hw_update_pending = TRUE; END: return status; }/*color_conversion_set_effect*/
/** clf_chroma_trigger_update: * @mod: CLF module instance * @in_params: triger update data * @in_param_size: update data size * * This function runs in ISP HW thread context. * * This function updates parametes and sets flag for hw update if needed * for chroma filtering * * Return: 0 - Success * -1 - parameter size mismatch **/ static int clf_chroma_trigger_update(isp_clf_mod_t *mod, isp_pix_trigger_update_input_t *in_params, uint32_t in_param_size) { chromatix_parms_type *chroma_ptr = (chromatix_parms_type *)in_params->cfg.chromatix_ptrs.chromatixPtr; chromatix_CL_filter_type *chromatix_CL_filter = &chroma_ptr->chromatix_VFE.chromatix_CL_filter; trigger_point_type *p_trigger_point = NULL; int8_t is_burst = IS_BURST_STREAMING(&(in_params->cfg)); tuning_control_type tuning_type; int8_t update_cf = FALSE; float ratio; Chroma_filter_type *p_cf_new = &(mod->clf_params.cf_param); Chroma_filter_type *p_cf = NULL; int8_t cf_enabled = mod->cf_enable && mod->cf_enable_trig; int status = 0; if (in_param_size != sizeof(isp_pix_trigger_update_input_t)) { /* size mismatch */ CDBG_ERROR("%s: size mismatch, expecting = %d, received = %d", __func__, sizeof(isp_pix_trigger_update_input_t), in_param_size); return -1; } if (!cf_enabled) { ISP_DBG(ISP_MOD_CLF, "%s: Chroma filter trigger not enabled %d %d", __func__, mod->cf_enable, mod->cf_enable_trig); return 0; } mod->cf_update = FALSE; tuning_type = chromatix_CL_filter->control_chroma_filter; p_trigger_point = &chromatix_CL_filter->chroma_filter_trigger_lowlight; p_cf = chromatix_CL_filter->chroma_filter; ratio = isp_util_get_aec_ratio(mod->notify_ops->parent, tuning_type, p_trigger_point, &(in_params->trigger_input.stats_update.aec_update), is_burst); update_cf = (mod->old_streaming_mode != in_params->cfg.streaming_mode) || !F_EQUAL(ratio, mod->cur_cf_aec_ratio); if (update_cf) { util_clf_chroma_interpolate(&p_cf[1], &p_cf[0], p_cf_new, ratio); mod->old_streaming_mode = in_params->cfg.streaming_mode; mod->cur_cf_aec_ratio = ratio; mod->cf_update = TRUE; } return status; } /* clf_chroma_trigger_update */
/*=========================================================================== * FUNCTION - vfe_chroma_suppresion_trigger_update - * * DESCRIPTION: *==========================================================================*/ vfe_status_t vfe_chroma_suppresion_trigger_update(int mod_id, void *mod_csupp, void *parms) { float lux_idx, ratio; int Diff, Q_slope; tuning_control_type *tc; trigger_point_type *tp; cs_luma_threshold_type *cs_luma_threshold, *cs_luma_threshold_lowlight; VFE_ChromaSuppress_ConfigCmdType *chroma_supp_cmd; uint8_t update_cs = FALSE; chroma_supp_mod_t *mod = (chroma_supp_mod_t *)mod_csupp; vfe_params_t *p_obj = (vfe_params_t *)parms; tc = &(p_obj->chroma3a->control_cs); if (!mod->chroma_supp_enable) { CDBG("%s: Chroma Suppression not enabled", __func__); return VFE_SUCCESS; } if (!mod->chroma_supp_trigger) { CDBG("%s: Chroma Suppression trigger not enabled", __func__); return VFE_SUCCESS; } switch (p_obj->vfe_op_mode) { case VFE_OP_MODE_PREVIEW: case VFE_OP_MODE_VIDEO: case VFE_OP_MODE_ZSL: tp = &(p_obj->chroma3a->cs_lowlight_trigger); cs_luma_threshold = &(p_obj->chroma3a->cs_luma_threshold); cs_luma_threshold_lowlight = &(p_obj->chroma3a->cs_luma_threshold_lowlight); chroma_supp_cmd = &(mod->chroma_supp_video_cmd); break; case VFE_OP_MODE_SNAPSHOT: case VFE_OP_MODE_JPEG_SNAPSHOT: tp = &(p_obj->chroma3a->cs_snapshot_lowlight_trigger); cs_luma_threshold = &(p_obj->chroma3a->cs_luma_threshold_snapshot); cs_luma_threshold_lowlight = &(p_obj->chroma3a->cs_luma_threshold_snapshot_lowlight); chroma_supp_cmd = &(mod->chroma_supp_snap_cmd); break; default: CDBG_ERROR("%s, invalid mode = %d",__func__, p_obj->vfe_op_mode); return VFE_ERROR_GENERAL; } ratio = vfe_util_get_aec_ratio(*tc, tp, p_obj); if (ratio > 1.0) ratio = 1.0; else if (ratio < 0.0) ratio = 0.0; update_cs = ((mod->prev_mode != p_obj->vfe_op_mode) || !F_EQUAL(mod->prev_aec_ratio, ratio)); CDBG("%s: update_cs : %d\n", __func__, update_cs); if (!update_cs) { CDBG("%s: Chroma Suppression update not required", __func__); return VFE_SUCCESS; } mod->prev_mode = p_obj->vfe_op_mode; mod->prev_aec_ratio = ratio; /* luma threshold */ chroma_supp_cmd->ySup1 = LINEAR_INTERPOLATION_INT(cs_luma_threshold-> cs_luma_threshold1, cs_luma_threshold_lowlight->cs_luma_threshold1, ratio); chroma_supp_cmd->ySup2 = LINEAR_INTERPOLATION_INT(cs_luma_threshold-> cs_luma_threshold2, cs_luma_threshold_lowlight->cs_luma_threshold2, ratio); Diff = chroma_supp_cmd->ySup2 - chroma_supp_cmd->ySup1; Diff = Clamp(Diff, 4, 127); chroma_supp_cmd->ySup2 = chroma_supp_cmd->ySup1 + Diff; Q_slope = (int)ceil(log((double)Diff) / log(2.0)) + 6; chroma_supp_cmd->ySupM1 = (1 << Q_slope) / Diff; chroma_supp_cmd->ySupS1 = Q_slope - 7; chroma_supp_cmd->ySup3 = LINEAR_INTERPOLATION_INT(cs_luma_threshold-> cs_luma_threshold3, cs_luma_threshold_lowlight->cs_luma_threshold3, ratio); chroma_supp_cmd->ySup4 = LINEAR_INTERPOLATION_INT(cs_luma_threshold-> cs_luma_threshold4, cs_luma_threshold_lowlight->cs_luma_threshold4, ratio); Diff = chroma_supp_cmd->ySup4 - chroma_supp_cmd->ySup3; Diff = Clamp(Diff, 4, 127); chroma_supp_cmd->ySup3 = chroma_supp_cmd->ySup4 - Diff; Q_slope = (int)ceil(log((double)Diff) / log(2.0)) + 6; chroma_supp_cmd->ySupM3 = (1 << Q_slope) / Diff; chroma_supp_cmd->ySupS3 = Q_slope - 7; /* chroma threshold */ chroma_supp_cmd->cSup1 = LINEAR_INTERPOLATION_INT(cs_luma_threshold-> cs_chroma_threshold1, cs_luma_threshold_lowlight->cs_chroma_threshold1, ratio); chroma_supp_cmd->cSup2 = LINEAR_INTERPOLATION_INT(cs_luma_threshold-> cs_chroma_threshold2, cs_luma_threshold_lowlight->cs_chroma_threshold2, ratio); Diff = chroma_supp_cmd->cSup2 - chroma_supp_cmd->cSup1; Diff = Clamp(Diff, 4, 127); chroma_supp_cmd->cSup2 = chroma_supp_cmd->cSup1 + Diff; Q_slope = (int)ceil(log((double)Diff) / log(2.0)) + 6; chroma_supp_cmd->cSupM1 = (1 << Q_slope) / Diff; chroma_supp_cmd->cSupS1 = Q_slope - 7; mod->chroma_supp_update = TRUE; return VFE_SUCCESS; } /* vfe_trigger_update_chroma_suppresion */
/** demux_trigger_update: * @demux_mod: demux module instance * @trigger_params: module trigger update params * @in_param_size: enable parameter size * * This function runs in ISP HW thread context. * * This function checks and initiates triger update of module * * Return: 0 - Success * -1 - Parameters size mismatch **/ static int demux_trigger_update(isp_demux_mod_t *demux_mod, isp_pix_trigger_update_input_t *trigger_params, uint32_t in_param_size) { isp_hw_pix_setting_params_t *pix_setting = &trigger_params->cfg; chromatix_parms_type *chromatix_ptr = pix_setting->chromatix_ptrs.chromatixPtr; chromatix_channel_balance_gains_type *chromatix_channel_balance_gains = &chromatix_ptr->chromatix_VFE.chromatix_channel_balance_gains; AEC_algo_struct_type *AEC_algo_data = &chromatix_ptr->AEC_algo_data; ISP_DemuxConfigCmdType* p_cmd = &demux_mod->ISP_DemuxConfigCmd; float max_gain = 0.0, gain = 0.0, new_dig_gain = 1.0; float max_ch_gain = 0.0; demux_mod->remaining_digital_gain = 1.0; /* set to unitity */ if(!demux_mod->enable || !demux_mod->trigger_enable) { ISP_DBG(ISP_MOD_DEMUX, "%s: no trigger update for DEMUX, trigger_enable = %d, enable =%d\n", __func__, demux_mod->enable, demux_mod->trigger_enable); return 0; } ISP_DBG(ISP_MOD_DEMUX, "%s: dig gain %5.3f", __func__, trigger_params->trigger_input.digital_gain); if (trigger_params->trigger_input.digital_gain < 1.0) trigger_params->trigger_input.digital_gain = 1.0; max_ch_gain = MAX(chromatix_channel_balance_gains->green_odd, MAX(chromatix_channel_balance_gains->green_even, MAX(chromatix_channel_balance_gains->red, chromatix_channel_balance_gains->blue))); ISP_DBG(ISP_MOD_DEMUX, "%s: max_ch_gain %5.3f glob %5.3f", __func__, max_ch_gain, AEC_algo_data->color_correction_global_gain); max_gain = max_ch_gain * AEC_algo_data->color_correction_global_gain * trigger_params->trigger_input.digital_gain; ISP_DBG(ISP_MOD_DEMUX, "%s: max_gain_final %5.3f", __func__, max_gain); if (max_gain > MAX_DEMUX_GAIN) { new_dig_gain = MAX_DEMUX_GAIN/ (AEC_algo_data->color_correction_global_gain * max_ch_gain); demux_mod->remaining_digital_gain = max_gain/MAX_DEMUX_GAIN; } else { new_dig_gain = max_gain/ (AEC_algo_data->color_correction_global_gain * max_ch_gain); } ISP_DBG(ISP_MOD_DEMUX, "%s: dig_gain_old %5.3f new %5.3f", __func__, demux_mod->dig_gain, new_dig_gain); if (F_EQUAL(demux_mod->dig_gain, new_dig_gain) && (pix_setting->streaming_mode == demux_mod->old_streaming_mode)) { ISP_DBG(ISP_MOD_DEMUX, "%s: No update required", __func__); return 0; } demux_mod->old_streaming_mode = pix_setting->streaming_mode; demux_mod->dig_gain = new_dig_gain; gain = AEC_algo_data->color_correction_global_gain * demux_mod->dig_gain; demux_mod->gain.green_odd = gain * chromatix_channel_balance_gains->green_odd; demux_mod->gain.green_even = gain * chromatix_channel_balance_gains->green_even; demux_mod->gain.red = gain * chromatix_channel_balance_gains->red; demux_mod->gain.blue = gain * chromatix_channel_balance_gains->blue; p_cmd->ch0EvenGain = DEMUX_GAIN(demux_mod->gain.green_even); p_cmd->ch0OddGain = DEMUX_GAIN(demux_mod->gain.green_odd); p_cmd->ch1Gain = DEMUX_GAIN(demux_mod->gain.blue); p_cmd->ch2Gain = DEMUX_GAIN(demux_mod->gain.red); /* 3D is not supported. */ if (demux_mod->is_3d) demux_r_image_gain_update(demux_mod); demux_mod->hw_update_pending = TRUE; return 0; }/*demux_trigger_update*/
/** color_conversion_trigger_update: * * @mod: * @in_params: * @in_param_size: * * enable color_conversion trigger update feature * **/ static int color_conversion_trigger_update(isp_color_conversion_mod_t *mod, isp_pix_trigger_update_input_t *in_params, uint32_t in_param_size) { int rc = 0; chromatix_parms_type *chromatix_ptr = in_params->cfg.chromatix_ptrs.chromatixPtr; chromatix_CV_type *chromatix_CV_ptr = &chromatix_ptr->chromatix_VFE.chromatix_CV; chromatix_gamma_type *chromatix_gamma = &(chromatix_ptr->chromatix_VFE.chromatix_gamma); int8_t update_cv = FALSE; aec_update_t *aec_params = &(in_params->trigger_input.stats_update.aec_update); trigger_ratio_t trigger_ratio; int is_burst = IS_BURST_STREAMING(&in_params->cfg); if (in_param_size != sizeof(isp_pix_trigger_update_input_t)) { /* size mismatch */ CDBG_ERROR("%s: size mismatch, expecting = %d, received = %d", __func__, sizeof(isp_pix_trigger_update_input_t), in_param_size); return -1; } if (!mod->enable || !isp_util_aec_check_settled(aec_params) || !mod->trigger_enable || in_params->trigger_input.stats_update.awb_update.color_temp == 0) { ISP_DBG(ISP_MOD_COLOR_CONV, "%s: CV no trigger update required, enable = %d," "trigger_enable = %d, aec_settled? %d\n", __func__, mod->enable, mod->trigger_enable, isp_util_aec_check_settled(aec_params)); return 0; } /* Decide the trigger ratio for current lighting condition */ rc = isp_util_get_aec_ratio2(mod->notify_ops->parent, chromatix_CV_ptr->control_cv, &(chromatix_gamma->gamma_outdoor_trigger), &(chromatix_CV_ptr->cv_trigger), aec_params, is_burst, &trigger_ratio); if (rc != 0) CDBG_ERROR("%s: get aec ratio error", __func__); update_cv = ((mod->old_streaming_mode != in_params->cfg.streaming_mode) || !F_EQUAL(trigger_ratio.ratio, mod->aec_ratio.ratio) || (trigger_ratio.lighting != mod->aec_ratio.lighting) || (mod->color_temp != in_params->trigger_input.stats_update.awb_update.color_temp)); ISP_DBG(ISP_MOD_COLOR_CONV, "%s: update_cv %d ratio %f lighting %d colortemp %u", __func__, update_cv, trigger_ratio.ratio, trigger_ratio.lighting, in_params->trigger_input.stats_update.awb_update.color_temp); if (update_cv) { mod->cv_data = *(mod->p_cv); if(!IS_MANUAL_WB(in_params) && !F_EQUAL(trigger_ratio.ratio, 0.0)) util_color_conversion_awb_update(mod, in_params, &mod->cv_data); util_color_conversion_aec_update(mod, in_params, &mod->cv_data, &trigger_ratio); mod->aec_ratio = trigger_ratio; mod->color_temp = in_params->trigger_input.stats_update.awb_update.color_temp; mod->old_streaming_mode = in_params->cfg.streaming_mode; } util_color_conversion_cmd_config(mod); mod->hw_update_pending = TRUE; return 0; } /* color_conversion_trigger_update */
/** bpc_trigger_update * @mod: bpc module control struct * @in_params: input config params including chromatix ptr * @in_param_size: input params struct size * * BPC module modify reg settings as per new input params and * trigger hw update * * Return: 0 - success and negative value - failure **/ static int bpc_trigger_update(isp_bpc_mod_t *mod, isp_pix_trigger_update_input_t *in_params, uint32_t in_param_size) { int rc = 0; chromatix_parms_type *chromatix_ptr = in_params->cfg.chromatix_ptrs.chromatixPtr; chromatix_BPC_type *chromatix_BPC = &chromatix_ptr->chromatix_VFE.chromatix_BPC; chromatix_CS_MCE_type *chromatix_CS_MCE = &chromatix_ptr->chromatix_VFE.chromatix_CS_MCE; float aec_ratio; uint8_t update_bpc = TRUE; uint8_t Fmin, Fmin_lowlight, Fmax, Fmax_lowlight; tuning_control_type tunning_control; bpc_4_offset_type *bpc_normal_input_offset = NULL; bpc_4_offset_type *bpc_lowlight_input_offset = NULL; trigger_point_type *trigger_point = NULL; int is_snapmode, update_cs; if (in_param_size != sizeof(isp_pix_trigger_update_input_t)) { /* size mismatch */ CDBG_ERROR("%s: size mismatch, expecting = %d, received = %d", __func__, sizeof(isp_pix_trigger_update_input_t), in_param_size); return -1; } if (!mod->enable || !mod->trigger_enable || mod->skip_trigger) { ISP_DBG(ISP_MOD_BPC, "%s: Skip Trigger update. enable %d, trig_enable %d, skip_trigger %d", __func__, mod->enable, mod->trigger_enable, mod->skip_trigger); return rc; } is_snapmode = IS_BURST_STREAMING(&in_params->cfg); if (!is_snapmode && !isp_util_aec_check_settled( &(in_params->trigger_input.stats_update.aec_update))) { ISP_DBG(ISP_MOD_BPC, "%s: AEC not settled", __func__); return rc; } ISP_DBG(ISP_MOD_BPC, "%s: Calculate table with AEC", __func__); if ((chromatix_BPC->bpc_Fmin > chromatix_BPC->bpc_Fmax) || (chromatix_BPC->bpc_Fmin_lowlight > chromatix_BPC->bpc_Fmax_lowlight)) { CDBG_ERROR("%s: Error min>max: %d/%d; %d/%d\n", __func__, chromatix_BPC->bpc_Fmin, chromatix_BPC->bpc_Fmax, chromatix_BPC->bpc_Fmin_lowlight, chromatix_BPC->bpc_Fmax_lowlight); return -1; } trigger_point = &(chromatix_BPC->bpc_lowlight_trigger); Fmin = chromatix_BPC->bpc_Fmin; Fmax = chromatix_BPC->bpc_Fmax; Fmin_lowlight = chromatix_BPC->bpc_Fmin_lowlight; Fmax_lowlight = chromatix_BPC->bpc_Fmax_lowlight; bpc_normal_input_offset = &(chromatix_BPC->bpc_4_offset[BPC_NORMAL_LIGHT]); bpc_lowlight_input_offset = &(chromatix_BPC->bpc_4_offset[BPC_LOW_LIGHT]); tunning_control = chromatix_BPC->control_bpc; aec_ratio = isp_util_get_aec_ratio(mod->notify_ops->parent, chromatix_BPC->control_bpc, trigger_point, &(in_params->trigger_input.stats_update.aec_update), is_snapmode); update_cs = ((mod->old_streaming_mode != in_params->cfg.streaming_mode) || !F_EQUAL(mod->aec_ratio, aec_ratio)); if (!update_cs) { ISP_DBG(ISP_MOD_BPC, "%s: update not required", __func__); return 0; } if (F_EQUAL(aec_ratio, 0.0)) { ISP_DBG(ISP_MOD_BPC, "%s: Low Light \n", __func__); mod->p_params.p_input_offset = bpc_lowlight_input_offset; mod->p_params.p_Fmin = &(Fmin_lowlight); mod->p_params.p_Fmax = &(Fmax_lowlight); util_bpc_cmd_config(mod); } else if (F_EQUAL(aec_ratio, 1.0)) { ISP_DBG(ISP_MOD_BPC, "%s: Normal Light \n", __func__); mod->p_params.p_input_offset = bpc_normal_input_offset; mod->p_params.p_Fmin = &(Fmin); mod->p_params.p_Fmax = &(Fmax); util_bpc_cmd_config(mod); } else { ISP_DBG(ISP_MOD_BPC, "%s: Interpolate between Nomal and Low Light \n", __func__); /* Directly configure reg cmd.*/ Fmin = (uint8_t)Round(LINEAR_INTERPOLATION(Fmin, Fmin_lowlight, aec_ratio)); mod->RegCmd.fminThreshold = Fmin; Fmax = (uint8_t)Round(LINEAR_INTERPOLATION(Fmax, Fmax_lowlight, aec_ratio)); mod->RegCmd.fmaxThreshold = Fmax; mod->RegCmd.rOffsetHi = (uint16_t)Round(LINEAR_INTERPOLATION( bpc_normal_input_offset->bpc_4_offset_r_hi, bpc_lowlight_input_offset->bpc_4_offset_r_hi, aec_ratio)); mod->RegCmd.rOffsetLo = (uint16_t)Round(LINEAR_INTERPOLATION( bpc_normal_input_offset->bpc_4_offset_r_lo, bpc_lowlight_input_offset->bpc_4_offset_r_lo, aec_ratio)); mod->RegCmd.bOffsetHi = (uint16_t)Round(LINEAR_INTERPOLATION( bpc_normal_input_offset->bpc_4_offset_b_hi, bpc_lowlight_input_offset->bpc_4_offset_b_hi, aec_ratio)); mod->RegCmd.bOffsetLo = (uint16_t)Round(LINEAR_INTERPOLATION( bpc_normal_input_offset->bpc_4_offset_b_lo, bpc_lowlight_input_offset->bpc_4_offset_b_lo, aec_ratio)); mod->RegCmd.grOffsetHi = (uint16_t)Round(LINEAR_INTERPOLATION( bpc_normal_input_offset->bpc_4_offset_gr_hi, bpc_lowlight_input_offset->bpc_4_offset_gr_hi, aec_ratio)); mod->RegCmd.grOffsetLo = (uint16_t)Round(LINEAR_INTERPOLATION( bpc_normal_input_offset->bpc_4_offset_gr_lo, bpc_lowlight_input_offset->bpc_4_offset_gr_lo, aec_ratio)); mod->RegCmd.gbOffsetHi = (uint16_t)Round(LINEAR_INTERPOLATION( bpc_normal_input_offset->bpc_4_offset_gb_hi, bpc_lowlight_input_offset->bpc_4_offset_gb_hi, aec_ratio)); mod->RegCmd.gbOffsetLo = (uint16_t)Round(LINEAR_INTERPOLATION( bpc_normal_input_offset->bpc_4_offset_gb_lo, bpc_lowlight_input_offset->bpc_4_offset_gb_lo, aec_ratio)); } mod->aec_ratio = aec_ratio; util_bpc_cmd_debug(&(mod->RegCmd)); mod->hw_update_pending = TRUE; return rc; } /* bpc_trigger_update */
/** abf_trigger_update: * @mod: pointer to instance private data * @trigger_params: input data * @in_params_size: size of input data * * Update configuration. * * This function executes in ISP thread context * * Return 0 on success. **/ static int abf_trigger_update(isp_abf_mod_t *mod, isp_pix_trigger_update_input_t *trigger_params, uint32_t in_param_size) { int i = 0; chromatix_parms_type *chroma_ptr = trigger_params->cfg.chromatix_ptrs.chromatixPtr; chromatix_ABF2_type *chromatix_ABF2 = &chroma_ptr->chromatix_VFE.chromatix_ABF2; abf2_parms_t *abf2_parms = &(mod->abf2_parms); trigger_point_type *outdoor = NULL, *lowlight = NULL; trigger_ratio_t trigger_ratio; chromatix_adaptive_bayer_filter_data_type2 *p1 = NULL, *p2 = NULL, *abf2_normal, *abf2_outdoor, *abf2_lowlight; tuning_control_type tunning_control = chromatix_ABF2->control_abf2; uint8_t is_burst = IS_BURST_STREAMING((&trigger_params->cfg)); if (!mod->enable || !mod->trigger_enable) { ISP_DBG(ISP_MOD_ABF, "%s: no trigger for ABF, enable = %d, trigger_ena = %d\n", __func__, mod->enable, mod->trigger_enable); return 0; } if (!isp_util_aec_check_settled( &trigger_params->trigger_input.stats_update.aec_update)) { ISP_DBG(ISP_MOD_ABF, "%s: AEC not settled", __func__); return 0; } outdoor = &(chromatix_ABF2->abf2_bright_light_trigger); lowlight = &(chromatix_ABF2->abf2_low_light_trigger); abf2_normal = &(chromatix_ABF2->abf2_config_normal_light); abf2_outdoor = &(chromatix_ABF2->abf2_config_bright_light); abf2_lowlight = &(chromatix_ABF2->abf2_config_low_light); /* Decide the trigger ratio for current lighting condition */ if (isp_util_get_aec_ratio2(mod->notify_ops->parent, tunning_control, outdoor, lowlight, &trigger_params->trigger_input.stats_update.aec_update, is_burst, &trigger_ratio) != 0) { CDBG_HIGH("%s: get aec ratio error", __func__); return -1; } switch (trigger_ratio.lighting) { case TRIGGER_LOWLIGHT: { p1 = abf2_lowlight; p2 = abf2_normal; } break; case TRIGGER_OUTDOOR: { p1 = abf2_outdoor; p2 = abf2_normal; } break; default: case TRIGGER_NORMAL: { p1 = p2 = abf2_normal; } break; } if ((trigger_params->cfg.streaming_mode != mod->old_streaming_mode) || (trigger_ratio.lighting != mod->aec_ratio.lighting) || !F_EQUAL(trigger_ratio.ratio, mod->aec_ratio.ratio)) { /* Update abf2 */ mod->hw_update_pending = 1; mod->old_streaming_mode = trigger_params->cfg.streaming_mode; mod->aec_ratio = trigger_ratio; if (!F_EQUAL(trigger_ratio.ratio, 0.0) && !F_EQUAL(trigger_ratio.ratio, 1.0)) { abf_interpolate(p2, p1, abf2_parms, trigger_ratio.ratio); } else { memcpy(&abf2_parms->data, p1, sizeof(chromatix_adaptive_bayer_filter_data_type2)); } abf_set_cmd_params2(&mod->RegCmd, abf2_parms); } return 0; } /* abf_trigger_update */
/** mce_trigger_update: * @mce_mod: pointer to instance private data * @trigger_params: input data * @in_params_size: size of input data * * Update configuration. * * This function executes in ISP thread context * * Return 0 on success. **/ static int mce_trigger_update(isp_mce_mod_t *mce_mod, isp_pix_trigger_update_input_t *trigger_params, uint32_t in_param_size) { float ratio, fKg, fKb, fKr, max_boost; uint32_t dS1, dS3, QKg, QKb, QKr, Q_s1, Q_s3; ISP_MCE_ConfigCmdType *mce_config = &(mce_mod->mce_cmd); chromatix_parms_type *chromatix_ptr = trigger_params->cfg.chromatix_ptrs.chromatixPtr; chromatix_CS_MCE_type *pchromatix_CS_MCE = &chromatix_ptr->chromatix_VFE.chromatix_CS_MCE; ASD_struct_type *ASD_algo_data_ptr = &chromatix_ptr->ASD_algo_data; float landscape_green_boost_factor = ASD_algo_data_ptr->landscape_scene_detect.landscape_green_boost_factor; float landscape_blue_boost_factor = ASD_algo_data_ptr->landscape_scene_detect.landscape_blue_boost_factor; float landscape_red_boost_factor = ASD_algo_data_ptr->landscape_scene_detect.landscape_red_boost_factor; uint32_t landscape_severity = 0; float lux_idx; uint8_t update_mce = FALSE; if (in_param_size != sizeof(isp_pix_trigger_update_input_t)) { /* size mismatch */ CDBG_ERROR("%s: size mismatch, expecting = %d, received = %d", __func__, sizeof(isp_pix_trigger_update_input_t), in_param_size); return -1; } lux_idx = trigger_params->trigger_input.stats_update.aec_update.lux_idx; /* check for trigger updation */ update_mce = ((mce_mod->old_streaming_mode!= trigger_params->cfg.streaming_mode) || !F_EQUAL(mce_mod->prev_lux_idx, lux_idx)); if (!update_mce) { ISP_DBG(ISP_MOD_MCE, "%s: MCE update not required", __func__); return 0; } else { mce_mod->prev_lux_idx = lux_idx; mce_mod->old_streaming_mode = trigger_params->cfg.streaming_mode; } if (!mce_mod->mce_enable) { ISP_DBG(ISP_MOD_MCE, "%s: MCE not enabled", __func__); return 0; } if (mce_mod->mce_trigger_enable != TRUE) { ISP_DBG(ISP_MOD_MCE, "%s: MCE trigger not enabled\n", __func__); return 0; } if (!isp_util_aec_check_settled( &trigger_params->trigger_input.stats_update.aec_update)) { ISP_DBG(ISP_MOD_MCE, "%s: AEC not settled", __func__); return 0; } if (trigger_params->cfg.bestshot_mode == CAM_SCENE_MODE_LANDSCAPE) landscape_severity = 255; // 100 % severity else landscape_severity = MIN(255, trigger_params->trigger_input.stats_update.asd_update.landscape_severity); /* Compute MCE gains and Q_K first */ /* Green */ ratio = 1.0f - isp_util_calc_interpolation_weight(lux_idx, pchromatix_CS_MCE->mce_config.green_bright_index, pchromatix_CS_MCE->mce_config.green_dark_index); ISP_DBG(ISP_MOD_MCE, "ratio = %f, lux_idx %f\n", ratio, lux_idx); fKg = ratio * (pchromatix_CS_MCE->mce_config.green_boost_factor - 1.0f); /*add ratio for landscape severity */ ISP_DBG(ISP_MOD_MCE, "pre fKg =%f", fKg); fKg = ((fKg + 1) * (((float)landscape_severity / 255.0 * (landscape_green_boost_factor - 1)) + 1)); max_boost = MAX(pchromatix_CS_MCE->mce_config.green_boost_factor, landscape_green_boost_factor); if (fKg > max_boost) fKg = max_boost; fKg = fKg - 1; ISP_DBG(ISP_MOD_MCE, "post fKg =%f", fKg); if (fKg > 0) { QKg = (uint8_t)ceil(log(4.0f / fKg) / log(2.0f)) + 6; while ((int32_t)(fKg * (1 << QKg)) > 383) QKg--; } else { fKg = 0; QKg = 15; } QKg = Clamp(QKg, 7, 15); /* Blue */ ratio = 1.0f - isp_util_calc_interpolation_weight(lux_idx, pchromatix_CS_MCE->mce_config.blue_bright_index, pchromatix_CS_MCE->mce_config.blue_dark_index); fKb = ratio * (pchromatix_CS_MCE->mce_config.blue_boost_factor - 1.0f); /*add ratio for landscape severity */ ISP_DBG(ISP_MOD_MCE, "pre fKb =%f", fKb); fKb = ((fKb + 1) * (((float)landscape_severity / 255.0 * (landscape_blue_boost_factor - 1)) + 1)); max_boost = MAX(pchromatix_CS_MCE->mce_config.blue_boost_factor, landscape_blue_boost_factor); if (fKb > max_boost) fKb = max_boost; fKb = fKb - 1; ISP_DBG(ISP_MOD_MCE, "post fKb =%f", fKb); if (fKb > 0) { QKb = (uint8_t)ceil(log(4.0f / fKb) / log(2.0f)) + 6; while ((int32_t)(fKb * (1 << QKb)) > 383) QKb--; } else { fKb = 0; QKb = 15; } QKb = Clamp(QKb, 7, 15); /* Red */ ratio = 1.0f - isp_util_calc_interpolation_weight(lux_idx, pchromatix_CS_MCE->mce_config.red_bright_index, pchromatix_CS_MCE->mce_config.red_dark_index); fKr = ratio * (pchromatix_CS_MCE->mce_config.red_boost_factor - 1.0f); ISP_DBG(ISP_MOD_MCE, "pre fKr =%f", fKr); /* add ratio for landscape severity */ fKr = ((fKr + 1) * (((float)landscape_severity / 255.0 * (landscape_red_boost_factor - 1)) + 1)); max_boost = MAX(pchromatix_CS_MCE->mce_config.red_boost_factor, landscape_red_boost_factor); if (fKr > max_boost) fKr = max_boost; fKr = fKr - 1; ISP_DBG(ISP_MOD_MCE, "post fKr =%f", fKr); if (fKr > 0) { QKr = (uint8_t)ceil(log(4.0f / fKr) / log(2.0f)) + 6; while ((int32_t)(fKr * (1 << QKr)) > 383) QKr--; } else { fKr = 0; QKr = 15; } QKr = Clamp(QKr, 7, 15); mce_mod->mce_mix_cmd_1.enable = mce_mod->mce_enable; /* Overall Q_K and gains */ mce_mod->mce_mix_cmd_2.qk = MIN(MIN(QKg, QKb), QKr); mce_config->redCfg.K = (int32_t)(fKr * (1 << mce_mod->mce_mix_cmd_2.qk)); mce_config->greenCfg.K = (int32_t)(fKg * (1 << mce_mod->mce_mix_cmd_2.qk)); mce_config->blueCfg.K = (int32_t)(fKb * (1 << mce_mod->mce_mix_cmd_2.qk)); /* Compute Y slopes */ /* Green */ dS1 = mce_config->greenCfg.y2 - mce_config->greenCfg.y1; dS3 = mce_config->greenCfg.y4 - mce_config->greenCfg.y3; if ((fKg > 0) && (dS1 > 0)) { Q_s1 = (int32_t)ceil(log(dS1 / fKg) / log(2.0f)) + 6; Q_s1 = Clamp(Q_s1, 7, 20); mce_config->greenCfg.yM1 = mce_config->greenCfg.K * (1 << (Q_s1 - mce_mod->mce_mix_cmd_2.qk)) / dS1; } else { Q_s1 = 20; mce_config->greenCfg.yM1 = 0; } mce_config->greenCfg.yS1 = Q_s1 - mce_mod->mce_mix_cmd_2.qk; if ((fKg > 0) && (dS3 > 0)) { Q_s3 = (int32_t)ceil(log(dS3 / fKg) / log(2.0f)) + 6; Q_s3 = Clamp(Q_s3, 7, 20); mce_config->greenCfg.yM3 = mce_config->greenCfg.K * (1 << (Q_s3 - mce_mod->mce_mix_cmd_2.qk)) / dS3; } else { Q_s3 = 20; mce_config->greenCfg.yM3 = 0; } mce_config->greenCfg.yS3 = Q_s3 - mce_mod->mce_mix_cmd_2.qk; /* Blue */ dS1 = mce_config->blueCfg.y2 - mce_config->blueCfg.y1; dS3 = mce_config->blueCfg.y4 - mce_config->blueCfg.y3; if ((fKb > 0) && (dS1 > 0)) { Q_s1 = (int32_t)ceil(log(dS1 / fKb) / log(2.0f)) + 6; Q_s1 = Clamp(Q_s1, 7, 20); mce_config->blueCfg.yM1 = mce_config->blueCfg.K * (1 << (Q_s1 - mce_mod->mce_mix_cmd_2.qk)) / dS1; } else { Q_s1 = 20; mce_config->blueCfg.yM1 = 0; } mce_config->blueCfg.yS1 = Q_s1 - mce_mod->mce_mix_cmd_2.qk; if ((fKb > 0) && (dS3 > 0)) { Q_s3 = (int32_t)ceil(log(dS3 / fKb) / log(2.0f)) + 6; Q_s3 = Clamp(Q_s3, 7, 20); mce_config->blueCfg.yM3 = mce_config->blueCfg.K * (1 << (Q_s3 - mce_mod->mce_mix_cmd_2.qk)) / dS3; } else { Q_s3 = 20; mce_config->blueCfg.yM3 = 0; } mce_config->blueCfg.yS3 = Q_s3 - mce_mod->mce_mix_cmd_2.qk; /* Red */ dS1 = mce_config->redCfg.y2 - mce_config->redCfg.y1; dS3 = mce_config->redCfg.y4 - mce_config->redCfg.y3; if ((fKr > 0) && (dS1 > 0)) { Q_s1 = (int32_t)ceil(log(dS1 / fKr) / log(2.0f)) + 6; Q_s1 = Clamp(Q_s1, 7, 20); mce_config->redCfg.yM1 = mce_config->redCfg.K * (1 << (Q_s1 - mce_mod->mce_mix_cmd_2.qk)) / dS1; } else { Q_s1 = 20; mce_config->redCfg.yM1 = 0; } mce_config->redCfg.yS1 = Q_s1 - mce_mod->mce_mix_cmd_2.qk; if ((fKr > 0) && (dS3 > 0)) { Q_s3 = (int32_t)ceil(log(dS3 / fKr) / log(2.0f)) + 6; Q_s3 = Clamp(Q_s3, 7, 20); mce_config->redCfg.yM3 = mce_config->redCfg.K * (1 << (Q_s3 - mce_mod->mce_mix_cmd_2.qk)) / dS3; } else { Q_s3 = 20; mce_config->redCfg.yM3 = 0; } mce_config->redCfg.yS3 = Q_s3 - mce_mod->mce_mix_cmd_2.qk; /* Compute C slopes */ /* Green */ mce_config->greenCfg.CBZone = pchromatix_CS_MCE->mce_config.green_cb_boundary; mce_config->greenCfg.CRZone = pchromatix_CS_MCE->mce_config.green_cr_boundary; mce_config->greenCfg.transWidth = (pchromatix_CS_MCE->mce_config.green_cb_transition_width + pchromatix_CS_MCE->mce_config.green_cr_transition_width) / 2; mce_config->greenCfg.transTrunc = (int32_t)ceil(log((float)( mce_config->greenCfg.transWidth)) / log(2.0f) ) + 4; mce_config->greenCfg.transTrunc = Clamp(mce_config->greenCfg.transTrunc, 6, 9); mce_config->greenCfg.transSlope = (1 << mce_config->greenCfg.transTrunc) / mce_config->greenCfg.transWidth; /* Blue */ mce_config->blueCfg.CBZone = pchromatix_CS_MCE->mce_config.blue_cb_boundary; mce_config->blueCfg.CRZone = pchromatix_CS_MCE->mce_config.blue_cr_boundary; mce_config->blueCfg.transWidth = (pchromatix_CS_MCE->mce_config.blue_cb_transition_width + pchromatix_CS_MCE->mce_config.blue_cr_transition_width) / 2; mce_config->blueCfg.transTrunc = (int32_t)ceil(log((float)( mce_config->blueCfg.transWidth)) / log(2.0f)) + 4; mce_config->blueCfg.transTrunc = Clamp(mce_config->blueCfg.transTrunc, 6, 9); mce_config->blueCfg.transSlope = (1 << mce_config->blueCfg.transTrunc) / mce_config->blueCfg.transWidth; /* Red */ mce_config->redCfg.CBZone = pchromatix_CS_MCE->mce_config.red_cb_boundary; mce_config->redCfg.CRZone = pchromatix_CS_MCE->mce_config.red_cr_boundary; mce_config->redCfg.transWidth = (pchromatix_CS_MCE->mce_config.red_cb_transition_width + pchromatix_CS_MCE->mce_config.red_cr_transition_width) / 2; mce_config->redCfg.transTrunc = (int32_t)ceil(log((float)( mce_config->redCfg.transWidth)) / log(2.0f)) + 4; mce_config->redCfg.transTrunc = Clamp(mce_config->redCfg.transTrunc, 6, 9); mce_config->redCfg.transSlope = (1 << mce_config->redCfg.transTrunc) / mce_config->redCfg.transWidth; mce_mod->mce_update = TRUE; if (mce_mod->cnt == 0) { ISP_DBG(ISP_MOD_MCE, "MCE_landscape_severity = %d\n", landscape_severity); ISP_DBG(ISP_MOD_MCE, "MCE aec ratio = %f, aec_out->lux_idx %f\n", ratio, lux_idx); mce_mod->hw_update_pending = TRUE; } mce_mod->cnt++; if (mce_mod->cnt == 6) mce_mod->cnt = 0; return 0; } /* mce_trigger_update */
/** clf_luma_trigger_update: * @mod: CLF module instance * @in_params: triger update data * @in_param_size: update data size * * This function runs in ISP HW thread context. * * This function updates parametes and sets flag for hw update if needed * for luma filtering * * Return: 0 - Success * Otherwise - get AEC ratio failed **/ static int clf_luma_trigger_update(isp_clf_mod_t *mod, isp_pix_trigger_update_input_t *in_params, uint32_t in_param_size) { trigger_point_type *p_trigger_low = NULL, *p_trigger_bright = NULL; int8_t is_burst = IS_BURST_STREAMING(&(in_params->cfg)); tuning_control_type tuning_type; int8_t update_lf = FALSE; float ratio; trigger_ratio_t trig_ratio; chromatix_parms_type *chroma_ptr = (chromatix_parms_type *)in_params->cfg.chromatix_ptrs.chromatixPtr; chromatix_ABF2_type *chromatix_ABF2 = &chroma_ptr->chromatix_VFE.chromatix_ABF2; int8_t lf_enabled = mod->lf_enable && mod->lf_enable_trig; int status = 0; if (!lf_enabled) { ISP_DBG(ISP_MOD_CLF, "%s: Luma filter trigger not enabled %d %d", __func__, mod->lf_enable, mod->lf_enable_trig); return status; } chromatix_adaptive_bayer_filter_data_type2 *p_lf_new = &(mod->clf_params.lf_param); chromatix_adaptive_bayer_filter_data_type2 *p_lf1 = NULL, *p_lf2 = NULL; mod->lf_update = FALSE; tuning_type = chromatix_ABF2->control_abf2; p_trigger_low = &chromatix_ABF2->abf2_low_light_trigger; p_trigger_bright = &chromatix_ABF2->abf2_bright_light_trigger; status = isp_util_get_aec_ratio2(mod->notify_ops->parent, tuning_type, p_trigger_bright, p_trigger_low, &(in_params->trigger_input.stats_update.aec_update), is_burst, &trig_ratio); if (status != 0) CDBG_HIGH("%s: get aec ratio failed", __func__); switch (trig_ratio.lighting) { case TRIGGER_LOWLIGHT: p_lf1 = &chromatix_ABF2->abf2_config_low_light; p_lf2 = &chromatix_ABF2->abf2_config_normal_light; break; case TRIGGER_OUTDOOR: p_lf1 = &chromatix_ABF2->abf2_config_bright_light; p_lf2 = &chromatix_ABF2->abf2_config_normal_light; break; case TRIGGER_NORMAL: default: p_lf1 = p_lf2 = &chromatix_ABF2->abf2_config_normal_light; break; } update_lf = (trig_ratio.lighting != mod->cur_lf_aec_ratio.lighting) || (trig_ratio.ratio != mod->cur_lf_aec_ratio.ratio) || (in_params->cfg.streaming_mode != mod->old_streaming_mode); ISP_DBG(ISP_MOD_CLF, "%s: update_lf %d ratio %f lighting %d", __func__, update_lf, trig_ratio.ratio, trig_ratio.lighting); if (update_lf) { if(F_EQUAL(trig_ratio.ratio, 0.0) || F_EQUAL(trig_ratio.ratio, 1.0)) *p_lf_new = *p_lf1; else util_clf_luma_interpolate(p_lf2, p_lf1, p_lf_new, trig_ratio.ratio); mod->cur_lf_aec_ratio = trig_ratio; /* need to handle for luma case */ mod->old_streaming_mode = in_params->cfg.streaming_mode; mod->lf_update = TRUE; } return status; } /* clf_luma_trigger_update */
/*=========================================================================== * FUNCTION linearization_trigger_update * * DESCRIPTION *==========================================================================*/ static int linearization_trigger_update(isp_linear_mod_t *linear_mod, isp_pix_trigger_update_input_t *trigger_params, uint32_t in_param_size) { int rc = 0; int is_burst = IS_BURST_STREAMING(&trigger_params->cfg); long bl_lux_index_end, bl_lux_index_start; long ll_lux_index_end, ll_lux_index_start; isp_linear_lux_t lux = LINEAR_AEC_NORMAL; awb_cct_type cct_type; chromatix_linearization_type output; uint8_t update_linear = FALSE; chromatix_parms_type *chroma3a = (chromatix_parms_type *)trigger_params->cfg.chromatix_ptrs.chromatixPtr; chromatix_black_level_type *pchromatix_black_level = &chroma3a->chromatix_VFE.chromatix_black_level; chromatix_VFE_common_type *pchromatix_common = (chromatix_VFE_common_type *) trigger_params->cfg.chromatix_ptrs.chromatixComPtr; chromatix_L_type *pchromatix_L = &pchromatix_common->chromatix_L; if (in_param_size != sizeof(isp_pix_trigger_update_input_t)) { /* size mismatch */ CDBG_ERROR("%s: size mismatch, expecting = %d, received = %d", __func__, sizeof(isp_pix_trigger_update_input_t), in_param_size); return -1; } if (!linear_mod->linear_enable) { ISP_DBG(ISP_MOD_LINEARIZATION , "%s: linearization not enabled", __func__); return 0; } if (!linear_mod->linear_trigger_enable) { ISP_DBG(ISP_MOD_LINEARIZATION , "%s: linearization tigger not enabled", __func__); return 0; } if ((!isp_util_aec_check_settled( &(trigger_params->trigger_input.stats_update.aec_update))) && (trigger_params->trigger_input.flash_mode != CAM_FLASH_MODE_TORCH)) { ISP_DBG(ISP_MOD_LINEARIZATION , "%s: AEC not settled", __func__); return 0; } linear_mod->trigger_info.mired_color_temp = MIRED(trigger_params->trigger_input.stats_update.awb_update.color_temp); CALC_CCT_TRIGGER_MIRED(linear_mod->trigger_info.trigger_A, pchromatix_L->linear_A_trigger); CALC_CCT_TRIGGER_MIRED(linear_mod->trigger_info.trigger_d65, pchromatix_L->linear_D65_trigger); // get the cct type cct_type = isp_util_get_awb_cct_type(linear_mod->notify_ops->parent, &linear_mod->trigger_info, chroma3a); // get the low light trigger points ll_lux_index_end = pchromatix_L->linearization_lowlight_trigger.lux_index_end; ll_lux_index_start = pchromatix_L->linearization_lowlight_trigger.lux_index_start; // get the low light trigger points bl_lux_index_end = pchromatix_black_level->blk_lowlight_trigger.lux_index_end; bl_lux_index_start = pchromatix_black_level->blk_lowlight_trigger.lux_index_start; /*============================================*/ /* AEC :Decision */ /*============================================*/ float lux_idx = trigger_params->trigger_input.stats_update.aec_update.lux_idx; if (lux_idx >= ll_lux_index_end) lux = LINEAR_AEC_LOW; else if (lux_idx < ll_lux_index_end && lux_idx >= ll_lux_index_start) lux = LINEAR_AEC_NORMAL_LOW; else if (lux_idx < ll_lux_index_start) lux = LINEAR_AEC_NORMAL; else CDBG_HIGH("%s: Lux index is invalid\n", __func__); /* check for trigger updation */ update_linear = ((linear_mod->old_streaming_mode != trigger_params->cfg.streaming_mode) || !F_EQUAL(linear_mod->prev_lux, lux) || !F_EQUAL(linear_mod->prev_cct_type, cct_type)); if ((update_linear) || (!F_EQUAL(linear_mod->prev_lux_idx, lux_idx) & ( lux == LINEAR_AEC_NORMAL_LOW ))) { select_linear_table(linear_mod, lux, cct_type, &output, trigger_params); config_linearization_cmd(linear_mod, &output); linear_mod->hw_update_pending = TRUE; ISP_DBG(ISP_MOD_LINEARIZATION , "%s: color temp %d", __func__, trigger_params->trigger_input. stats_update.awb_update.color_temp); ISP_DBG(ISP_MOD_LINEARIZATION , "%s: lux index %f", __func__, trigger_params->trigger_input. stats_update.aec_update.lux_idx); ISP_DBG(ISP_MOD_LINEARIZATION , "%s: AEC type prev %s new %s", __func__, aec_debug_str[linear_mod->prev_lux],aec_debug_str[lux]); ISP_DBG(ISP_MOD_LINEARIZATION , "%s: AWB type prev %s new %s", __func__, awb_debug_str[linear_mod->prev_cct_type], awb_debug_str[cct_type]); linear_mod->old_streaming_mode = trigger_params->cfg.streaming_mode; linear_mod->prev_lux = lux; linear_mod->prev_cct_type = cct_type; linear_mod->prev_lux_idx = lux_idx; } return 0; } /* linearization_trigger_update */
/*=========================================================================== * FUNCTION - vfe_demosaic_bpc_trigger_update - * * DESCRIPTION: *==========================================================================*/ vfe_status_t vfe_demosaic_bpc_trigger_update(bpc_mod_t *bpc_ctrl, vfe_params_t *vfe_params) { uint8_t dbpcFmin, dbpcFmin_lowlight, dbpcFmax, dbpcFmax_lowlight; uint8_t dbccFmin, dbccFmin_lowlight, dbccFmax, dbccFmax_lowlight; tuning_control_type bpc_tuning_control, bcc_tuning_control; float new_bpc_trigger_ratio, new_bcc_trigger_ratio; VFE_DemosaicDBPC_CmdType *cmd = NULL; bpc_4_offset_type *bpc_normal_input_offset = NULL, *bcc_normal_input_offset = NULL; bpc_4_offset_type *bpc_lowlight_input_offset = NULL, *bcc_lowlight_input_offset = NULL; trigger_point_type *bpc_trigger_point = NULL, *bcc_trigger_point = NULL; chromatix_parms_type *chrPtr = vfe_params->chroma3a; static vfe_op_mode_t cur_mode = VFE_OP_MODE_INVALID; if (!bpc_ctrl->enable) { CDBG("%s: bpc is not enabled. Skip the config\n", __func__); return VFE_SUCCESS; } bpc_ctrl->trigger_update = FALSE; bpc_tuning_control = chrPtr->control_bpc; bcc_tuning_control = chrPtr->control_bcc; if (!bpc_ctrl->trigger_enable) { CDBG("%s: Trigger is disable. Skip the trigger update.\n", __func__); return VFE_SUCCESS; } if (IS_SNAP_MODE(vfe_params)) { bpc_trigger_point = &(chrPtr->bpc_snapshot_lowlight_trigger); bcc_trigger_point = &(chrPtr->bcc_snapshot_lowlight_trigger); dbpcFmin = chrPtr->bpc_Fmin_snapshot; dbpcFmax = chrPtr->bpc_Fmax_snapshot; dbpcFmin_lowlight = chrPtr->bpc_Fmin_snapshot_lowlight; dbpcFmax_lowlight = chrPtr->bpc_Fmax_snapshot_lowlight; dbccFmin = chrPtr->bcc_Fmin_snapshot; dbccFmax = chrPtr->bcc_Fmax_snapshot; dbccFmin_lowlight = chrPtr->bcc_Fmin_snapshot_lowlight; dbccFmax_lowlight = chrPtr->bcc_Fmax_snapshot_lowlight; bpc_normal_input_offset = &(chrPtr->bpc_4_offset_snapshot[BPC_NORMAL_LIGHT]); bpc_lowlight_input_offset = &(chrPtr->bpc_4_offset_snapshot[BPC_LOW_LIGHT]); bcc_normal_input_offset = &(chrPtr->bcc_4_offset_snapshot[BPC_NORMAL_LIGHT]); bcc_lowlight_input_offset = &(chrPtr->bcc_4_offset_snapshot[BPC_LOW_LIGHT]); cmd = &(bpc_ctrl->bpc_snap_cmd); } else { if (!vfe_util_aec_check_settled(&(vfe_params->aec_params))) { if (!bpc_ctrl->reload_params) { CDBG("%s: AEC is not setteled. Skip the trigger\n", __func__); return VFE_SUCCESS; } } bpc_trigger_point = &(chrPtr->bpc_lowlight_trigger); bcc_trigger_point = &(chrPtr->bcc_lowlight_trigger); dbpcFmin = chrPtr->bpc_Fmin_preview; dbpcFmax = chrPtr->bpc_Fmax_preview; dbpcFmin_lowlight = chrPtr->bpc_Fmin_preview_lowlight; dbpcFmax_lowlight = chrPtr->bpc_Fmax_preview_lowlight; dbccFmin = chrPtr->bcc_Fmin_preview; dbccFmax = chrPtr->bcc_Fmax_preview; dbccFmin_lowlight = chrPtr->bcc_Fmin_preview_lowlight; dbccFmax_lowlight = chrPtr->bcc_Fmax_preview_lowlight; bpc_normal_input_offset = &(chrPtr->bpc_4_offset[BPC_NORMAL_LIGHT]); bpc_lowlight_input_offset = &(chrPtr->bpc_4_offset[BPC_LOW_LIGHT]); bcc_normal_input_offset = &(chrPtr->bcc_4_offset[BPC_NORMAL_LIGHT]); bcc_lowlight_input_offset = &(chrPtr->bcc_4_offset[BPC_LOW_LIGHT]); cmd = &(bpc_ctrl->bpc_prev_cmd); } new_bpc_trigger_ratio = vfe_util_get_aec_ratio(bpc_tuning_control, bpc_trigger_point, vfe_params); new_bcc_trigger_ratio = vfe_util_get_aec_ratio(bcc_tuning_control, bcc_trigger_point, vfe_params); if (cur_mode != vfe_params->vfe_op_mode || bpc_ctrl->reload_params || !F_EQUAL(new_bpc_trigger_ratio, bpc_ctrl->bpc_trigger_ratio) || !F_EQUAL(new_bcc_trigger_ratio, bpc_ctrl->bcc_trigger_ratio)) { cmd->dbpcFmin = (uint8_t)LINEAR_INTERPOLATION(dbpcFmin, dbpcFmin_lowlight, new_bpc_trigger_ratio); cmd->dbpcFmax = (uint8_t)LINEAR_INTERPOLATION(dbpcFmax, dbpcFmax_lowlight, new_bpc_trigger_ratio); cmd->RdbpcOffHi = (uint16_t)LINEAR_INTERPOLATION( bpc_normal_input_offset->bpc_4_offset_r_hi, bpc_lowlight_input_offset->bpc_4_offset_r_hi, new_bpc_trigger_ratio); cmd->RdbpcOffLo = (uint16_t)LINEAR_INTERPOLATION( bpc_normal_input_offset->bpc_4_offset_r_lo, bpc_lowlight_input_offset->bpc_4_offset_r_lo, new_bpc_trigger_ratio); cmd->BdbpcOffHi = (uint16_t)LINEAR_INTERPOLATION( bpc_normal_input_offset->bpc_4_offset_b_hi, bpc_lowlight_input_offset->bpc_4_offset_b_hi, new_bpc_trigger_ratio); cmd->BdbpcOffLo = (uint16_t)LINEAR_INTERPOLATION( bpc_normal_input_offset->bpc_4_offset_b_lo, bpc_lowlight_input_offset->bpc_4_offset_b_lo, new_bpc_trigger_ratio); cmd->GRdbpcOffHi = (uint16_t)LINEAR_INTERPOLATION( bpc_normal_input_offset->bpc_4_offset_gr_hi, bpc_lowlight_input_offset->bpc_4_offset_gr_hi, new_bpc_trigger_ratio); cmd->GRdbpcOffLo = (uint16_t)LINEAR_INTERPOLATION( bpc_normal_input_offset->bpc_4_offset_gr_lo, bpc_lowlight_input_offset->bpc_4_offset_gr_lo, new_bpc_trigger_ratio); cmd->GBdbpcOffHi = (uint16_t)LINEAR_INTERPOLATION( bpc_normal_input_offset->bpc_4_offset_gb_hi, bpc_lowlight_input_offset->bpc_4_offset_gb_hi, new_bpc_trigger_ratio); cmd->GBdbpcOffLo = (uint16_t)LINEAR_INTERPOLATION( bpc_normal_input_offset->bpc_4_offset_gb_lo, bpc_lowlight_input_offset->bpc_4_offset_gb_lo, new_bpc_trigger_ratio); cmd->dbccFmin = (uint8_t)LINEAR_INTERPOLATION(dbccFmin, dbccFmin_lowlight, new_bcc_trigger_ratio); cmd->dbccFmax = (uint8_t)LINEAR_INTERPOLATION(dbccFmax, dbccFmax_lowlight, new_bcc_trigger_ratio); cmd->RdbccOffHi = (uint16_t)LINEAR_INTERPOLATION( bcc_normal_input_offset->bpc_4_offset_r_hi, bcc_lowlight_input_offset->bpc_4_offset_r_hi, new_bcc_trigger_ratio); cmd->RdbccOffLo = (uint16_t)LINEAR_INTERPOLATION( bcc_normal_input_offset->bpc_4_offset_r_lo, bcc_lowlight_input_offset->bpc_4_offset_r_lo, new_bcc_trigger_ratio); cmd->BdbpcOffHi = (uint16_t)LINEAR_INTERPOLATION( bcc_normal_input_offset->bpc_4_offset_b_hi, bcc_lowlight_input_offset->bpc_4_offset_b_hi, new_bcc_trigger_ratio); cmd->BdbpcOffLo = (uint16_t)LINEAR_INTERPOLATION( bcc_normal_input_offset->bpc_4_offset_b_lo, bcc_lowlight_input_offset->bpc_4_offset_b_lo, new_bcc_trigger_ratio); cmd->GRdbpcOffHi = (uint16_t)LINEAR_INTERPOLATION( bcc_normal_input_offset->bpc_4_offset_gr_hi, bcc_lowlight_input_offset->bpc_4_offset_gr_hi, new_bcc_trigger_ratio); cmd->GRdbpcOffLo = (uint16_t)LINEAR_INTERPOLATION( bcc_normal_input_offset->bpc_4_offset_gr_lo, bcc_lowlight_input_offset->bpc_4_offset_gr_lo, new_bcc_trigger_ratio); cmd->GBdbpcOffHi = (uint16_t)LINEAR_INTERPOLATION( bcc_normal_input_offset->bpc_4_offset_gb_hi, bcc_lowlight_input_offset->bpc_4_offset_gb_hi, new_bcc_trigger_ratio); cmd->GBdbpcOffLo = (uint16_t)LINEAR_INTERPOLATION( bcc_normal_input_offset->bpc_4_offset_gb_lo, bcc_lowlight_input_offset->bpc_4_offset_gb_lo, new_bcc_trigger_ratio); cur_mode = vfe_params->vfe_op_mode; bpc_ctrl->bpc_trigger_ratio = new_bpc_trigger_ratio; bpc_ctrl->bcc_trigger_ratio = new_bcc_trigger_ratio; bpc_ctrl->trigger_update = TRUE; bpc_ctrl->reload_params = FALSE; } else { CDBG("%s: No update required.\n", __func__); } return VFE_SUCCESS; } /* vfe_demosaic_bpc_trigger_update */
/** vfe_sce_trigger_update * * DESCRIPTION: trigger update by aec/awb trigger event * **/ static int sce_trigger_update( isp_sce_mod_t *sce_mod, isp_pix_trigger_update_input_t *trigger_params, uint32_t in_param_size) { uint8_t update_sce = FALSE; chromatix_parms_type *chroma_ptr = (chromatix_parms_type *)trigger_params->cfg.chromatix_ptrs.chromatixPtr; chromatix_SCE_type *chromatix_SCE = &chroma_ptr->chromatix_VFE.chromatix_SCE; float aec_ratio = 0.0; tuning_control_type *tc = &(chromatix_SCE->control_SCE); trigger_point_type *tp = &(chromatix_SCE->SCE_trigger); uint8_t is_burst = IS_BURST_STREAMING((&trigger_params->cfg)); if (!sce_mod->sce_enable) { ISP_DBG(ISP_MOD_SCE, "%s: SCE not enabled", __func__); return 0; } if (!sce_mod->sce_trigger_enable) { ISP_DBG(ISP_MOD_SCE, "%s: SCE trigger not enabled", __func__); return 0; } if (trigger_params->trigger_input.stats_update.awb_update.color_temp == 0) { ISP_DBG(ISP_MOD_SCE, "%s: SCE zero color temperature", __func__); return 0; } sce_mod->trigger_info.mired_color_temp = MIRED(trigger_params->trigger_input.stats_update.awb_update.color_temp); CALC_CCT_TRIGGER_MIRED(sce_mod->trigger_info.trigger_A, chromatix_SCE->SCE_A_trigger); CALC_CCT_TRIGGER_MIRED(sce_mod->trigger_info.trigger_d65, chromatix_SCE->SCE_D65_trigger); awb_cct_type cct_type = isp_util_get_awb_cct_type(sce_mod->notify_ops->parent, &sce_mod->trigger_info, chroma_ptr); aec_ratio = isp_util_get_aec_ratio(sce_mod->notify_ops->parent,*tc, tp, &trigger_params->trigger_input.stats_update.aec_update, is_burst); /* check for trigger updation */ update_sce = ((sce_mod->old_streaming_mode != trigger_params->cfg.streaming_mode) || (sce_mod->prev_sce_adj != sce_mod->sce_adjust_factor) || !F_EQUAL(sce_mod->prev_aec_ratio, aec_ratio) || !F_EQUAL(sce_mod->prev_cct_type, cct_type)); if(update_sce) { ISP_DBG(ISP_MOD_SCE, "Prev SCE Adj factor: %lf new: %lf", sce_mod->prev_sce_adj, sce_mod->sce_adjust_factor); ISP_DBG(ISP_MOD_SCE, "Prev mode: %d new: %d", sce_mod->old_streaming_mode, trigger_params->cfg.streaming_mode); ISP_DBG(ISP_MOD_SCE, "Prev aec ratio %f new %f", sce_mod->prev_aec_ratio, aec_ratio); ISP_DBG(ISP_MOD_SCE, "Prev cct type %d new %d", sce_mod->prev_cct_type, cct_type); trigger_sce_get_triangles(sce_mod, trigger_params, aec_ratio, cct_type); config_sce_cmd(sce_mod, trigger_params); sce_mod->old_streaming_mode = trigger_params->cfg.streaming_mode; sce_mod->prev_aec_ratio = aec_ratio; sce_mod->prev_cct_type = cct_type; sce_mod->prev_sce_adj = sce_mod->sce_adjust_factor; sce_mod->hw_update_pending = TRUE; } else { ISP_DBG(ISP_MOD_SCE, "%s: no updates\n",__func__); } return 0; } /* vfe_sce_trigger_update */