[COMMON] fimc-is2: Implementation of uvsp
authorSunmi Lee <carrotsm.lee@samsung.com>
Fri, 6 Jul 2018 02:10:12 +0000 (11:10 +0900)
committerSunyoung Kang <sy0816.kang@samsung.com>
Mon, 23 Jul 2018 08:06:21 +0000 (17:06 +0900)
UVSP function is controlled by noise_index (this value from ISP).
So it is needed to calculate the proper value with using linear interpolation by noise_index.
New functions were added to support uvsp.

PR JIRA ID: CPR-39

Change-Id: Id9b27ace9a2e663091f0901258b95b20a304bfbe
Signed-off-by: Sunmi Lee <carrotsm.lee@samsung.com>
drivers/media/platform/exynos/fimc-is2/hardware/api/fimc-is-hw-api-mcscaler-v2.h
drivers/media/platform/exynos/fimc-is2/hardware/api/fimc-is-hw-api-mcscaler-v5_0.c
drivers/media/platform/exynos/fimc-is2/hardware/fimc-is-hw-mcscaler-v2.c
drivers/media/platform/exynos/fimc-is2/hardware/fimc-is-hw-mcscaler-v2.h
drivers/media/platform/exynos/fimc-is2/hardware/fimc-is-hw-uvsp-cac.c
drivers/media/platform/exynos/fimc-is2/hardware/fimc-is-hw-uvsp-cac.h

index 85fabb4dee068aa923d0011be928378d65fcf6aa..7fa92731bbb892fba5318d1410c7bc243759bc8c 100644 (file)
@@ -233,6 +233,15 @@ void fimc_is_scaler_set_cac_enable(void __iomem *base_addr, u32 en);
 void fimc_is_scaler_set_cac_input_source(void __iomem *base_addr, u32 in);
 void fimc_is_scaler_set_cac_map_crt_thr(void __iomem *base_addr, struct cac_cfg_by_ni *cfg);
 
+/* uvsp */
+void fimc_is_scaler_set_uvsp_enable(void __iomem *base_addr, u32 hw_id, u32 en);
+void fimc_is_scaler_set_uvsp_radial_ctrl(void __iomem *base_addr, u32 hw_id, struct uvsp_ctrl *cfg);
+void fimc_is_scaler_set_uvsp_radial_cfg(void __iomem *base_addr, u32 hw_id, struct uvsp_radial_cfg *cfg);
+void fimc_is_scaler_set_uvsp_pedestal_cfg(void __iomem *base_addr, u32 hw_id, struct uvsp_pedestal_cfg *cfg);
+void fimc_is_scaler_set_uvsp_offset_cfg(void __iomem *base_addr, u32 hw_id, struct uvsp_offset_cfg *cfg);
+void fimc_is_scaler_set_uvsp_desat_cfg(void __iomem *base_addr, u32 hw_id, struct uvsp_desat_cfg *cfg);
+void fimc_is_scaler_set_uvsp_r2y_coef_cfg(void __iomem *base_addr, u32 hw_id, struct uvsp_r2y_coef_cfg *cfg);
+
 /* ysum */
 void fimc_is_scaler_set_ysum_input_sourece_enable(void __iomem *base_addr, u32 output_id, bool ysum_enable);
 void fimc_is_scaler_set_ysum_enable(void __iomem *base_addr, bool ysum_enable);
index ff93458de149862c775914bf61d93f954a5b9531..e83e81ece8da532ba9778b5f5dcfbac64ce4bf53 100644 (file)
@@ -3548,6 +3548,322 @@ void fimc_is_scaler_set_cac_map_crt_thr(void __iomem *base_addr, struct cac_cfg_
        fimc_is_hw_set_reg(base_addr, &mcsc_regs[MCSC_R_CAC_CRT_THR], reg_val);
 }
 
