Loading drivers/video/msm/mdss/mdss_mdp.h +1 −0 Original line number Diff line number Diff line Loading @@ -618,6 +618,7 @@ struct pp_sts_type { u32 gamut_sts; u32 pgc_sts; u32 sharp_sts; u32 hist_sts; u32 side_sts; }; Loading drivers/video/msm/mdss/mdss_mdp_pp.c +46 −18 Original line number Diff line number Diff line Loading @@ -407,7 +407,8 @@ static struct mdss_pp_res_type *mdss_pp_res; static u32 pp_hist_read(char __iomem *v_addr, struct pp_hist_col_info *hist_info); static int pp_hist_setup(u32 *op, u32 block, struct mdss_mdp_mixer *mix); static int pp_hist_setup(u32 *op, u32 block, struct mdss_mdp_mixer *mix, struct pp_sts_type *pp_sts); static int pp_hist_disable(struct pp_hist_col_info *hist_info); static void pp_update_pcc_regs(char __iomem *addr, struct mdp_pcc_cfg_data *cfg_ptr); Loading Loading @@ -1048,7 +1049,8 @@ static int pp_vig_pipe_setup(struct mdss_mdp_pipe *pipe, u32 *op) } /* Histogram collection enabled checked inside pp_hist_setup */ pp_hist_setup(op, MDSS_PP_SSPP_CFG | pipe->num, pipe->mixer_left); pp_hist_setup(op, MDSS_PP_SSPP_CFG | pipe->num, pipe->mixer_left, &pipe->pp_res.pp_sts); if (!(pipe->flags & MDP_OVERLAY_PP_CFG_EN)) { pr_debug("Overlay PP CFG enable not set\n"); Loading Loading @@ -2002,11 +2004,12 @@ static char __iomem *mdss_mdp_get_dspp_addr_off(u32 dspp_num) } /* Assumes that function will be called from within clock enabled space*/ static int pp_hist_setup(u32 *op, u32 block, struct mdss_mdp_mixer *mix) static int pp_hist_setup(u32 *op, u32 block, struct mdss_mdp_mixer *mix, struct pp_sts_type *pp_sts) { int ret = -EINVAL; int ret = 0; char __iomem *base; u32 op_flags; u32 op_flags = 0, block_type = 0; struct mdss_mdp_pipe *pipe; struct pp_hist_col_info *hist_info; unsigned long flag; Loading @@ -2019,6 +2022,7 @@ static int pp_hist_setup(u32 *op, u32 block, struct mdss_mdp_mixer *mix) intr_mask = 1; if (mix && (PP_LOCAT(block) == MDSS_PP_DSPP_CFG)) { /* HIST_EN */ block_type = DSPP; op_flags = BIT(16); hist_info = &mdss_pp_res->dspp_hist[mix->num]; base = mdss_mdp_get_dspp_addr_off(PP_BLOCK(block)); Loading @@ -2029,6 +2033,7 @@ static int pp_hist_setup(u32 *op, u32 block, struct mdss_mdp_mixer *mix) } else if (PP_LOCAT(block) == MDSS_PP_SSPP_CFG && (pp_driver_ops.is_sspp_hist_supp) && (pp_driver_ops.is_sspp_hist_supp())) { block_type = SSPP_VIG; pipe = __get_hist_pipe(PP_BLOCK(block)); if (IS_ERR_OR_NULL(pipe)) { pr_debug("pipe DNE (%d)\n", Loading @@ -2041,18 +2046,38 @@ static int pp_hist_setup(u32 *op, u32 block, struct mdss_mdp_mixer *mix) base = pipe->base; mdss_mdp_pipe_unmap(pipe); } else { ret = -EINVAL; goto error; } mutex_lock(&hist_info->hist_mutex); spin_lock_irqsave(&hist_info->hist_lock, flag); if (hist_info->col_en) { /* * Set histogram interrupt if histogram collection is enabled. The * interrupt register offsets are the same across different mdss * versions so far, hence mdss_mdp_hist_irq_set_mask is used for * all the mdss versions. */ if (hist_info->col_en) mdss_mdp_hist_irq_set_mask(intr_mask << hist_info->intr_shift); /* * Starting from msmcobalt, the histogram enable bit has been moved * from DSPP opmode register to PA_HIST opmode register, hence we need * to update the histogram enable bit differently based on mdss version. * If HIST pp_set_config is defined, we will enable or disable the * hist_en bit in PA_HIST opmode register inside HIST pp_set_config * function; else, we only need to add the hist_en bit to the *op when * histogram collection is enable, and *op will be passed to * pp_dspp_setup to update the DSPP opmode register. */ if (pp_ops[HIST].pp_set_config) ret = pp_ops[HIST].pp_set_config(base, pp_sts, hist_info, block_type); else if (hist_info->col_en) *op |= op_flags; } spin_unlock_irqrestore(&hist_info->hist_lock, flag); mutex_unlock(&hist_info->hist_mutex); ret = 0; error: return ret; } Loading Loading @@ -2195,14 +2220,20 @@ static int pp_dspp_setup(u32 disp_num, struct mdss_mdp_mixer *mixer) (pp_driver_ops.gamut_clk_gate_en)) pp_driver_ops.gamut_clk_gate_en(base + mdata->pp_block_off.dspp_gamut_off); ret = pp_hist_setup(&opmode, MDSS_PP_DSPP_CFG | dspp_num, mixer); if (disp_num < MDSS_BLOCK_DISP_NUM) { pp_sts = &mdss_pp_res->pp_disp_sts[disp_num]; pp_sts->side_sts = side; ret = pp_hist_setup(&opmode, MDSS_PP_DSPP_CFG | dspp_num, mixer, pp_sts); if (ret) goto dspp_exit; if (disp_num < MDSS_BLOCK_DISP_NUM) flags = mdss_pp_res->pp_disp_flags[disp_num]; else } else { flags = 0; } mixer_cnt = mdss_mdp_get_ctl_mixers(disp_num, mixer_id); if (dspp_num < mdata->nad_cfgs && disp_num < mdata->nad_cfgs && Loading @@ -2218,9 +2249,6 @@ static int pp_dspp_setup(u32 disp_num, struct mdss_mdp_mixer *mixer) if ((!flags) && (!(opmode)) && (!ad_flags)) goto dspp_exit; pp_sts = &mdss_pp_res->pp_disp_sts[disp_num]; pp_sts->side_sts = side; if (flags & PP_FLAGS_DIRTY_PA) { if (!pp_ops[PA].pp_set_config) { if (mdata->mdp_rev >= MDSS_MDP_HW_REV_103) { Loading Loading @@ -2847,7 +2875,7 @@ int mdss_mdp_pp_init(struct device *dev) vig[i].pp_res.hist.intr_shift = 10; if (pp_driver_ops.get_hist_offset) { ret = pp_driver_ops.get_hist_offset( DSPP, &ctl_off); SSPP_VIG, &ctl_off); if (ret) { pr_err("get_hist_offset ret %d\n", ret); Loading Loading @@ -4803,7 +4831,7 @@ hist_stop_clk: } /** * mdss_mdp_hist_intr_req() - Request changes the histogram interupts * mdss_mdp_hist_intr_req() - Request changes the histogram interrupts * @intr: structure containting state of interrupt register * @bits: the bits on interrupt register that should be changed * @en: true if bits should be set, false if bits should be cleared Loading drivers/video/msm/mdss/mdss_mdp_pp_v1_7.c +3 −2 Original line number Diff line number Diff line Loading @@ -421,7 +421,7 @@ static int pp_hist_lut_get_config(char __iomem *base_addr, void *cfg_data, hist_addr += 4; } if (copy_to_user(lut_data->data, data, sz)) { pr_err("faild to copy the hist_lut back to user\n"); pr_err("failed to copy the hist_lut back to user\n"); ret = -EFAULT; } kfree(data); Loading Loading @@ -503,7 +503,8 @@ static int pp_hist_lut_set_config(char __iomem *base_addr, } if (lut_cfg_data->hist_lut_first) pp_sts->enhist_sts |= PP_STS_PA_LUT_FIRST; else pp_sts->enhist_sts &= ~PP_STS_PA_LUT_FIRST; writel_relaxed(1, swap_addr); Loading drivers/video/msm/mdss/mdss_mdp_pp_v3.c +304 −2 Original line number Diff line number Diff line Loading @@ -21,7 +21,7 @@ #include "mdss_mdp_pp_common.h" #define IGC_DSPP_OP_MODE_EN BIT(0) #define ENHIST_BIT_SHIFT 16 /* PA related define */ /* Offsets from DSPP/VIG base to PA block */ Loading Loading @@ -56,6 +56,24 @@ #define PA_LUTV_REG_OFF 0x200 #define PA_HIST_RAM_REG_OFF 0x400 /* histogram prototypes */ static int pp_get_hist_offset(u32 block, u32 *ctl_off); static int pp_hist_set_config(char __iomem *base_addr, struct pp_sts_type *pp_sts, void *cfg_data, u32 block_type); static int pp_hist_get_config(char __iomem *base_addr, void *cfg_data, u32 block_type, u32 disp_num); /* PA LUT prototypes */ static int pp_hist_lut_get_config(char __iomem *base_addr, void *cfg_data, u32 block_type, u32 disp_num); static int pp_hist_lut_set_config(char __iomem *base_addr, struct pp_sts_type *pp_sts, void *cfg_data, u32 block_type); static int pp_hist_lut_get_version(u32 *version); static void pp_hist_lut_opmode_config(char __iomem *base_addr, struct pp_sts_type *pp_sts); static int pp_pa_set_config(char __iomem *base_addr, struct pp_sts_type *pp_sts, void *cfg_data, u32 block_type); Loading Loading @@ -103,6 +121,16 @@ void *pp_get_driver_ops_v3(struct mdp_pp_driver_ops *ops) ops->pp_ops[PA].pp_get_config = pp_pa_get_config; ops->pp_ops[PA].pp_get_version = pp_pa_get_version; /* HIST_LUT ops */ ops->pp_ops[HIST_LUT].pp_set_config = pp_hist_lut_set_config; ops->pp_ops[HIST_LUT].pp_get_config = pp_hist_lut_get_config; ops->pp_ops[HIST_LUT].pp_get_version = pp_hist_lut_get_version; /* HIST ops */ ops->pp_ops[HIST].pp_set_config = pp_hist_set_config; ops->pp_ops[HIST].pp_get_config = pp_hist_get_config; ops->pp_ops[HIST].pp_get_version = NULL; /* Dither ops */ ops->pp_ops[DITHER].pp_set_config = pp_dither_set_config; ops->pp_ops[DITHER].pp_get_config = pp_dither_get_config; Loading @@ -111,10 +139,278 @@ void *pp_get_driver_ops_v3(struct mdp_pp_driver_ops *ops) /* Set opmode pointers */ ops->pp_opmode_config = pp_opmode_config; ops->get_hist_offset = pp_get_hist_offset; ops->gamut_clk_gate_en = NULL; return pp_cfg; } static int pp_get_hist_offset(u32 block, u32 *ctl_off) { int ret = 0; if (!ctl_off) { pr_err("invalid params ctl_off %p\n", ctl_off); return -EINVAL; } switch (block) { case SSPP_VIG: *ctl_off = PA_VIG_BLOCK_REG_OFF + PA_HIST_REG_OFF; break; case DSPP: *ctl_off = PA_DSPP_BLOCK_REG_OFF + PA_HIST_REG_OFF; break; default: pr_err("Invalid block type %d\n", block); ret = -EINVAL; break; } return ret; } static int pp_hist_set_config(char __iomem *base_addr, struct pp_sts_type *pp_sts, void *cfg_data, u32 block_type) { u32 opmode = 0; struct pp_hist_col_info *hist_info = NULL; if (!base_addr || !cfg_data || !pp_sts) { pr_err("invalid params base_addr %p cfg_data %p pp_sts_type %p\n", base_addr, cfg_data, pp_sts); return -EINVAL; } if (block_type != DSPP) { pr_err("Invalid block type %d\n", block_type); return -EINVAL; } hist_info = (struct pp_hist_col_info *)cfg_data; opmode = readl_relaxed(base_addr + PA_DSPP_BLOCK_REG_OFF + PA_OP_MODE_REG_OFF); /* set the hist_en bit */ if (hist_info->col_en) { pp_sts->hist_sts |= PP_STS_ENABLE; opmode |= BIT(16); } else { pp_sts->hist_sts &= ~PP_STS_ENABLE; opmode &= ~BIT(16); } writel_relaxed(opmode, base_addr + PA_DSPP_BLOCK_REG_OFF + PA_OP_MODE_REG_OFF); return 0; } static int pp_hist_get_config(char __iomem *base_addr, void *cfg_data, u32 block_type, u32 disp_num) { int i = 0; u32 sum = 0; struct pp_hist_col_info *hist_info = NULL; char __iomem *hist_addr; if (!base_addr || !cfg_data) { pr_err("invalid params base_addr %p cfg_data %p\n", base_addr, cfg_data); return -EINVAL; } if (block_type != DSPP) { pr_err("Invalid block type %d\n", block_type); return -EINVAL; } hist_info = (struct pp_hist_col_info *) cfg_data; hist_addr = base_addr + PA_DSPP_BLOCK_REG_OFF + PA_HIST_RAM_REG_OFF; for (i = 0; i < HIST_V_SIZE; i++) { hist_info->data[i] = readl_relaxed(hist_addr) & REG_MASK(24); hist_addr += 0x4; sum += hist_info->data[i]; } hist_info->hist_cnt_read++; return sum; } static int pp_hist_lut_get_config(char __iomem *base_addr, void *cfg_data, u32 block_type, u32 disp_num) { int ret = 0, i = 0; char __iomem *hist_lut_addr; u32 sz = 0, temp = 0, *data = NULL; struct mdp_hist_lut_data_v1_7 *lut_data = NULL; struct mdp_hist_lut_data *lut_cfg_data = NULL; if (!base_addr || !cfg_data) { pr_err("invalid params base_addr %p cfg_data %p\n", base_addr, cfg_data); return -EINVAL; } if (block_type != DSPP) { pr_err("Invalid block type %d\n", block_type); return -EINVAL; } lut_cfg_data = (struct mdp_hist_lut_data *) cfg_data; if (!(lut_cfg_data->ops & MDP_PP_OPS_READ)) { pr_err("read ops not set for hist_lut %d\n", lut_cfg_data->ops); return 0; } if (lut_cfg_data->version != mdp_hist_lut_v1_7 || !lut_cfg_data->cfg_payload) { pr_err("invalid hist_lut version %d payload %p\n", lut_cfg_data->version, lut_cfg_data->cfg_payload); return -EINVAL; } lut_data = lut_cfg_data->cfg_payload; if (lut_data->len != ENHIST_LUT_ENTRIES) { pr_err("invalid hist_lut len %d", lut_data->len); return -EINVAL; } sz = ENHIST_LUT_ENTRIES * sizeof(u32); if (!access_ok(VERIFY_WRITE, lut_data->data, sz)) { pr_err("invalid lut address for hist_lut sz %d\n", sz); return -EFAULT; } hist_lut_addr = base_addr + PA_DSPP_BLOCK_REG_OFF + PA_LUTV_REG_OFF; data = kzalloc(sz, GFP_KERNEL); if (!data) return -ENOMEM; for (i = 0; i < ENHIST_LUT_ENTRIES; i += 2) { temp = readl_relaxed(hist_lut_addr); data[i] = temp & REG_MASK(10); data[i + 1] = (temp & REG_MASK_SHIFT(10, 16)) >> ENHIST_BIT_SHIFT; hist_lut_addr += 4; } if (copy_to_user(lut_data->data, data, sz)) { pr_err("failed to copy the hist_lut back to user\n"); ret = -EFAULT; } kfree(data); return ret; } static int pp_hist_lut_set_config(char __iomem *base_addr, struct pp_sts_type *pp_sts, void *cfg_data, u32 block_type) { int ret = 0, i = 0; u32 temp = 0; struct mdp_hist_lut_data *lut_cfg_data = NULL; struct mdp_hist_lut_data_v1_7 *lut_data = NULL; char __iomem *hist_lut_addr = NULL, *swap_addr = NULL; if (!base_addr || !cfg_data || !pp_sts) { pr_err("invalid params base_addr %p cfg_data %p pp_sts_type %p\n", base_addr, cfg_data, pp_sts); return -EINVAL; } if (block_type != DSPP) { pr_err("Invalid block type %d\n", block_type); return -EINVAL; } lut_cfg_data = (struct mdp_hist_lut_data *) cfg_data; if (lut_cfg_data->version != mdp_hist_lut_v1_7) { pr_err("invalid hist_lut version %d\n", lut_cfg_data->version); return -EINVAL; } if (!(lut_cfg_data->ops & ~(MDP_PP_OPS_READ))) { pr_err("only read ops set for lut\n"); return ret; } if (lut_cfg_data->ops & MDP_PP_OPS_DISABLE || !(lut_cfg_data->ops & MDP_PP_OPS_WRITE)) { pr_debug("non write ops set %d\n", lut_cfg_data->ops); goto hist_lut_set_sts; } lut_data = lut_cfg_data->cfg_payload; if (!lut_data) { pr_err("invalid hist_lut cfg_payload %p\n", lut_data); return -EINVAL; } if (lut_data->len != ENHIST_LUT_ENTRIES || !lut_data->data) { pr_err("invalid hist_lut len %d data %p\n", lut_data->len, lut_data->data); return -EINVAL; } hist_lut_addr = base_addr + PA_DSPP_BLOCK_REG_OFF + PA_LUTV_REG_OFF; swap_addr = base_addr + PA_DSPP_BLOCK_REG_OFF + PA_LUTV_SWAP_REG_OFF; for (i = 0; i < ENHIST_LUT_ENTRIES; i += 2) { temp = (lut_data->data[i] & REG_MASK(10)) | ((lut_data->data[i + 1] & REG_MASK(10)) << ENHIST_BIT_SHIFT); writel_relaxed(temp, hist_lut_addr); hist_lut_addr += 4; } writel_relaxed(1, swap_addr); hist_lut_set_sts: if (lut_cfg_data->ops & MDP_PP_OPS_DISABLE) { pp_sts->enhist_sts &= ~(PP_STS_ENABLE | PP_STS_PA_LUT_FIRST); } else if (lut_cfg_data->ops & MDP_PP_OPS_ENABLE) { pp_sts->enhist_sts |= PP_STS_ENABLE; if (lut_cfg_data->hist_lut_first) pp_sts->enhist_sts |= PP_STS_PA_LUT_FIRST; else pp_sts->enhist_sts &= ~PP_STS_PA_LUT_FIRST; } pp_hist_lut_opmode_config(base_addr + PA_DSPP_BLOCK_REG_OFF, pp_sts); return ret; } static int pp_hist_lut_get_version(u32 *version) { if (!version) { pr_err("invalid param version %p\n", version); return -EINVAL; } *version = mdp_hist_lut_v1_7; return 0; } static void pp_hist_lut_opmode_config(char __iomem *base_addr, struct pp_sts_type *pp_sts) { u32 opmode = 0; if (!base_addr || !pp_sts) { pr_err("invalid params base_addr %p pp_sts_type %p\n", base_addr, pp_sts); return; } opmode = readl_relaxed(base_addr + PA_OP_MODE_REG_OFF); /* set the hist_lutv_en and hist_lutv_first_en bits */ if (pp_sts->enhist_sts & PP_STS_ENABLE) { opmode |= BIT(19) | BIT(20); opmode |= (pp_sts->enhist_sts & PP_STS_PA_LUT_FIRST) ? BIT(21) : 0; } else { opmode &= ~(BIT(19) | BIT(21)); if (!(pp_sts->pa_sts & PP_STS_ENABLE)) opmode &= ~BIT(20); } writel_relaxed(opmode, base_addr + PA_OP_MODE_REG_OFF); } static int pp_pa_set_config(char __iomem *base_addr, struct pp_sts_type *pp_sts, void *cfg_data, u32 block_type) Loading Loading @@ -427,9 +723,15 @@ static void pp_pa_opmode_config(char __iomem *base_addr, opmode |= BIT(17); } /* TODO: reset hist_en, hist_lutv_en and hist_lutv_first_en /* reset hist_en, hist_lutv_en and hist_lutv_first_en bits based on the pp_sts */ if (pp_sts->hist_sts & PP_STS_ENABLE) opmode |= BIT(16); if (pp_sts->enhist_sts & PP_STS_ENABLE) opmode |= BIT(19) | BIT(20); if (pp_sts->enhist_sts & PP_STS_PA_LUT_FIRST) opmode |= BIT(21); writel_relaxed(opmode, base_addr + PA_OP_MODE_REG_OFF); } Loading
drivers/video/msm/mdss/mdss_mdp.h +1 −0 Original line number Diff line number Diff line Loading @@ -618,6 +618,7 @@ struct pp_sts_type { u32 gamut_sts; u32 pgc_sts; u32 sharp_sts; u32 hist_sts; u32 side_sts; }; Loading
drivers/video/msm/mdss/mdss_mdp_pp.c +46 −18 Original line number Diff line number Diff line Loading @@ -407,7 +407,8 @@ static struct mdss_pp_res_type *mdss_pp_res; static u32 pp_hist_read(char __iomem *v_addr, struct pp_hist_col_info *hist_info); static int pp_hist_setup(u32 *op, u32 block, struct mdss_mdp_mixer *mix); static int pp_hist_setup(u32 *op, u32 block, struct mdss_mdp_mixer *mix, struct pp_sts_type *pp_sts); static int pp_hist_disable(struct pp_hist_col_info *hist_info); static void pp_update_pcc_regs(char __iomem *addr, struct mdp_pcc_cfg_data *cfg_ptr); Loading Loading @@ -1048,7 +1049,8 @@ static int pp_vig_pipe_setup(struct mdss_mdp_pipe *pipe, u32 *op) } /* Histogram collection enabled checked inside pp_hist_setup */ pp_hist_setup(op, MDSS_PP_SSPP_CFG | pipe->num, pipe->mixer_left); pp_hist_setup(op, MDSS_PP_SSPP_CFG | pipe->num, pipe->mixer_left, &pipe->pp_res.pp_sts); if (!(pipe->flags & MDP_OVERLAY_PP_CFG_EN)) { pr_debug("Overlay PP CFG enable not set\n"); Loading Loading @@ -2002,11 +2004,12 @@ static char __iomem *mdss_mdp_get_dspp_addr_off(u32 dspp_num) } /* Assumes that function will be called from within clock enabled space*/ static int pp_hist_setup(u32 *op, u32 block, struct mdss_mdp_mixer *mix) static int pp_hist_setup(u32 *op, u32 block, struct mdss_mdp_mixer *mix, struct pp_sts_type *pp_sts) { int ret = -EINVAL; int ret = 0; char __iomem *base; u32 op_flags; u32 op_flags = 0, block_type = 0; struct mdss_mdp_pipe *pipe; struct pp_hist_col_info *hist_info; unsigned long flag; Loading @@ -2019,6 +2022,7 @@ static int pp_hist_setup(u32 *op, u32 block, struct mdss_mdp_mixer *mix) intr_mask = 1; if (mix && (PP_LOCAT(block) == MDSS_PP_DSPP_CFG)) { /* HIST_EN */ block_type = DSPP; op_flags = BIT(16); hist_info = &mdss_pp_res->dspp_hist[mix->num]; base = mdss_mdp_get_dspp_addr_off(PP_BLOCK(block)); Loading @@ -2029,6 +2033,7 @@ static int pp_hist_setup(u32 *op, u32 block, struct mdss_mdp_mixer *mix) } else if (PP_LOCAT(block) == MDSS_PP_SSPP_CFG && (pp_driver_ops.is_sspp_hist_supp) && (pp_driver_ops.is_sspp_hist_supp())) { block_type = SSPP_VIG; pipe = __get_hist_pipe(PP_BLOCK(block)); if (IS_ERR_OR_NULL(pipe)) { pr_debug("pipe DNE (%d)\n", Loading @@ -2041,18 +2046,38 @@ static int pp_hist_setup(u32 *op, u32 block, struct mdss_mdp_mixer *mix) base = pipe->base; mdss_mdp_pipe_unmap(pipe); } else { ret = -EINVAL; goto error; } mutex_lock(&hist_info->hist_mutex); spin_lock_irqsave(&hist_info->hist_lock, flag); if (hist_info->col_en) { /* * Set histogram interrupt if histogram collection is enabled. The * interrupt register offsets are the same across different mdss * versions so far, hence mdss_mdp_hist_irq_set_mask is used for * all the mdss versions. */ if (hist_info->col_en) mdss_mdp_hist_irq_set_mask(intr_mask << hist_info->intr_shift); /* * Starting from msmcobalt, the histogram enable bit has been moved * from DSPP opmode register to PA_HIST opmode register, hence we need * to update the histogram enable bit differently based on mdss version. * If HIST pp_set_config is defined, we will enable or disable the * hist_en bit in PA_HIST opmode register inside HIST pp_set_config * function; else, we only need to add the hist_en bit to the *op when * histogram collection is enable, and *op will be passed to * pp_dspp_setup to update the DSPP opmode register. */ if (pp_ops[HIST].pp_set_config) ret = pp_ops[HIST].pp_set_config(base, pp_sts, hist_info, block_type); else if (hist_info->col_en) *op |= op_flags; } spin_unlock_irqrestore(&hist_info->hist_lock, flag); mutex_unlock(&hist_info->hist_mutex); ret = 0; error: return ret; } Loading Loading @@ -2195,14 +2220,20 @@ static int pp_dspp_setup(u32 disp_num, struct mdss_mdp_mixer *mixer) (pp_driver_ops.gamut_clk_gate_en)) pp_driver_ops.gamut_clk_gate_en(base + mdata->pp_block_off.dspp_gamut_off); ret = pp_hist_setup(&opmode, MDSS_PP_DSPP_CFG | dspp_num, mixer); if (disp_num < MDSS_BLOCK_DISP_NUM) { pp_sts = &mdss_pp_res->pp_disp_sts[disp_num]; pp_sts->side_sts = side; ret = pp_hist_setup(&opmode, MDSS_PP_DSPP_CFG | dspp_num, mixer, pp_sts); if (ret) goto dspp_exit; if (disp_num < MDSS_BLOCK_DISP_NUM) flags = mdss_pp_res->pp_disp_flags[disp_num]; else } else { flags = 0; } mixer_cnt = mdss_mdp_get_ctl_mixers(disp_num, mixer_id); if (dspp_num < mdata->nad_cfgs && disp_num < mdata->nad_cfgs && Loading @@ -2218,9 +2249,6 @@ static int pp_dspp_setup(u32 disp_num, struct mdss_mdp_mixer *mixer) if ((!flags) && (!(opmode)) && (!ad_flags)) goto dspp_exit; pp_sts = &mdss_pp_res->pp_disp_sts[disp_num]; pp_sts->side_sts = side; if (flags & PP_FLAGS_DIRTY_PA) { if (!pp_ops[PA].pp_set_config) { if (mdata->mdp_rev >= MDSS_MDP_HW_REV_103) { Loading Loading @@ -2847,7 +2875,7 @@ int mdss_mdp_pp_init(struct device *dev) vig[i].pp_res.hist.intr_shift = 10; if (pp_driver_ops.get_hist_offset) { ret = pp_driver_ops.get_hist_offset( DSPP, &ctl_off); SSPP_VIG, &ctl_off); if (ret) { pr_err("get_hist_offset ret %d\n", ret); Loading Loading @@ -4803,7 +4831,7 @@ hist_stop_clk: } /** * mdss_mdp_hist_intr_req() - Request changes the histogram interupts * mdss_mdp_hist_intr_req() - Request changes the histogram interrupts * @intr: structure containting state of interrupt register * @bits: the bits on interrupt register that should be changed * @en: true if bits should be set, false if bits should be cleared Loading
drivers/video/msm/mdss/mdss_mdp_pp_v1_7.c +3 −2 Original line number Diff line number Diff line Loading @@ -421,7 +421,7 @@ static int pp_hist_lut_get_config(char __iomem *base_addr, void *cfg_data, hist_addr += 4; } if (copy_to_user(lut_data->data, data, sz)) { pr_err("faild to copy the hist_lut back to user\n"); pr_err("failed to copy the hist_lut back to user\n"); ret = -EFAULT; } kfree(data); Loading Loading @@ -503,7 +503,8 @@ static int pp_hist_lut_set_config(char __iomem *base_addr, } if (lut_cfg_data->hist_lut_first) pp_sts->enhist_sts |= PP_STS_PA_LUT_FIRST; else pp_sts->enhist_sts &= ~PP_STS_PA_LUT_FIRST; writel_relaxed(1, swap_addr); Loading
drivers/video/msm/mdss/mdss_mdp_pp_v3.c +304 −2 Original line number Diff line number Diff line Loading @@ -21,7 +21,7 @@ #include "mdss_mdp_pp_common.h" #define IGC_DSPP_OP_MODE_EN BIT(0) #define ENHIST_BIT_SHIFT 16 /* PA related define */ /* Offsets from DSPP/VIG base to PA block */ Loading Loading @@ -56,6 +56,24 @@ #define PA_LUTV_REG_OFF 0x200 #define PA_HIST_RAM_REG_OFF 0x400 /* histogram prototypes */ static int pp_get_hist_offset(u32 block, u32 *ctl_off); static int pp_hist_set_config(char __iomem *base_addr, struct pp_sts_type *pp_sts, void *cfg_data, u32 block_type); static int pp_hist_get_config(char __iomem *base_addr, void *cfg_data, u32 block_type, u32 disp_num); /* PA LUT prototypes */ static int pp_hist_lut_get_config(char __iomem *base_addr, void *cfg_data, u32 block_type, u32 disp_num); static int pp_hist_lut_set_config(char __iomem *base_addr, struct pp_sts_type *pp_sts, void *cfg_data, u32 block_type); static int pp_hist_lut_get_version(u32 *version); static void pp_hist_lut_opmode_config(char __iomem *base_addr, struct pp_sts_type *pp_sts); static int pp_pa_set_config(char __iomem *base_addr, struct pp_sts_type *pp_sts, void *cfg_data, u32 block_type); Loading Loading @@ -103,6 +121,16 @@ void *pp_get_driver_ops_v3(struct mdp_pp_driver_ops *ops) ops->pp_ops[PA].pp_get_config = pp_pa_get_config; ops->pp_ops[PA].pp_get_version = pp_pa_get_version; /* HIST_LUT ops */ ops->pp_ops[HIST_LUT].pp_set_config = pp_hist_lut_set_config; ops->pp_ops[HIST_LUT].pp_get_config = pp_hist_lut_get_config; ops->pp_ops[HIST_LUT].pp_get_version = pp_hist_lut_get_version; /* HIST ops */ ops->pp_ops[HIST].pp_set_config = pp_hist_set_config; ops->pp_ops[HIST].pp_get_config = pp_hist_get_config; ops->pp_ops[HIST].pp_get_version = NULL; /* Dither ops */ ops->pp_ops[DITHER].pp_set_config = pp_dither_set_config; ops->pp_ops[DITHER].pp_get_config = pp_dither_get_config; Loading @@ -111,10 +139,278 @@ void *pp_get_driver_ops_v3(struct mdp_pp_driver_ops *ops) /* Set opmode pointers */ ops->pp_opmode_config = pp_opmode_config; ops->get_hist_offset = pp_get_hist_offset; ops->gamut_clk_gate_en = NULL; return pp_cfg; } static int pp_get_hist_offset(u32 block, u32 *ctl_off) { int ret = 0; if (!ctl_off) { pr_err("invalid params ctl_off %p\n", ctl_off); return -EINVAL; } switch (block) { case SSPP_VIG: *ctl_off = PA_VIG_BLOCK_REG_OFF + PA_HIST_REG_OFF; break; case DSPP: *ctl_off = PA_DSPP_BLOCK_REG_OFF + PA_HIST_REG_OFF; break; default: pr_err("Invalid block type %d\n", block); ret = -EINVAL; break; } return ret; } static int pp_hist_set_config(char __iomem *base_addr, struct pp_sts_type *pp_sts, void *cfg_data, u32 block_type) { u32 opmode = 0; struct pp_hist_col_info *hist_info = NULL; if (!base_addr || !cfg_data || !pp_sts) { pr_err("invalid params base_addr %p cfg_data %p pp_sts_type %p\n", base_addr, cfg_data, pp_sts); return -EINVAL; } if (block_type != DSPP) { pr_err("Invalid block type %d\n", block_type); return -EINVAL; } hist_info = (struct pp_hist_col_info *)cfg_data; opmode = readl_relaxed(base_addr + PA_DSPP_BLOCK_REG_OFF + PA_OP_MODE_REG_OFF); /* set the hist_en bit */ if (hist_info->col_en) { pp_sts->hist_sts |= PP_STS_ENABLE; opmode |= BIT(16); } else { pp_sts->hist_sts &= ~PP_STS_ENABLE; opmode &= ~BIT(16); } writel_relaxed(opmode, base_addr + PA_DSPP_BLOCK_REG_OFF + PA_OP_MODE_REG_OFF); return 0; } static int pp_hist_get_config(char __iomem *base_addr, void *cfg_data, u32 block_type, u32 disp_num) { int i = 0; u32 sum = 0; struct pp_hist_col_info *hist_info = NULL; char __iomem *hist_addr; if (!base_addr || !cfg_data) { pr_err("invalid params base_addr %p cfg_data %p\n", base_addr, cfg_data); return -EINVAL; } if (block_type != DSPP) { pr_err("Invalid block type %d\n", block_type); return -EINVAL; } hist_info = (struct pp_hist_col_info *) cfg_data; hist_addr = base_addr + PA_DSPP_BLOCK_REG_OFF + PA_HIST_RAM_REG_OFF; for (i = 0; i < HIST_V_SIZE; i++) { hist_info->data[i] = readl_relaxed(hist_addr) & REG_MASK(24); hist_addr += 0x4; sum += hist_info->data[i]; } hist_info->hist_cnt_read++; return sum; } static int pp_hist_lut_get_config(char __iomem *base_addr, void *cfg_data, u32 block_type, u32 disp_num) { int ret = 0, i = 0; char __iomem *hist_lut_addr; u32 sz = 0, temp = 0, *data = NULL; struct mdp_hist_lut_data_v1_7 *lut_data = NULL; struct mdp_hist_lut_data *lut_cfg_data = NULL; if (!base_addr || !cfg_data) { pr_err("invalid params base_addr %p cfg_data %p\n", base_addr, cfg_data); return -EINVAL; } if (block_type != DSPP) { pr_err("Invalid block type %d\n", block_type); return -EINVAL; } lut_cfg_data = (struct mdp_hist_lut_data *) cfg_data; if (!(lut_cfg_data->ops & MDP_PP_OPS_READ)) { pr_err("read ops not set for hist_lut %d\n", lut_cfg_data->ops); return 0; } if (lut_cfg_data->version != mdp_hist_lut_v1_7 || !lut_cfg_data->cfg_payload) { pr_err("invalid hist_lut version %d payload %p\n", lut_cfg_data->version, lut_cfg_data->cfg_payload); return -EINVAL; } lut_data = lut_cfg_data->cfg_payload; if (lut_data->len != ENHIST_LUT_ENTRIES) { pr_err("invalid hist_lut len %d", lut_data->len); return -EINVAL; } sz = ENHIST_LUT_ENTRIES * sizeof(u32); if (!access_ok(VERIFY_WRITE, lut_data->data, sz)) { pr_err("invalid lut address for hist_lut sz %d\n", sz); return -EFAULT; } hist_lut_addr = base_addr + PA_DSPP_BLOCK_REG_OFF + PA_LUTV_REG_OFF; data = kzalloc(sz, GFP_KERNEL); if (!data) return -ENOMEM; for (i = 0; i < ENHIST_LUT_ENTRIES; i += 2) { temp = readl_relaxed(hist_lut_addr); data[i] = temp & REG_MASK(10); data[i + 1] = (temp & REG_MASK_SHIFT(10, 16)) >> ENHIST_BIT_SHIFT; hist_lut_addr += 4; } if (copy_to_user(lut_data->data, data, sz)) { pr_err("failed to copy the hist_lut back to user\n"); ret = -EFAULT; } kfree(data); return ret; } static int pp_hist_lut_set_config(char __iomem *base_addr, struct pp_sts_type *pp_sts, void *cfg_data, u32 block_type) { int ret = 0, i = 0; u32 temp = 0; struct mdp_hist_lut_data *lut_cfg_data = NULL; struct mdp_hist_lut_data_v1_7 *lut_data = NULL; char __iomem *hist_lut_addr = NULL, *swap_addr = NULL; if (!base_addr || !cfg_data || !pp_sts) { pr_err("invalid params base_addr %p cfg_data %p pp_sts_type %p\n", base_addr, cfg_data, pp_sts); return -EINVAL; } if (block_type != DSPP) { pr_err("Invalid block type %d\n", block_type); return -EINVAL; } lut_cfg_data = (struct mdp_hist_lut_data *) cfg_data; if (lut_cfg_data->version != mdp_hist_lut_v1_7) { pr_err("invalid hist_lut version %d\n", lut_cfg_data->version); return -EINVAL; } if (!(lut_cfg_data->ops & ~(MDP_PP_OPS_READ))) { pr_err("only read ops set for lut\n"); return ret; } if (lut_cfg_data->ops & MDP_PP_OPS_DISABLE || !(lut_cfg_data->ops & MDP_PP_OPS_WRITE)) { pr_debug("non write ops set %d\n", lut_cfg_data->ops); goto hist_lut_set_sts; } lut_data = lut_cfg_data->cfg_payload; if (!lut_data) { pr_err("invalid hist_lut cfg_payload %p\n", lut_data); return -EINVAL; } if (lut_data->len != ENHIST_LUT_ENTRIES || !lut_data->data) { pr_err("invalid hist_lut len %d data %p\n", lut_data->len, lut_data->data); return -EINVAL; } hist_lut_addr = base_addr + PA_DSPP_BLOCK_REG_OFF + PA_LUTV_REG_OFF; swap_addr = base_addr + PA_DSPP_BLOCK_REG_OFF + PA_LUTV_SWAP_REG_OFF; for (i = 0; i < ENHIST_LUT_ENTRIES; i += 2) { temp = (lut_data->data[i] & REG_MASK(10)) | ((lut_data->data[i + 1] & REG_MASK(10)) << ENHIST_BIT_SHIFT); writel_relaxed(temp, hist_lut_addr); hist_lut_addr += 4; } writel_relaxed(1, swap_addr); hist_lut_set_sts: if (lut_cfg_data->ops & MDP_PP_OPS_DISABLE) { pp_sts->enhist_sts &= ~(PP_STS_ENABLE | PP_STS_PA_LUT_FIRST); } else if (lut_cfg_data->ops & MDP_PP_OPS_ENABLE) { pp_sts->enhist_sts |= PP_STS_ENABLE; if (lut_cfg_data->hist_lut_first) pp_sts->enhist_sts |= PP_STS_PA_LUT_FIRST; else pp_sts->enhist_sts &= ~PP_STS_PA_LUT_FIRST; } pp_hist_lut_opmode_config(base_addr + PA_DSPP_BLOCK_REG_OFF, pp_sts); return ret; } static int pp_hist_lut_get_version(u32 *version) { if (!version) { pr_err("invalid param version %p\n", version); return -EINVAL; } *version = mdp_hist_lut_v1_7; return 0; } static void pp_hist_lut_opmode_config(char __iomem *base_addr, struct pp_sts_type *pp_sts) { u32 opmode = 0; if (!base_addr || !pp_sts) { pr_err("invalid params base_addr %p pp_sts_type %p\n", base_addr, pp_sts); return; } opmode = readl_relaxed(base_addr + PA_OP_MODE_REG_OFF); /* set the hist_lutv_en and hist_lutv_first_en bits */ if (pp_sts->enhist_sts & PP_STS_ENABLE) { opmode |= BIT(19) | BIT(20); opmode |= (pp_sts->enhist_sts & PP_STS_PA_LUT_FIRST) ? BIT(21) : 0; } else { opmode &= ~(BIT(19) | BIT(21)); if (!(pp_sts->pa_sts & PP_STS_ENABLE)) opmode &= ~BIT(20); } writel_relaxed(opmode, base_addr + PA_OP_MODE_REG_OFF); } static int pp_pa_set_config(char __iomem *base_addr, struct pp_sts_type *pp_sts, void *cfg_data, u32 block_type) Loading Loading @@ -427,9 +723,15 @@ static void pp_pa_opmode_config(char __iomem *base_addr, opmode |= BIT(17); } /* TODO: reset hist_en, hist_lutv_en and hist_lutv_first_en /* reset hist_en, hist_lutv_en and hist_lutv_first_en bits based on the pp_sts */ if (pp_sts->hist_sts & PP_STS_ENABLE) opmode |= BIT(16); if (pp_sts->enhist_sts & PP_STS_ENABLE) opmode |= BIT(19) | BIT(20); if (pp_sts->enhist_sts & PP_STS_PA_LUT_FIRST) opmode |= BIT(21); writel_relaxed(opmode, base_addr + PA_OP_MODE_REG_OFF); }