+/* for UVSP */
+void fimc_is_scaler_set_uvsp_enable(void __iomem *base_addr, u32 hw_id, u32 en)
+{
+       u32 reg_val = 0;
+
+       switch (hw_id) {
+       case DEV_HW_MCSC0:
+               reg_val = fimc_is_hw_get_reg(base_addr, &mcsc_regs[MCSC_R_UVSP0_CTRL]);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP0_ENABLE], en);
+               fimc_is_hw_set_reg(base_addr, &mcsc_regs[MCSC_R_UVSP0_CTRL], reg_val);
+               break;
+       case DEV_HW_MCSC1:
+               reg_val = fimc_is_hw_get_reg(base_addr, &mcsc_regs[MCSC_R_UVSP1_CTRL]);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP1_ENABLE], en);
+               fimc_is_hw_set_reg(base_addr, &mcsc_regs[MCSC_R_UVSP1_CTRL], reg_val);
+               break;
+       default:
+               warn_hw("invalid hw_id(%d) for MCSC api\n", hw_id);
+               break;
+       }
+}
+
+void fimc_is_scaler_set_uvsp_radial_ctrl(void __iomem *base_addr, u32 hw_id, struct uvsp_ctrl *cfg)
+{
+       u32 reg_val = 0;
+
+       switch (hw_id) {
+       case DEV_HW_MCSC0:
+               reg_val = fimc_is_hw_get_reg(base_addr, &mcsc_regs[MCSC_R_UVSP0_BINNING]);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP0_BINNING_X],
+                               cfg->binning_x);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP0_BINNING_Y],
+                               cfg->binning_y);
+               fimc_is_hw_set_reg(base_addr, &mcsc_regs[MCSC_R_UVSP0_BINNING], reg_val);
+
+               reg_val = fimc_is_hw_get_reg(base_addr, &mcsc_regs[MCSC_R_UVSP0_RADIAL_CTRL]);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP0_RADIAL_EN], 1);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP0_RADIAL_CENTER_X],
+                               cfg->radial_center_x);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP0_RADIAL_CENTER_Y],
+                               cfg->radial_center_y);
+               fimc_is_hw_set_reg(base_addr, &mcsc_regs[MCSC_R_UVSP0_RADIAL_CTRL], reg_val);
+
+               reg_val = fimc_is_hw_get_reg(base_addr, &mcsc_regs[MCSC_R_UVSP0_RADIAL_BIQUAD_A]);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP0_RADIAL_BIQUAD_A],
+                               cfg->biquad_a);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP0_RADIAL_BIQUAD_B],
+                               cfg->biquad_b);
+               fimc_is_hw_set_reg(base_addr, &mcsc_regs[MCSC_R_UVSP0_RADIAL_BIQUAD_B], reg_val);
+               break;
+       case DEV_HW_MCSC1:
+               reg_val = fimc_is_hw_get_reg(base_addr, &mcsc_regs[MCSC_R_UVSP1_BINNING]);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP1_BINNING_X],
+                               cfg->binning_x);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP1_BINNING_Y],
+                               cfg->binning_y);
+               fimc_is_hw_set_reg(base_addr, &mcsc_regs[MCSC_R_UVSP1_BINNING], reg_val);
+
+               reg_val = fimc_is_hw_get_reg(base_addr, &mcsc_regs[MCSC_R_UVSP1_RADIAL_CTRL]);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP1_RADIAL_EN], 1);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP1_RADIAL_CENTER_X],
+                               cfg->radial_center_x);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP1_RADIAL_CENTER_Y],
+                               cfg->radial_center_y);
+               fimc_is_hw_set_reg(base_addr, &mcsc_regs[MCSC_R_UVSP1_RADIAL_CTRL], reg_val);
+
+               reg_val = fimc_is_hw_get_reg(base_addr, &mcsc_regs[MCSC_R_UVSP1_RADIAL_BIQUAD_A]);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP1_RADIAL_BIQUAD_A],
+                               cfg->biquad_a);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP1_RADIAL_BIQUAD_B],
+                               cfg->biquad_b);
+               fimc_is_hw_set_reg(base_addr, &mcsc_regs[MCSC_R_UVSP1_RADIAL_BIQUAD_B], reg_val);
+               break;
+       default:
+               warn_hw("invalid hw_id(%d) for MCSC api\n", hw_id);
+               break;
+       }
+}
+
+void fimc_is_scaler_set_uvsp_radial_cfg(void __iomem *base_addr, u32 hw_id, struct uvsp_radial_cfg *cfg)
+{
+       u32 reg_val = 0;
+
+       switch (hw_id) {
+       case DEV_HW_MCSC0:
+               fimc_is_hw_set_reg(base_addr, &mcsc_regs[MCSC_R_UVSP0_RADIAL_BIQUAD_SHIFT],
+                       cfg->biquad_shift);
+
+               reg_val = fimc_is_hw_get_reg(base_addr, &mcsc_regs[MCSC_R_UVSP0_RADIAL_RANDOM]);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP0_RADIAL_RANDOM_EN],
+                               cfg->random_en);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP0_RADIAL_RANDOM_POWER],
+                               cfg->random_power);
+               fimc_is_hw_set_reg(base_addr, &mcsc_regs[MCSC_R_UVSP0_RADIAL_RANDOM], reg_val);
+
+               reg_val = fimc_is_hw_get_reg(base_addr, &mcsc_regs[MCSC_R_UVSP0_RADIAL_REFINE]);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP0_RADIAL_REFINE_EN],
+                               cfg->refine_en);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP0_RADIAL_REFINE_LUMA_MIN],
+                               cfg->refine_luma_min);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP0_RADIAL_REFINE_DENOM],
+                               cfg->refine_denom);
+               fimc_is_hw_set_reg(base_addr, &mcsc_regs[MCSC_R_UVSP0_RADIAL_REFINE], reg_val);
+
+               reg_val = fimc_is_hw_get_reg(base_addr, &mcsc_regs[MCSC_R_UVSP0_RADIAL_ALPHA]);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP0_RADIAL_ALPHA_GAIN_ADD_EN],
+                               cfg->alpha_gain_add_en);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP0_RADIAL_ALPHA_GREEN_EN],
+                               cfg->alpha_green_en);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP0_RADIAL_ALPHA_R],
+                               cfg->alpha_r);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP0_RADIAL_ALPHA_G],
+                               cfg->alpha_g);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP0_RADIAL_ALPHA_B],
+                               cfg->alpha_b);
+               fimc_is_hw_set_reg(base_addr, &mcsc_regs[MCSC_R_UVSP0_RADIAL_ALPHA], reg_val);
+               break;
+       case DEV_HW_MCSC1:
+               fimc_is_hw_set_reg(base_addr, &mcsc_regs[MCSC_R_UVSP1_RADIAL_BIQUAD_SHIFT],
+                       cfg->biquad_shift);
+
+               reg_val = fimc_is_hw_get_reg(base_addr, &mcsc_regs[MCSC_R_UVSP1_RADIAL_RANDOM]);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP1_RADIAL_RANDOM_EN],
+                               cfg->random_en);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP1_RADIAL_RANDOM_POWER],
+                               cfg->random_power);
+               fimc_is_hw_set_reg(base_addr, &mcsc_regs[MCSC_R_UVSP1_RADIAL_RANDOM], reg_val);
+
+               reg_val = fimc_is_hw_get_reg(base_addr, &mcsc_regs[MCSC_R_UVSP1_RADIAL_REFINE]);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP1_RADIAL_REFINE_EN],
+                               cfg->refine_en);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP1_RADIAL_REFINE_LUMA_MIN],
+                               cfg->refine_luma_min);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP1_RADIAL_REFINE_DENOM],
+                               cfg->refine_denom);
+               fimc_is_hw_set_reg(base_addr, &mcsc_regs[MCSC_R_UVSP1_RADIAL_REFINE], reg_val);
+
+               reg_val = fimc_is_hw_get_reg(base_addr, &mcsc_regs[MCSC_R_UVSP1_RADIAL_ALPHA]);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP1_RADIAL_ALPHA_GAIN_ADD_EN],
+                               cfg->alpha_gain_add_en);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP1_RADIAL_ALPHA_GREEN_EN],
+                               cfg->alpha_green_en);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP1_RADIAL_ALPHA_R],
+                               cfg->alpha_r);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP1_RADIAL_ALPHA_G],
+                               cfg->alpha_g);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP1_RADIAL_ALPHA_B],
+                               cfg->alpha_b);
+               fimc_is_hw_set_reg(base_addr, &mcsc_regs[MCSC_R_UVSP1_RADIAL_ALPHA], reg_val);
+               break;
+       default:
+               warn_hw("invalid hw_id(%d) for MCSC api\n", hw_id);
+               break;
+       }
+}
+
+void fimc_is_scaler_set_uvsp_pedestal_cfg(void __iomem *base_addr, u32 hw_id, struct uvsp_pedestal_cfg *cfg)
+{
+       u32 reg_val = 0;
+
+       switch (hw_id) {
+       case DEV_HW_MCSC0:
+               reg_val = fimc_is_hw_get_reg(base_addr, &mcsc_regs[MCSC_R_UVSP0_PEDESTAL]);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP0_PEDESTAL_R], cfg->r);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP0_PEDESTAL_G], cfg->g);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP0_PEDESTAL_B], cfg->b);
+               fimc_is_hw_set_reg(base_addr, &mcsc_regs[MCSC_R_UVSP0_PEDESTAL], reg_val);
+               break;
+       case DEV_HW_MCSC1:
+               reg_val = fimc_is_hw_get_reg(base_addr, &mcsc_regs[MCSC_R_UVSP1_PEDESTAL]);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP1_PEDESTAL_R], cfg->r);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP1_PEDESTAL_G], cfg->g);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP1_PEDESTAL_B], cfg->b);
+               fimc_is_hw_set_reg(base_addr, &mcsc_regs[MCSC_R_UVSP1_PEDESTAL], reg_val);
+               break;
+       default:
+               warn_hw("invalid hw_id(%d) for MCSC api\n", hw_id);
+               break;
+       }
+}
+
+void fimc_is_scaler_set_uvsp_offset_cfg(void __iomem *base_addr, u32 hw_id, struct uvsp_offset_cfg *cfg)
+{
+       u32 reg_val = 0;
+
+       switch (hw_id) {
+       case DEV_HW_MCSC0:
+               reg_val = fimc_is_hw_get_reg(base_addr, &mcsc_regs[MCSC_R_UVSP0_OFFSET]);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP0_OFFSET_R], cfg->r);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP0_OFFSET_G], cfg->g);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP0_OFFSET_B], cfg->b);
+               fimc_is_hw_set_reg(base_addr, &mcsc_regs[MCSC_R_UVSP0_OFFSET], reg_val);
+               break;
+       case DEV_HW_MCSC1:
+               reg_val = fimc_is_hw_get_reg(base_addr, &mcsc_regs[MCSC_R_UVSP1_OFFSET]);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP1_OFFSET_R], cfg->r);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP1_OFFSET_G], cfg->g);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP1_OFFSET_B], cfg->b);
+               fimc_is_hw_set_reg(base_addr, &mcsc_regs[MCSC_R_UVSP1_OFFSET], reg_val);
+               break;
+       default:
+               warn_hw("invalid hw_id(%d) for MCSC api\n", hw_id);
+               break;
+       }
+}
+
+void fimc_is_scaler_set_uvsp_desat_cfg(void __iomem *base_addr, u32 hw_id, struct uvsp_desat_cfg *cfg)
+{
+       u32 reg_val = 0;
+
+       switch (hw_id) {
+       case DEV_HW_MCSC0:
+               reg_val = fimc_is_hw_get_reg(base_addr, &mcsc_regs[MCSC_R_UVSP0_DESAT_CTRL]);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP0_DESAT_CTRL_EN],
+                               cfg->ctrl_en);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP0_DESAT_CTRL_SINGLESIDE],
+                               cfg->ctrl_singleSide);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP0_DESAT_CTRL_LUMA_OFFSET],
+                               cfg->ctrl_luma_offset);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP0_DESAT_CTRL_GAIN_OFFSET],
+                               cfg->ctrl_gain_offset);
+               fimc_is_hw_set_reg(base_addr, &mcsc_regs[MCSC_R_UVSP0_DESAT_CTRL], reg_val);
+
+               reg_val = fimc_is_hw_get_reg(base_addr, &mcsc_regs[MCSC_R_UVSP0_DESAT_Y]);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP0_DESAT_Y_SHIFT],
+                               cfg->y_shift);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP0_DESAT_Y_LUMA_MAX],
+                               cfg->y_luma_max);
+               fimc_is_hw_set_reg(base_addr, &mcsc_regs[MCSC_R_UVSP0_DESAT_Y], reg_val);
+
+               reg_val = fimc_is_hw_get_reg(base_addr, &mcsc_regs[MCSC_R_UVSP0_DESAT_U]);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP0_DESAT_U_LOW],
+                               cfg->u_low);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP0_DESAT_U_HIGH],
+                               cfg->u_high);
+               fimc_is_hw_set_reg(base_addr, &mcsc_regs[MCSC_R_UVSP0_DESAT_U], reg_val);
+
+               reg_val = fimc_is_hw_get_reg(base_addr, &mcsc_regs[MCSC_R_UVSP0_DESAT_V]);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP0_DESAT_V_LOW],
+                               cfg->v_low);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP0_DESAT_V_HIGH],
+                               cfg->v_high);
+               fimc_is_hw_set_reg(base_addr, &mcsc_regs[MCSC_R_UVSP0_DESAT_V], reg_val);
+               break;
+       case DEV_HW_MCSC1:
+               reg_val = fimc_is_hw_get_reg(base_addr, &mcsc_regs[MCSC_R_UVSP1_DESAT_CTRL]);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP1_DESAT_CTRL_EN],
+                               cfg->ctrl_en);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP1_DESAT_CTRL_SINGLESIDE],
+                               cfg->ctrl_singleSide);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP1_DESAT_CTRL_LUMA_OFFSET],
+                               cfg->ctrl_luma_offset);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP1_DESAT_CTRL_GAIN_OFFSET],
+                               cfg->ctrl_gain_offset);
+               fimc_is_hw_set_reg(base_addr, &mcsc_regs[MCSC_R_UVSP1_DESAT_CTRL], reg_val);
+
+               reg_val = fimc_is_hw_get_reg(base_addr, &mcsc_regs[MCSC_R_UVSP1_DESAT_Y]);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP1_DESAT_Y_SHIFT],
+                               cfg->y_shift);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP1_DESAT_Y_LUMA_MAX],
+                               cfg->y_luma_max);
+               fimc_is_hw_set_reg(base_addr, &mcsc_regs[MCSC_R_UVSP1_DESAT_Y], reg_val);
+
+               reg_val = fimc_is_hw_get_reg(base_addr, &mcsc_regs[MCSC_R_UVSP1_DESAT_U]);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP1_DESAT_U_LOW],
+                               cfg->u_low);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP1_DESAT_U_HIGH],
+                               cfg->u_high);
+               fimc_is_hw_set_reg(base_addr, &mcsc_regs[MCSC_R_UVSP1_DESAT_U], reg_val);
+
+               reg_val = fimc_is_hw_get_reg(base_addr, &mcsc_regs[MCSC_R_UVSP1_DESAT_V]);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP1_DESAT_V_LOW],
+                               cfg->v_low);
+               reg_val = fimc_is_hw_set_field_value(reg_val, &mcsc_fields[MCSC_F_UVSP1_DESAT_V_HIGH],
+                               cfg->v_high);
+               fimc_is_hw_set_reg(base_addr, &mcsc_regs[MCSC_R_UVSP1_DESAT_V], reg_val);
+               break;
+       default:
+               warn_hw("invalid hw_id(%d) for MCSC api\n", hw_id);
+               break;
+       }
+}
+
+void fimc_is_scaler_set_uvsp_r2y_coef_cfg(void __iomem *base_addr, u32 hw_id, struct uvsp_r2y_coef_cfg *cfg)
+{
+       switch (hw_id) {
+       case DEV_HW_MCSC0:
+               fimc_is_hw_set_reg(base_addr, &mcsc_regs[MCSC_R_UVSP0_RGB2YUV_COEF_00], cfg->r2y_coef_00);
+               fimc_is_hw_set_reg(base_addr, &mcsc_regs[MCSC_R_UVSP0_RGB2YUV_COEF_01], cfg->r2y_coef_01);
+               fimc_is_hw_set_reg(base_addr, &mcsc_regs[MCSC_R_UVSP0_RGB2YUV_COEF_02], cfg->r2y_coef_02);
+               fimc_is_hw_set_reg(base_addr, &mcsc_regs[MCSC_R_UVSP0_RGB2YUV_COEF_10], cfg->r2y_coef_10);
+               fimc_is_hw_set_reg(base_addr, &mcsc_regs[MCSC_R_UVSP0_RGB2YUV_COEF_11], cfg->r2y_coef_11);
+               fimc_is_hw_set_reg(base_addr, &mcsc_regs[MCSC_R_UVSP0_RGB2YUV_COEF_12], cfg->r2y_coef_12);
+               fimc_is_hw_set_reg(base_addr, &mcsc_regs[MCSC_R_UVSP0_RGB2YUV_COEF_20], cfg->r2y_coef_20);
+               fimc_is_hw_set_reg(base_addr, &mcsc_regs[MCSC_R_UVSP0_RGB2YUV_COEF_21], cfg->r2y_coef_21);
+               fimc_is_hw_set_reg(base_addr, &mcsc_regs[MCSC_R_UVSP0_RGB2YUV_COEF_22], cfg->r2y_coef_22);
+               fimc_is_hw_set_reg(base_addr, &mcsc_regs[MCSC_R_UVSP0_RGB2YUV_COEF_SHIFT], cfg->r2y_coef_shift);
+               break;
+       case DEV_HW_MCSC1:
+               fimc_is_hw_set_reg(base_addr, &mcsc_regs[MCSC_R_UVSP1_RGB2YUV_COEF_00], cfg->r2y_coef_00);
+               fimc_is_hw_set_reg(base_addr, &mcsc_regs[MCSC_R_UVSP1_RGB2YUV_COEF_01], cfg->r2y_coef_01);
+               fimc_is_hw_set_reg(base_addr, &mcsc_regs[MCSC_R_UVSP1_RGB2YUV_COEF_02], cfg->r2y_coef_02);
+               fimc_is_hw_set_reg(base_addr, &mcsc_regs[MCSC_R_UVSP1_RGB2YUV_COEF_10], cfg->r2y_coef_10);
+               fimc_is_hw_set_reg(base_addr, &mcsc_regs[MCSC_R_UVSP1_RGB2YUV_COEF_11], cfg->r2y_coef_11);
+               fimc_is_hw_set_reg(base_addr, &mcsc_regs[MCSC_R_UVSP1_RGB2YUV_COEF_12], cfg->r2y_coef_12);
+               fimc_is_hw_set_reg(base_addr, &mcsc_regs[MCSC_R_UVSP1_RGB2YUV_COEF_20], cfg->r2y_coef_20);
+               fimc_is_hw_set_reg(base_addr, &mcsc_regs[MCSC_R_UVSP1_RGB2YUV_COEF_21], cfg->r2y_coef_21);
+               fimc_is_hw_set_reg(base_addr, &mcsc_regs[MCSC_R_UVSP1_RGB2YUV_COEF_22], cfg->r2y_coef_22);
+               fimc_is_hw_set_reg(base_addr, &mcsc_regs[MCSC_R_UVSP1_RGB2YUV_COEF_SHIFT], cfg->r2y_coef_shift);
+               break;
+       default:
+               warn_hw("invalid hw_id(%d) for MCSC api\n", hw_id);
+               break;
+       }
+}
+
 /* DS */
 void fimc_is_scaler_set_ds_enable(void __iomem *base_addr, u32 ds_enable)
 {
index 33c577db429bae8c1ac85580d97d7a74048ea38d..59c4954b3eb1c3df14b401d00472f974a9ff64cb 100644 (file)
@@ -833,6 +833,7 @@ config:
        ret_internal = fimc_is_hw_mcsc_update_dsvra_register(hw_ip, head, mcs_param, instance, frame->shot);
        ret_internal = fimc_is_hw_mcsc_update_tdnr_register(hw_ip, frame, param, start_flag);
        ret_internal = fimc_is_hw_mcsc_update_cac_register(hw_ip, frame, instance);
+       ret_internal = fimc_is_hw_mcsc_update_uvsp_register(hw_ip, frame, instance);
        ret_internal = fimc_is_hw_mcsc_update_ysum_register(hw_ip, head, mcs_param, instance, frame->shot);
        if (ret_internal) {
                msdbg_hw(2, "ysum cfg is failed\n", instance, hw_ip);
@@ -1146,6 +1147,10 @@ static int fimc_is_hw_mcsc_load_setfile(struct fimc_is_hw_ip *hw_ip, u32 instanc
                        return -EINVAL;
                }
        }
+#if defined(USE_UVSP_CAC)
+       hw_mcsc->uvsp_ctrl.biquad_a = hw_ip->hardware->cal_info[sensor_position].data[2];
+       hw_mcsc->uvsp_ctrl.biquad_b = hw_ip->hardware->cal_info[sensor_position].data[3];
+#endif
 
        set_bit(HW_TUNESET, &hw_ip->state);
 
index 93ab9636f25c6bce387b89bca34b3cbfaca674b2..a4484c104bd04ca67e08d0990f3cd2d2df581a52 100644 (file)
@@ -152,6 +152,7 @@ struct fimc_is_hw_mcsc_cap {
        enum mcsc_cap_enum      tdnr;
        enum mcsc_cap_enum      djag;
        enum mcsc_cap_enum      cac;
+       enum mcsc_cap_enum      uvsp;
        enum mcsc_cap_enum      ysum;
        enum mcsc_cap_enum      ds_vra;
 };
@@ -180,6 +181,8 @@ struct fimc_is_hw_mcsc {
        enum tdnr_mode          cur_tdnr_mode;
        enum yic_mode           yic_en;
        struct tdnr_configs     tdnr_cfgs;
+       /* for uvsp */
+       struct uvsp_ctrl        uvsp_ctrl;
 
        /* for CAC*/
        u32                     cac_in;
@@ -250,6 +253,8 @@ int fimc_is_hw_mcsc_update_djag_register(struct fimc_is_hw_ip *hw_ip,
                u32 instance);
 int fimc_is_hw_mcsc_update_cac_register(struct fimc_is_hw_ip *hw_ip,
        struct fimc_is_frame *frame, u32 instance);
+int fimc_is_hw_mcsc_update_uvsp_register(struct fimc_is_hw_ip *hw_ip,
+       struct fimc_is_frame *frame, u32 instance);
 int fimc_is_hw_mcsc_update_ysum_register(struct fimc_is_hw_ip *hw_ip,
        struct fimc_is_group *head, struct mcs_param *mcs_param,
        u32 instance, struct camera2_shot *shot);
index 4c57602f0b8a66d2510c0f7f72a7010d1c19f78a..85e3a25aa60249601876f3a581248a5a4b86d7d9 100644 (file)
@@ -211,3 +211,343 @@ int fimc_is_hw_mcsc_recovery_cac_register(struct fimc_is_hw_ip *hw_ip,
 
        return ret;
 }
+
+struct ref_ni hw_mcsc_find_ni_idx_for_uvsp(struct fimc_is_hw_ip *hw_ip,
+       struct uvsp_setfile_contents *uvsp, u32 cur_ni)
+{
+       struct ref_ni ret_idx = {0, 0};
+       struct ref_ni ni_idx_range;
+       u32 ni_idx;
+
+       for (ni_idx = 0; ni_idx < uvsp->ni_max - 1; ni_idx++) {
+               ni_idx_range.min = MULTIPLIED_10(uvsp->ni_vals[ni_idx]);
+               ni_idx_range.max = MULTIPLIED_10(uvsp->ni_vals[ni_idx + 1]);
+
+               if (ni_idx_range.min < cur_ni && cur_ni < ni_idx_range.max) {
+                       ret_idx.min = ni_idx;
+                       ret_idx.max = ni_idx + 1;
+                       break;
+               } else if (cur_ni == ni_idx_range.min) {
+                       ret_idx.min = ni_idx;
+                       ret_idx.max = ni_idx;
+                       break;
+               } else if (cur_ni == ni_idx_range.max) {
+                       ret_idx.min = ni_idx + 1;
+                       ret_idx.max = ni_idx + 1;
+                       break;
+               }
+       }
+
+       sdbg_hw(2, "[UVSP] find_ni_idx: cur_ni(%d), ni[%d, %d], idx[%d, %d]\n", hw_ip,
+               uvsp->ni_vals[ret_idx.min], uvsp->ni_vals[ret_idx.max],
+               ret_idx.min, ret_idx.max);
+
+       return ret_idx;
+}
+
+void hw_mcsc_calc_uvsp_r2y_coef_cfg(struct uvsp_cfg_by_ni *uvsp_cfg,
+       struct uvsp_cfg_by_ni *cfg_min, struct uvsp_cfg_by_ni *cfg_max,
+       struct ref_ni *ni_idx, u32 cur_ni)
+{
+       struct uvsp_r2y_coef_cfg *min, *max, *cfg;
+
+       min = &cfg_min->r2y_coef_cfg;
+       max = &cfg_max->r2y_coef_cfg;
+       cfg = &uvsp_cfg->r2y_coef_cfg;
+
+       cfg->r2y_coef_00 = GET_LNR_INTRPL(
+                       min->r2y_coef_00, max->r2y_coef_00,
+                       ni_idx->min, ni_idx->max, cur_ni);
+       cfg->r2y_coef_01 = GET_LNR_INTRPL(
+                       min->r2y_coef_01, max->r2y_coef_01,
+                       ni_idx->min, ni_idx->max, cur_ni);
+       cfg->r2y_coef_02 = GET_LNR_INTRPL(
+                       min->r2y_coef_02, max->r2y_coef_02,
+                       ni_idx->min, ni_idx->max, cur_ni);
+       cfg->r2y_coef_10 = GET_LNR_INTRPL(
+                       min->r2y_coef_10, max->r2y_coef_10,
+                       ni_idx->min, ni_idx->max, cur_ni);
+       cfg->r2y_coef_11 = GET_LNR_INTRPL(
+                       min->r2y_coef_11, max->r2y_coef_11,
+                       ni_idx->min, ni_idx->max, cur_ni);
+       cfg->r2y_coef_12 = GET_LNR_INTRPL(
+                       min->r2y_coef_12, max->r2y_coef_12,
+                       ni_idx->min, ni_idx->max, cur_ni);
+       cfg->r2y_coef_20 = GET_LNR_INTRPL(
+                       min->r2y_coef_20, max->r2y_coef_20,
+                       ni_idx->min, ni_idx->max, cur_ni);
+       cfg->r2y_coef_21 = GET_LNR_INTRPL(
+                       min->r2y_coef_21, max->r2y_coef_21,
+                       ni_idx->min, ni_idx->max, cur_ni);
+       cfg->r2y_coef_22 = GET_LNR_INTRPL(
+                       min->r2y_coef_22, max->r2y_coef_22,
+                       ni_idx->min, ni_idx->max, cur_ni);
+       cfg->r2y_coef_shift = GET_LNR_INTRPL(
+                       min->r2y_coef_shift, max->r2y_coef_shift,
+                       ni_idx->min, ni_idx->max, cur_ni);
+}
+
+void hw_mcsc_calc_uvsp_desat_cfg(struct uvsp_cfg_by_ni *uvsp_cfg,
+       struct uvsp_cfg_by_ni *cfg_min, struct uvsp_cfg_by_ni *cfg_max,
+       struct ref_ni *ni_idx, u32 cur_ni)
+{
+       struct uvsp_desat_cfg *min, *max, *cfg;
+
+       min = &cfg_min->desat_cfg;
+       max = &cfg_max->desat_cfg;
+       cfg = &uvsp_cfg->desat_cfg;
+
+       cfg->ctrl_en = GET_LNR_INTRPL(
+                       min->ctrl_en, max->ctrl_en,
+                       ni_idx->min, ni_idx->max, cur_ni);
+       cfg->ctrl_singleSide = GET_LNR_INTRPL(
+                       min->ctrl_singleSide, max->ctrl_singleSide,
+                       ni_idx->min, ni_idx->max, cur_ni);
+       cfg->ctrl_luma_offset = GET_LNR_INTRPL(
+                       min->ctrl_luma_offset, max->ctrl_luma_offset,
+                       ni_idx->min, ni_idx->max, cur_ni);
+       cfg->ctrl_gain_offset = GET_LNR_INTRPL(
+                       min->ctrl_gain_offset, max->ctrl_gain_offset,
+                       ni_idx->min, ni_idx->max, cur_ni);
+
+       cfg->y_shift = GET_LNR_INTRPL(
+                       min->y_shift, max->y_shift,
+                       ni_idx->min, ni_idx->max, cur_ni);
+       cfg->y_luma_max = GET_LNR_INTRPL(
+                       min->y_luma_max, max->y_luma_max,
+                       ni_idx->min, ni_idx->max, cur_ni);
+       cfg->u_low = GET_LNR_INTRPL(
+                       min->u_low, max->u_low,
+                       ni_idx->min, ni_idx->max, cur_ni);
+       cfg->u_high = GET_LNR_INTRPL(
+                       min->u_high, max->u_high,
+                       ni_idx->min, ni_idx->max, cur_ni);
+       cfg->v_low = GET_LNR_INTRPL(
+                       min->v_low, max->v_low,
+                       ni_idx->min, ni_idx->max, cur_ni);
+       cfg->v_high = GET_LNR_INTRPL(
+                       min->v_high, max->v_high,
+                       ni_idx->min, ni_idx->max, cur_ni);
+}
+
+void hw_mcsc_calc_uvsp_offset_cfg(struct uvsp_cfg_by_ni *uvsp_cfg,
+       struct uvsp_cfg_by_ni *cfg_min, struct uvsp_cfg_by_ni *cfg_max,
+       struct ref_ni *ni_idx, u32 cur_ni)
+{
+       struct uvsp_offset_cfg *min, *max, *cfg;
+
+       min = &cfg_min->offset_cfg;
+       max = &cfg_max->offset_cfg;
+       cfg = &uvsp_cfg->offset_cfg;
+
+       cfg->r = GET_LNR_INTRPL(
+                       min->r, max->r,
+                       ni_idx->min, ni_idx->max, cur_ni);
+       cfg->g = GET_LNR_INTRPL(
+                       min->g, max->g,
+                       ni_idx->min, ni_idx->max, cur_ni);
+       cfg->b = GET_LNR_INTRPL(
+                       min->b, max->b,
+                       ni_idx->min, ni_idx->max, cur_ni);
+}
+
+void hw_mcsc_calc_uvsp_pedestal_cfg(struct uvsp_cfg_by_ni *uvsp_cfg,
+       struct uvsp_cfg_by_ni *cfg_min, struct uvsp_cfg_by_ni *cfg_max,
+       struct ref_ni *ni_idx, u32 cur_ni)
+{
+       struct uvsp_pedestal_cfg *min, *max, *cfg;
+
+       min = &cfg_min->pedestal_cfg;
+       max = &cfg_max->pedestal_cfg;
+       cfg = &uvsp_cfg->pedestal_cfg;
+
+       cfg->r = GET_LNR_INTRPL(
+                       min->r, max->r,
+                       ni_idx->min, ni_idx->max, cur_ni);
+       cfg->g = GET_LNR_INTRPL(
+                       min->g, max->g,
+                       ni_idx->min, ni_idx->max, cur_ni);
+       cfg->b = GET_LNR_INTRPL(
+                       min->b, max->b,
+                       ni_idx->min, ni_idx->max, cur_ni);
+}
+
+void hw_mcsc_calc_uvsp_radial_cfg(struct uvsp_cfg_by_ni *uvsp_cfg,
+       struct uvsp_cfg_by_ni *cfg_min, struct uvsp_cfg_by_ni *cfg_max,
+       struct ref_ni *ni_idx, u32 cur_ni)
+{
+       struct uvsp_radial_cfg *min, *max, *cfg;
+
+       min = &cfg_min->radial_cfg;
+       max = &cfg_max->radial_cfg;
+       cfg = &uvsp_cfg->radial_cfg;
+
+       cfg->biquad_shift = GET_LNR_INTRPL(
+                       min->biquad_shift, max->biquad_shift,
+                       ni_idx->min, ni_idx->max, cur_ni);
+
+       cfg->random_en = GET_LNR_INTRPL(
+                       min->random_en, max->random_en,
+                       ni_idx->min, ni_idx->max, cur_ni);
+       cfg->random_power = GET_LNR_INTRPL(
+                       min->random_power, max->random_power,
+                       ni_idx->min, ni_idx->max, cur_ni);
+       cfg->refine_en = GET_LNR_INTRPL(
+                       min->refine_en, max->refine_en,
+                       ni_idx->min, ni_idx->max, cur_ni);
+       cfg->refine_luma_min = GET_LNR_INTRPL(
+                       min->refine_luma_min, max->refine_luma_min,
+                       ni_idx->min, ni_idx->max, cur_ni);
+       cfg->refine_denom = GET_LNR_INTRPL(
+                       min->refine_denom, max->refine_denom,
+                       ni_idx->min, ni_idx->max, cur_ni);
+
+       cfg->alpha_gain_add_en = GET_LNR_INTRPL(
+                       min->alpha_gain_add_en, max->alpha_gain_add_en,
+                       ni_idx->min, ni_idx->max, cur_ni);
+       cfg->alpha_green_en = GET_LNR_INTRPL(
+                       min->alpha_green_en, max->alpha_green_en,
+                       ni_idx->min, ni_idx->max, cur_ni);
+       cfg->alpha_r = GET_LNR_INTRPL(
+                       min->alpha_r, max->alpha_r,
+                       ni_idx->min, ni_idx->max, cur_ni);
+       cfg->alpha_g = GET_LNR_INTRPL(
+                       min->alpha_g, max->alpha_g,
+                       ni_idx->min, ni_idx->max, cur_ni);
+       cfg->alpha_b = GET_LNR_INTRPL(
+                       min->alpha_b, max->alpha_b,
+                       ni_idx->min, ni_idx->max, cur_ni);
+}
+
+void hw_mcsc_calc_uvsp_param_by_ni(struct fimc_is_hw_ip *hw_ip,
+       struct uvsp_setfile_contents *uvsp, u32 cur_ni)
+{
+       struct ref_ni ni_range, ni_idx;
+       struct uvsp_cfg_by_ni uvsp_cfg, cfg_max, cfg_min;
+
+       ni_range.min = MULTIPLIED_10(uvsp->ni_vals[0]);
+       ni_range.max = MULTIPLIED_10(uvsp->ni_vals[uvsp->ni_max - 1]);
+
+       if (cur_ni <= ni_range.min) {
+               sdbg_hw(2, "[UVSP] cur_ni(%d) <= ni_range.min(%d)\n", hw_ip, cur_ni, ni_range.min);
+               ni_idx.min = 0;
+               ni_idx.max = 0;
+       } else if (cur_ni >= ni_range.max) {
+               sdbg_hw(2, "[UVSP] cur_ni(%d) >= ni_range.max(%d)\n", hw_ip, cur_ni, ni_range.max);
+               ni_idx.min = uvsp->ni_max - 1;
+               ni_idx.max = uvsp->ni_max - 1;
+       } else {
+               ni_idx = hw_mcsc_find_ni_idx_for_uvsp(hw_ip, uvsp, cur_ni);
+       }
+
+       cfg_min = uvsp->cfgs[ni_idx.min];
+       cfg_max = uvsp->cfgs[ni_idx.max];
+       hw_mcsc_calc_uvsp_radial_cfg(&uvsp_cfg, &cfg_min, &cfg_max, &ni_idx, cur_ni);
+       hw_mcsc_calc_uvsp_pedestal_cfg(&uvsp_cfg, &cfg_min, &cfg_max, &ni_idx, cur_ni);
+       hw_mcsc_calc_uvsp_offset_cfg(&uvsp_cfg, &cfg_min, &cfg_max, &ni_idx, cur_ni);
+       hw_mcsc_calc_uvsp_desat_cfg(&uvsp_cfg, &cfg_min, &cfg_max, &ni_idx, cur_ni);
+       hw_mcsc_calc_uvsp_r2y_coef_cfg(&uvsp_cfg, &cfg_min, &cfg_max, &ni_idx, cur_ni);
+
+       fimc_is_scaler_set_uvsp_radial_cfg(hw_ip->regs, hw_ip->id, &uvsp_cfg.radial_cfg);
+       fimc_is_scaler_set_uvsp_pedestal_cfg(hw_ip->regs, hw_ip->id, &uvsp_cfg.pedestal_cfg);
+       fimc_is_scaler_set_uvsp_offset_cfg(hw_ip->regs, hw_ip->id, &uvsp_cfg.offset_cfg);
+       fimc_is_scaler_set_uvsp_r2y_coef_cfg(hw_ip->regs, hw_ip->id, &uvsp_cfg.r2y_coef_cfg);
+       fimc_is_scaler_set_uvsp_enable(hw_ip->regs, hw_ip->id, 1);
+}
+
+void hw_mcsc_calc_uvsp_radial_ctrl(struct fimc_is_hw_ip *hw_ip,
+       struct fimc_is_hw_mcsc *hw_mcsc, struct fimc_is_frame *frame,
+       struct cal_info *cal_info, u32 instance)
+{
+       struct uvsp_ctrl *uvsp_ctrl;
+       struct camera2_shot_ext *shot_ext;
+       u32 lsc_center_x, lsc_center_y;
+
+       lsc_center_x = cal_info->data[0];
+       lsc_center_y = cal_info->data[1];
+       uvsp_ctrl->biquad_a = cal_info->data[2];
+       uvsp_ctrl->biquad_b = cal_info->data[3];
+       sdbg_hw(2, "[UVSP][F:%d]: lsc_center_x,y(%d,%d), uvsp_ctrl->biquad_a,b(%d,%d)\n",
+               hw_ip, __func__, frame->fcount, lsc_center_x, lsc_center_y,
+               uvsp_ctrl->biquad_a, uvsp_ctrl->biquad_b);
+
+       shot_ext = frame->shot_ext;
+       if (!frame->shot_ext) {
+               sdbg_hw(2, "___carrotsm:[F:%d] shot_ext(NULL)\n", hw_ip, __func__);
+               fimc_is_scaler_set_uvsp_enable(hw_ip->regs, hw_ip->id, 0);
+               return;
+       }
+
+       sdbg_hw(2, "[UVSP][F:%d]: shot >> binning_r(%d,%d), crop_taa(%d,%d), bds(%d,%d)\n",
+               hw_ip, __func__, frame->fcount,
+               shot_ext->binning_ratio_x, shot_ext->binning_ratio_y,
+               shot_ext->crop_taa_x, shot_ext->crop_taa_y,
+               shot_ext->bds_ratio_x, shot_ext->bds_ratio_y);
+
+       uvsp_ctrl = &hw_mcsc->uvsp_ctrl;
+       uvsp_ctrl->binning_x = shot_ext->binning_ratio_x * shot_ext->bds_ratio_x * 1024;
+       uvsp_ctrl->binning_y = shot_ext->binning_ratio_y * shot_ext->bds_ratio_y * 1024;
+       if (shot_ext->bds_ratio_x && shot_ext->bds_ratio_y) {
+               shot_ext->bds_ratio_x = 1;
+               shot_ext->bds_ratio_y = 1;
+       }
+       uvsp_ctrl->radial_center_x = (u32)((lsc_center_x - shot_ext->crop_taa_x) / shot_ext->bds_ratio_x);
+       uvsp_ctrl->radial_center_y = (u32)((lsc_center_y - shot_ext->crop_taa_y) / shot_ext->bds_ratio_y);
+
+       fimc_is_scaler_set_uvsp_radial_ctrl(hw_ip->regs, hw_ip->id, uvsp_ctrl);
+       sdbg_hw(2, "[UVSP][F:%d]: uvsp_ctrl >> binning(%d,%d), r_center(%d,%d), biquad(%d,%d)\n",
+               hw_ip, __func__, frame->fcount, uvsp_ctrl->binning_x, uvsp_ctrl->binning_y,
+               uvsp_ctrl->radial_center_x, uvsp_ctrl->radial_center_y,
+               uvsp_ctrl->biquad_a, uvsp_ctrl->biquad_b);
+}
+
+int fimc_is_hw_mcsc_update_uvsp_register(struct fimc_is_hw_ip *hw_ip,
+       struct fimc_is_frame *frame, u32 instance)
+{
+       int ret = 0;
+       struct fimc_is_hw_mcsc *hw_mcsc;
+       struct fimc_is_hw_mcsc_cap *cap;
+       struct hw_mcsc_setfile *setfile;
+       struct uvsp_setfile_contents *uvsp;
+       struct cal_info *cal_info;
+       enum exynos_sensor_position sensor_position;
+       u32 ni;
+
+       hw_mcsc = (struct fimc_is_hw_mcsc *)hw_ip->priv_info;
+       cap = GET_MCSC_HW_CAP(hw_ip);
+
+       if (cap->uvsp != MCSC_CAP_SUPPORT)
+               return ret;
+
+       sensor_position = hw_ip->hardware->sensor_position[instance];
+       setfile = hw_mcsc->cur_setfile[sensor_position];
+       cal_info = &hw_ip->hardware->cal_info[sensor_position];
+
+       sdbg_hw(10, "TEST: get_lnr_intprl(11, 20, 1, 1, 3) = %d\n",
+                       hw_ip, GET_LNR_INTRPL(11, 20, 1, 1, 3));
+
+#ifdef LHM_ENABLE_EVT0
+       return ret;
+#endif
+       /* calculate cac parameters */
+#ifdef FIXED_TDNR_NOISE_INDEX
+       ni = FIXED_TDNR_NOISE_INDEX_VALUE;
+#else
+       ni = frame->noise_idx;
+#endif
+       if (hw_mcsc->cur_ni == ni)
+               goto exit;
+
+       hw_mcsc_calc_uvsp_radial_ctrl(hw_ip, hw_mcsc, frame, cal_info, instance);
+#if defined(USE_UVSP_CAC)
+       uvsp = &setfile->uvsp;
+       hw_mcsc_calc_uvsp_param_by_ni(hw_ip, uvsp, ni);
+#endif
+       sdbg_hw(2, "[UVSP][F:%d]: ni(%d)\n",
+               hw_ip, __func__, frame->fcount, ni);
+
+exit:
+       hw_mcsc->cur_ni = ni;
+
+       return 0;
+}
index 3a465c719c2b8b19f099a61056cf04f0b5901018..4f54e5a20bfcf9afd4d59c52e092f75898afa619 100644 (file)
@@ -36,7 +36,18 @@ struct cac_setfile_contents {
        struct cac_cfg_by_ni    cfgs[CAC_MAX_NI_DEPENDED_CFG];
 };
 
-#define UVSP_MAX_NI_DEPENDED_CONFIGS     (6)
+#define UVSP_MAX_NI_DEPENDED_CONFIGS     (9)
+struct uvsp_ctrl {
+       u32     binning_x;
+       u32     binning_y;
+
+       u32     radial_center_x;
+       u32     radial_center_y;
+
+       u32     biquad_a;
+       u32     biquad_b;
+};
+
 struct uvsp_radial_cfg {
        u32     biquad_shift;