Loading drivers/gpu/drm/msm/sde/sde_ad4.h +1 −0 Original line number Diff line number Diff line Loading @@ -49,6 +49,7 @@ enum ad_property { AD_ASSERTIVE, AD_BACKLIGHT, AD_STRENGTH, AD_ROI, AD_IPC_SUSPEND, AD_IPC_RESUME, AD_IPC_RESET, Loading drivers/gpu/drm/msm/sde/sde_color_processing.c +19 −0 Original line number Diff line number Diff line Loading @@ -137,6 +137,7 @@ enum { SDE_CP_CRTC_DSPP_AD_ASSERTIVENESS, SDE_CP_CRTC_DSPP_AD_BACKLIGHT, SDE_CP_CRTC_DSPP_AD_STRENGTH, SDE_CP_CRTC_DSPP_AD_ROI, SDE_CP_CRTC_DSPP_MAX, /* DSPP features end */ Loading Loading @@ -826,6 +827,15 @@ static void sde_cp_crtc_setfeature(struct sde_cp_node *prop_node, ad_cfg.hw_cfg = &hw_cfg; hw_dspp->ops.setup_ad(hw_dspp, &ad_cfg); break; case SDE_CP_CRTC_DSPP_AD_ROI: if (!hw_dspp || !hw_dspp->ops.setup_ad) { ret = -EINVAL; continue; } ad_cfg.prop = AD_ROI; ad_cfg.hw_cfg = &hw_cfg; hw_dspp->ops.setup_ad(hw_dspp, &ad_cfg); break; default: ret = -EINVAL; break; Loading Loading @@ -1427,6 +1437,11 @@ static void dspp_ad_install_property(struct drm_crtc *crtc) "SDE_DSPP_AD_V4_BACKLIGHT", SDE_CP_CRTC_DSPP_AD_BACKLIGHT, 0, (BIT(16) - 1), 0); sde_cp_crtc_install_range_property(crtc, "SDE_DSPP_AD_V4_ROI", SDE_CP_CRTC_DSPP_AD_ROI, 0, U64_MAX, 0); sde_cp_create_local_blob(crtc, SDE_CP_CRTC_DSPP_AD_ROI, sizeof(struct drm_msm_ad4_roi_cfg)); break; default: DRM_ERROR("version %d not supported\n", version); Loading Loading @@ -1590,6 +1605,7 @@ static void sde_cp_update_list(struct sde_cp_node *prop_node, case SDE_CP_CRTC_DSPP_AD_ASSERTIVENESS: case SDE_CP_CRTC_DSPP_AD_BACKLIGHT: case SDE_CP_CRTC_DSPP_AD_STRENGTH: case SDE_CP_CRTC_DSPP_AD_ROI: if (dirty_list) list_add_tail(&prop_node->dirty_list, &crtc->ad_dirty); else Loading Loading @@ -1641,6 +1657,9 @@ static int sde_cp_ad_validate_prop(struct sde_cp_node *prop_node, case SDE_CP_CRTC_DSPP_AD_STRENGTH: ad_prop = AD_STRENGTH; break; case SDE_CP_CRTC_DSPP_AD_ROI: ad_prop = AD_ROI; break; default: /* Not an AD property */ return 0; Loading drivers/gpu/drm/msm/sde/sde_hw_ad4.c +250 −34 Original line number Diff line number Diff line Loading @@ -48,6 +48,15 @@ enum ad4_state { ad4_state_max, }; struct ad4_roi_info { u32 h_start; u32 h_end; u32 v_start; u32 v_end; u32 f_in; u32 f_out; }; typedef int (*ad4_prop_setup)(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *ad); Loading Loading @@ -77,6 +86,11 @@ static int ad4_cfg_setup_ipcr(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg); static int ad4_input_setup(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg); static int ad4_roi_setup(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg); static int ad4_roi_setup_ipcr(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg); static int ad4_roi_coordinate_offset(struct sde_hw_cp_cfg *hw_cfg, struct ad4_roi_info *output); static int ad4_input_setup_idle(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg); static int ad4_input_setup_ipcr(struct sde_hw_dspp *dspp, Loading Loading @@ -118,6 +132,7 @@ static ad4_prop_setup prop_set_func[ad4_state_max][AD_PROPMAX] = { [ad4_state_idle][AD_ASSERTIVE] = ad4_assertive_setup, [ad4_state_idle][AD_BACKLIGHT] = ad4_backlight_setup, [ad4_state_idle][AD_STRENGTH] = ad4_strength_setup_idle, [ad4_state_idle][AD_ROI] = ad4_no_op_setup, [ad4_state_idle][AD_IPC_SUSPEND] = ad4_no_op_setup, [ad4_state_idle][AD_IPC_RESUME] = ad4_no_op_setup, [ad4_state_idle][AD_IPC_RESET] = ad4_no_op_setup, Loading @@ -131,6 +146,7 @@ static ad4_prop_setup prop_set_func[ad4_state_max][AD_PROPMAX] = { [ad4_state_startup][AD_BACKLIGHT] = ad4_backlight_setup, [ad4_state_startup][AD_IPC_SUSPEND] = ad4_no_op_setup, [ad4_state_startup][AD_STRENGTH] = ad4_no_op_setup, [ad4_state_startup][AD_ROI] = ad4_roi_setup, [ad4_state_startup][AD_IPC_RESUME] = ad4_no_op_setup, [ad4_state_startup][AD_IPC_RESET] = ad4_ipc_reset_setup_startup, Loading @@ -142,6 +158,7 @@ static ad4_prop_setup prop_set_func[ad4_state_max][AD_PROPMAX] = { [ad4_state_run][AD_ASSERTIVE] = ad4_assertive_setup, [ad4_state_run][AD_BACKLIGHT] = ad4_backlight_setup, [ad4_state_run][AD_STRENGTH] = ad4_no_op_setup, [ad4_state_run][AD_ROI] = ad4_roi_setup, [ad4_state_run][AD_IPC_SUSPEND] = ad4_ipc_suspend_setup_run, [ad4_state_run][AD_IPC_RESUME] = ad4_no_op_setup, [ad4_state_run][AD_IPC_RESET] = ad4_setup_debug, Loading @@ -154,6 +171,7 @@ static ad4_prop_setup prop_set_func[ad4_state_max][AD_PROPMAX] = { [ad4_state_ipcs][AD_ASSERTIVE] = ad4_no_op_setup, [ad4_state_ipcs][AD_BACKLIGHT] = ad4_no_op_setup, [ad4_state_ipcs][AD_STRENGTH] = ad4_no_op_setup, [ad4_state_ipcs][AD_ROI] = ad4_no_op_setup, [ad4_state_ipcs][AD_IPC_SUSPEND] = ad4_no_op_setup, [ad4_state_ipcs][AD_IPC_RESUME] = ad4_ipc_resume_setup_ipcs, [ad4_state_ipcs][AD_IPC_RESET] = ad4_no_op_setup, Loading @@ -166,6 +184,7 @@ static ad4_prop_setup prop_set_func[ad4_state_max][AD_PROPMAX] = { [ad4_state_ipcr][AD_ASSERTIVE] = ad4_assertive_setup_ipcr, [ad4_state_ipcr][AD_BACKLIGHT] = ad4_backlight_setup_ipcr, [ad4_state_ipcr][AD_STRENGTH] = ad4_no_op_setup, [ad4_state_ipcr][AD_ROI] = ad4_roi_setup_ipcr, [ad4_state_ipcr][AD_IPC_SUSPEND] = ad4_ipc_suspend_setup_ipcr, [ad4_state_ipcr][AD_IPC_RESUME] = ad4_no_op_setup, [ad4_state_ipcr][AD_IPC_RESET] = ad4_ipc_reset_setup_ipcr, Loading @@ -178,6 +197,7 @@ static ad4_prop_setup prop_set_func[ad4_state_max][AD_PROPMAX] = { [ad4_state_manual][AD_ASSERTIVE] = ad4_no_op_setup, [ad4_state_manual][AD_BACKLIGHT] = ad4_no_op_setup, [ad4_state_manual][AD_STRENGTH] = ad4_strength_setup, [ad4_state_manual][AD_ROI] = ad4_no_op_setup, [ad4_state_manual][AD_IPC_SUSPEND] = ad4_no_op_setup, [ad4_state_manual][AD_IPC_RESUME] = ad4_no_op_setup, [ad4_state_manual][AD_IPC_RESET] = ad4_setup_debug_manual, Loading @@ -191,16 +211,19 @@ struct ad4_info { bool is_master; u32 last_assertive; u32 cached_assertive; u32 last_str_inroi; u32 last_str_outroi; u64 last_als; u64 cached_als; u64 last_bl; u64 cached_bl; u32 last_str; u32 frame_count; u32 frmt_mode; u32 irdx_control_0; u32 tf_ctrl; u32 vc_control_0; struct ad4_roi_info last_roi_cfg; struct ad4_roi_info cached_roi_cfg; }; static struct ad4_info info[DSPP_MAX] = { Loading Loading @@ -319,7 +342,7 @@ static int ad4_no_op_setup(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg) static int ad4_setup_debug(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg) { u32 strength = 0; u32 in_str = 0, out_str = 0; struct sde_hw_mixer *hw_lm; hw_lm = cfg->hw_cfg->mixer_info; Loading @@ -327,9 +350,10 @@ static int ad4_setup_debug(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg) /* this AD core is the salve core */ return 0; strength = SDE_REG_READ(&dspp->hw, dspp->cap->sblk->ad.base + 0x4c); pr_debug("%s(): AD strength = %d\n", __func__, strength); in_str = SDE_REG_READ(&dspp->hw, dspp->cap->sblk->ad.base + 0x4c); out_str = SDE_REG_READ(&dspp->hw, dspp->cap->sblk->ad.base + 0x50); pr_debug("%s(): AD in strength %d, out strength %d\n", __func__, in_str, out_str); return 0; } Loading Loading @@ -368,6 +392,18 @@ static int ad4_mode_setup(struct sde_hw_dspp *dspp, enum ad4_modes mode) info[dspp->idx].cached_bl = U64_MAX; info[dspp->idx].last_als = 0x0; info[dspp->idx].cached_als = U64_MAX; info[dspp->idx].last_roi_cfg.h_start = 0x0; info[dspp->idx].last_roi_cfg.h_end = 0xffff; info[dspp->idx].last_roi_cfg.v_start = 0x0; info[dspp->idx].last_roi_cfg.v_end = 0xffff; info[dspp->idx].last_roi_cfg.f_in = 0x400; info[dspp->idx].last_roi_cfg.f_out = 0x400; info[dspp->idx].cached_roi_cfg.h_start = U32_MAX; info[dspp->idx].cached_roi_cfg.h_end = U32_MAX; info[dspp->idx].cached_roi_cfg.v_start = U32_MAX; info[dspp->idx].cached_roi_cfg.v_end = U32_MAX; info[dspp->idx].cached_roi_cfg.f_in = U32_MAX; info[dspp->idx].cached_roi_cfg.f_out = U32_MAX; } else { if (mode == AD4_MANUAL) { /*vc_control_0 */ Loading Loading @@ -768,15 +804,6 @@ static int ad4_cfg_setup(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg) } ad_cfg = cfg->hw_cfg->payload; blk_offset = 0x18; val = (ad_cfg->cfg_param_002 & (BIT(16) - 1)); val |= ((ad_cfg->cfg_param_001 & (BIT(16) - 1)) << 16); SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val); blk_offset += 4; val = (ad_cfg->cfg_param_004 & (BIT(16) - 1)); val |= ((ad_cfg->cfg_param_003 & (BIT(16) - 1)) << 16); SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val); blk_offset = 0x20; val = (ad_cfg->cfg_param_005 & (BIT(8) - 1)); SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val); Loading @@ -793,10 +820,6 @@ static int ad4_cfg_setup(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg) blk_offset = 0x3c; val = (ad_cfg->cfg_param_010 & (BIT(12) - 1)); SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val); blk_offset += 4; val = ((ad_cfg->cfg_param_011 & (BIT(16) - 1)) << 16); val |= (ad_cfg->cfg_param_012 & (BIT(16) - 1)); SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val); blk_offset = 0x88; val = (ad_cfg->cfg_param_013 & (BIT(8) - 1)); Loading Loading @@ -891,10 +914,6 @@ static int ad4_cfg_setup(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg) info[dspp->idx].vc_control_0 = (ad_cfg->cfg_param_041 & (BIT(7) - 1)); blk_offset = 0x160; val = (ad_cfg->cfg_param_043 & (BIT(10) - 1)); SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val); blk_offset = 0x16c; val = (ad_cfg->cfg_param_044 & (BIT(8) - 1)); SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val); Loading Loading @@ -934,6 +953,145 @@ static int ad4_input_setup(struct sde_hw_dspp *dspp, return 0; } static int ad4_roi_setup(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg) { int ret = 0; u32 blk_offset = 0, val = 0; struct ad4_roi_info roi_cfg = {}; ret = ad4_roi_coordinate_offset(cfg->hw_cfg, &roi_cfg); if (ret) { DRM_ERROR("params invalid\n"); return -EINVAL; } info[dspp->idx].last_roi_cfg = roi_cfg; /*roi h start and end*/ blk_offset = 0x18; val = (info[dspp->idx].last_roi_cfg.h_end & (BIT(16) - 1)); val |= ((info[dspp->idx].last_roi_cfg.h_start & (BIT(16) - 1)) << 16); SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val); /*roi v start and end*/ blk_offset += 4; val = (info[dspp->idx].last_roi_cfg.v_end & (BIT(16) - 1)); val |= ((info[dspp->idx].last_roi_cfg.v_start & (BIT(16) - 1)) << 16); SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val); /*roi factor in and out*/ blk_offset = 0x40; val = ((info[dspp->idx].last_roi_cfg.f_in & (BIT(16) - 1)) << 16); val |= (info[dspp->idx].last_roi_cfg.f_out & (BIT(16) - 1)); SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val); return ret; } static int ad4_roi_setup_ipcr(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg) { int ret = 0; struct ad4_roi_info roi_cfg = {}; ret = ad4_roi_coordinate_offset(cfg->hw_cfg, &roi_cfg); if (ret) { DRM_ERROR("params invalid\n"); return -EINVAL; } info[dspp->idx].cached_roi_cfg = roi_cfg; return 0; } static int ad4_roi_coordinate_offset(struct sde_hw_cp_cfg *hw_cfg, struct ad4_roi_info *output) { struct sde_hw_mixer *hw_lm = hw_cfg->mixer_info; struct drm_msm_ad4_roi_cfg *roi = NULL; if (!hw_cfg->payload) { output->h_start = 0x0; output->h_end = hw_cfg->displayh; output->v_start = 0x0; output->v_end = hw_cfg->displayv; output->f_in = 0x400; output->f_out = 0x400; return 0; } if (hw_cfg->len != sizeof(struct drm_msm_ad4_roi_cfg)) { DRM_ERROR("invalid sz param exp %zd given %d cfg %pK\n", sizeof(struct drm_msm_ad4_roi_cfg), hw_cfg->len, hw_cfg->payload); return -EINVAL; } roi = (struct drm_msm_ad4_roi_cfg *)hw_cfg->payload; if (roi->h_x >= hw_cfg->displayh || roi->v_x >= hw_cfg->displayv) { DRM_ERROR("invalid roi=[%u,%u,%u,%u], display=[%u,%u]\n", roi->h_x, roi->h_y, roi->v_x, roi->v_y, hw_cfg->displayh, hw_cfg->displayv); return -EINVAL; } if (roi->h_x >= roi->h_y || roi->v_x >= roi->v_y) { DRM_ERROR("invalid roi=[%u,%u,%u,%u], display=[%u,%u]\n", roi->h_x, roi->h_y, roi->v_x, roi->v_y, hw_cfg->displayh, hw_cfg->displayv); return -EINVAL; } if (roi->h_y > hw_cfg->displayh) roi->h_y = hw_cfg->displayh; if (roi->v_y > hw_cfg->displayv) roi->v_y = hw_cfg->displayv; /* single dspp cfg */ output->h_start = roi->h_x; output->h_end = roi->h_y; output->v_start = roi->v_x; output->v_end = roi->v_y; output->f_in = roi->factor_in; output->f_out = roi->factor_out; /* check whether dual dspp */ if (hw_cfg->num_of_mixers != 2) return 0; if (roi->h_y <= hw_lm->cfg.out_width) { if (hw_lm->cfg.right_mixer) { /* the region on the left of screen, clear right info */ output->h_start = 0; output->h_end = 0; output->v_start = 0; output->v_end = 0; } } else if (roi->h_x < hw_lm->cfg.out_width) { /* the region occupy both sides of screen: left and right */ if (hw_lm->cfg.right_mixer) { output->h_start = 0; output->h_end -= hw_lm->cfg.out_width; } else { output->h_end = hw_lm->cfg.out_width; } } else { /* the region on the right of the screen*/ if (hw_lm->cfg.right_mixer) { output->h_start -= hw_lm->cfg.out_width; output->h_end -= hw_lm->cfg.out_width; } else { output->h_start = 0; output->h_end = 0; output->v_start = 0; output->v_end = 0; } } return 0; } static int ad4_suspend_setup(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg) { Loading Loading @@ -1335,7 +1493,7 @@ void sde_read_intr_resp_ad4(struct sde_hw_dspp *dspp, u32 event, static int ad4_ipc_suspend_setup_run(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg) { u32 strength = 0, i = 0; u32 in_str = 0, out_str = 0, i = 0; struct sde_hw_mixer *hw_lm; hw_lm = cfg->hw_cfg->mixer_info; Loading @@ -1343,16 +1501,21 @@ static int ad4_ipc_suspend_setup_run(struct sde_hw_dspp *dspp, /* this AD core is the salve core */ for (i = DSPP_0; i < DSPP_MAX; i++) { if (info[i].is_master) { strength = info[i].last_str; in_str = info[i].last_str_inroi; out_str = info[i].last_str_outroi; break; } } } else { strength = SDE_REG_READ(&dspp->hw, in_str = SDE_REG_READ(&dspp->hw, dspp->cap->sblk->ad.base + 0x4c); pr_debug("%s(): AD strength = %d\n", __func__, strength); out_str = SDE_REG_READ(&dspp->hw, dspp->cap->sblk->ad.base + 0x50); pr_debug("%s(): AD in strength %d, out %d\n", __func__, in_str, out_str); } info[dspp->idx].last_str = strength; info[dspp->idx].last_str_inroi = in_str; info[dspp->idx].last_str_outroi = out_str; info[dspp->idx].state = ad4_state_ipcs; pr_debug("%s(): AD state move to ipcs\n", __func__); Loading @@ -1378,10 +1541,29 @@ static int ad4_ipc_resume_setup_ipcs(struct sde_hw_dspp *dspp, blk_offset = 0x34; val = (0x55 & (BIT(8) - 1)); SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val); /* set roi config */ blk_offset = 0x18; val = (info[dspp->idx].last_roi_cfg.h_end & (BIT(16) - 1)); val |= ((info[dspp->idx].last_roi_cfg.h_start & (BIT(16) - 1)) << 16); SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val); blk_offset += 4; val = (info[dspp->idx].last_roi_cfg.v_end & (BIT(16) - 1)); val |= ((info[dspp->idx].last_roi_cfg.v_start & (BIT(16) - 1)) << 16); SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val); blk_offset = 0x40; val = ((info[dspp->idx].last_roi_cfg.f_in & (BIT(16) - 1)) << 16); val |= (info[dspp->idx].last_roi_cfg.f_out & (BIT(16) - 1)); SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val); /* set manual strength */ blk_offset = 0x15c; val = (info[dspp->idx].last_str & (BIT(10) - 1)); val = (info[dspp->idx].last_str_inroi & (BIT(10) - 1)); SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val); blk_offset = 0x160; val = (info[dspp->idx].last_str_outroi & (BIT(10) - 1)); SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val); /* enable manual mode */ blk_offset = 0x138; SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, 0); Loading @@ -1401,7 +1583,7 @@ static int ad4_ipc_reset_setup_ipcr(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg) { int ret; u32 strength = 0, i = 0; u32 in_str = 0, out_str = 0, i = 0; struct sde_hw_mixer *hw_lm; /* Read AD calculator strength output during the 2 frames of manual Loading @@ -1414,20 +1596,25 @@ static int ad4_ipc_reset_setup_ipcr(struct sde_hw_dspp *dspp, /* this AD core is the salve core */ for (i = DSPP_0; i < DSPP_MAX; i++) { if (info[i].is_master) { strength = info[i].last_str; in_str = info[i].last_str_inroi; out_str = info[i].last_str_outroi; break; } } } else { strength = SDE_REG_READ(&dspp->hw, in_str = SDE_REG_READ(&dspp->hw, dspp->cap->sblk->ad.base + 0x4c); pr_debug("%s(): AD strength = %d\n", __func__, strength); out_str = SDE_REG_READ(&dspp->hw, dspp->cap->sblk->ad.base + 0x50); pr_debug("%s(): AD in strength %d, out %d\n", __func__, in_str, out_str); } if (info[dspp->idx].frame_count == AD_IPC_FRAME_COUNT) { info[dspp->idx].state = ad4_state_run; pr_debug("%s(): AD state move to run\n", __func__); info[dspp->idx].last_str = strength; info[dspp->idx].last_str_inroi = in_str; info[dspp->idx].last_str_outroi = out_str; ret = ad4_cfg_ipc_reset(dspp, cfg); if (ret) return ret; Loading @@ -1441,7 +1628,7 @@ static int ad4_ipc_reset_setup_ipcr(struct sde_hw_dspp *dspp, static int ad4_cfg_ipc_reset(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg) { u32 blk_offset; u32 blk_offset, val = 0; /* revert manual strength */ /* tf control */ Loading Loading @@ -1477,6 +1664,35 @@ static int ad4_cfg_ipc_reset(struct sde_hw_dspp *dspp, info[dspp->idx].cached_assertive = U8_MAX; } /*reset cached roi config*/ if (info[dspp->idx].cached_roi_cfg.h_start != U32_MAX) { blk_offset = 0x18; val = (info[dspp->idx].cached_roi_cfg.h_end & (BIT(16) - 1)); val |= ((info[dspp->idx].cached_roi_cfg.h_start & (BIT(16) - 1)) << 16); SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val); blk_offset += 4; val = (info[dspp->idx].cached_roi_cfg.v_end & (BIT(16) - 1)); val |= ((info[dspp->idx].cached_roi_cfg.v_start & (BIT(16) - 1)) << 16); SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val); blk_offset = 0x40; val = ((info[dspp->idx].cached_roi_cfg.f_in & (BIT(16) - 1)) << 16); val |= (info[dspp->idx].cached_roi_cfg.f_out & (BIT(16) - 1)); SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val); info[dspp->idx].last_roi_cfg = info[dspp->idx].cached_roi_cfg; info[dspp->idx].cached_roi_cfg.h_start = U32_MAX; info[dspp->idx].cached_roi_cfg.h_end = U32_MAX; info[dspp->idx].cached_roi_cfg.v_start = U32_MAX; info[dspp->idx].cached_roi_cfg.v_end = U32_MAX; info[dspp->idx].cached_roi_cfg.f_in = U32_MAX; info[dspp->idx].cached_roi_cfg.f_out = U32_MAX; } return 0; } Loading include/uapi/drm/msm_drm_pp.h +19 −0 Original line number Diff line number Diff line Loading @@ -436,4 +436,23 @@ struct drm_msm_pa_dither { __u32 matrix[DITHER_MATRIX_SZ]; }; /** * struct drm_msm_ad4_roi_cfg - ad4 roi params config set * by user-space client. * @h_x - hotizontal direction start * @h_y - hotizontal direction end * @v_x - vertical direction start * @v_y - vertical direction end * @factor_in - the alpha value for inside roi region * @factor_out - the alpha value for outside roi region */ #define DRM_MSM_AD4_ROI struct drm_msm_ad4_roi_cfg { __u32 h_x; __u32 h_y; __u32 v_x; __u32 v_y; __u32 factor_in; __u32 factor_out; }; #endif /* _MSM_DRM_PP_H_ */ Loading
drivers/gpu/drm/msm/sde/sde_ad4.h +1 −0 Original line number Diff line number Diff line Loading @@ -49,6 +49,7 @@ enum ad_property { AD_ASSERTIVE, AD_BACKLIGHT, AD_STRENGTH, AD_ROI, AD_IPC_SUSPEND, AD_IPC_RESUME, AD_IPC_RESET, Loading
drivers/gpu/drm/msm/sde/sde_color_processing.c +19 −0 Original line number Diff line number Diff line Loading @@ -137,6 +137,7 @@ enum { SDE_CP_CRTC_DSPP_AD_ASSERTIVENESS, SDE_CP_CRTC_DSPP_AD_BACKLIGHT, SDE_CP_CRTC_DSPP_AD_STRENGTH, SDE_CP_CRTC_DSPP_AD_ROI, SDE_CP_CRTC_DSPP_MAX, /* DSPP features end */ Loading Loading @@ -826,6 +827,15 @@ static void sde_cp_crtc_setfeature(struct sde_cp_node *prop_node, ad_cfg.hw_cfg = &hw_cfg; hw_dspp->ops.setup_ad(hw_dspp, &ad_cfg); break; case SDE_CP_CRTC_DSPP_AD_ROI: if (!hw_dspp || !hw_dspp->ops.setup_ad) { ret = -EINVAL; continue; } ad_cfg.prop = AD_ROI; ad_cfg.hw_cfg = &hw_cfg; hw_dspp->ops.setup_ad(hw_dspp, &ad_cfg); break; default: ret = -EINVAL; break; Loading Loading @@ -1427,6 +1437,11 @@ static void dspp_ad_install_property(struct drm_crtc *crtc) "SDE_DSPP_AD_V4_BACKLIGHT", SDE_CP_CRTC_DSPP_AD_BACKLIGHT, 0, (BIT(16) - 1), 0); sde_cp_crtc_install_range_property(crtc, "SDE_DSPP_AD_V4_ROI", SDE_CP_CRTC_DSPP_AD_ROI, 0, U64_MAX, 0); sde_cp_create_local_blob(crtc, SDE_CP_CRTC_DSPP_AD_ROI, sizeof(struct drm_msm_ad4_roi_cfg)); break; default: DRM_ERROR("version %d not supported\n", version); Loading Loading @@ -1590,6 +1605,7 @@ static void sde_cp_update_list(struct sde_cp_node *prop_node, case SDE_CP_CRTC_DSPP_AD_ASSERTIVENESS: case SDE_CP_CRTC_DSPP_AD_BACKLIGHT: case SDE_CP_CRTC_DSPP_AD_STRENGTH: case SDE_CP_CRTC_DSPP_AD_ROI: if (dirty_list) list_add_tail(&prop_node->dirty_list, &crtc->ad_dirty); else Loading Loading @@ -1641,6 +1657,9 @@ static int sde_cp_ad_validate_prop(struct sde_cp_node *prop_node, case SDE_CP_CRTC_DSPP_AD_STRENGTH: ad_prop = AD_STRENGTH; break; case SDE_CP_CRTC_DSPP_AD_ROI: ad_prop = AD_ROI; break; default: /* Not an AD property */ return 0; Loading
drivers/gpu/drm/msm/sde/sde_hw_ad4.c +250 −34 Original line number Diff line number Diff line Loading @@ -48,6 +48,15 @@ enum ad4_state { ad4_state_max, }; struct ad4_roi_info { u32 h_start; u32 h_end; u32 v_start; u32 v_end; u32 f_in; u32 f_out; }; typedef int (*ad4_prop_setup)(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *ad); Loading Loading @@ -77,6 +86,11 @@ static int ad4_cfg_setup_ipcr(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg); static int ad4_input_setup(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg); static int ad4_roi_setup(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg); static int ad4_roi_setup_ipcr(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg); static int ad4_roi_coordinate_offset(struct sde_hw_cp_cfg *hw_cfg, struct ad4_roi_info *output); static int ad4_input_setup_idle(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg); static int ad4_input_setup_ipcr(struct sde_hw_dspp *dspp, Loading Loading @@ -118,6 +132,7 @@ static ad4_prop_setup prop_set_func[ad4_state_max][AD_PROPMAX] = { [ad4_state_idle][AD_ASSERTIVE] = ad4_assertive_setup, [ad4_state_idle][AD_BACKLIGHT] = ad4_backlight_setup, [ad4_state_idle][AD_STRENGTH] = ad4_strength_setup_idle, [ad4_state_idle][AD_ROI] = ad4_no_op_setup, [ad4_state_idle][AD_IPC_SUSPEND] = ad4_no_op_setup, [ad4_state_idle][AD_IPC_RESUME] = ad4_no_op_setup, [ad4_state_idle][AD_IPC_RESET] = ad4_no_op_setup, Loading @@ -131,6 +146,7 @@ static ad4_prop_setup prop_set_func[ad4_state_max][AD_PROPMAX] = { [ad4_state_startup][AD_BACKLIGHT] = ad4_backlight_setup, [ad4_state_startup][AD_IPC_SUSPEND] = ad4_no_op_setup, [ad4_state_startup][AD_STRENGTH] = ad4_no_op_setup, [ad4_state_startup][AD_ROI] = ad4_roi_setup, [ad4_state_startup][AD_IPC_RESUME] = ad4_no_op_setup, [ad4_state_startup][AD_IPC_RESET] = ad4_ipc_reset_setup_startup, Loading @@ -142,6 +158,7 @@ static ad4_prop_setup prop_set_func[ad4_state_max][AD_PROPMAX] = { [ad4_state_run][AD_ASSERTIVE] = ad4_assertive_setup, [ad4_state_run][AD_BACKLIGHT] = ad4_backlight_setup, [ad4_state_run][AD_STRENGTH] = ad4_no_op_setup, [ad4_state_run][AD_ROI] = ad4_roi_setup, [ad4_state_run][AD_IPC_SUSPEND] = ad4_ipc_suspend_setup_run, [ad4_state_run][AD_IPC_RESUME] = ad4_no_op_setup, [ad4_state_run][AD_IPC_RESET] = ad4_setup_debug, Loading @@ -154,6 +171,7 @@ static ad4_prop_setup prop_set_func[ad4_state_max][AD_PROPMAX] = { [ad4_state_ipcs][AD_ASSERTIVE] = ad4_no_op_setup, [ad4_state_ipcs][AD_BACKLIGHT] = ad4_no_op_setup, [ad4_state_ipcs][AD_STRENGTH] = ad4_no_op_setup, [ad4_state_ipcs][AD_ROI] = ad4_no_op_setup, [ad4_state_ipcs][AD_IPC_SUSPEND] = ad4_no_op_setup, [ad4_state_ipcs][AD_IPC_RESUME] = ad4_ipc_resume_setup_ipcs, [ad4_state_ipcs][AD_IPC_RESET] = ad4_no_op_setup, Loading @@ -166,6 +184,7 @@ static ad4_prop_setup prop_set_func[ad4_state_max][AD_PROPMAX] = { [ad4_state_ipcr][AD_ASSERTIVE] = ad4_assertive_setup_ipcr, [ad4_state_ipcr][AD_BACKLIGHT] = ad4_backlight_setup_ipcr, [ad4_state_ipcr][AD_STRENGTH] = ad4_no_op_setup, [ad4_state_ipcr][AD_ROI] = ad4_roi_setup_ipcr, [ad4_state_ipcr][AD_IPC_SUSPEND] = ad4_ipc_suspend_setup_ipcr, [ad4_state_ipcr][AD_IPC_RESUME] = ad4_no_op_setup, [ad4_state_ipcr][AD_IPC_RESET] = ad4_ipc_reset_setup_ipcr, Loading @@ -178,6 +197,7 @@ static ad4_prop_setup prop_set_func[ad4_state_max][AD_PROPMAX] = { [ad4_state_manual][AD_ASSERTIVE] = ad4_no_op_setup, [ad4_state_manual][AD_BACKLIGHT] = ad4_no_op_setup, [ad4_state_manual][AD_STRENGTH] = ad4_strength_setup, [ad4_state_manual][AD_ROI] = ad4_no_op_setup, [ad4_state_manual][AD_IPC_SUSPEND] = ad4_no_op_setup, [ad4_state_manual][AD_IPC_RESUME] = ad4_no_op_setup, [ad4_state_manual][AD_IPC_RESET] = ad4_setup_debug_manual, Loading @@ -191,16 +211,19 @@ struct ad4_info { bool is_master; u32 last_assertive; u32 cached_assertive; u32 last_str_inroi; u32 last_str_outroi; u64 last_als; u64 cached_als; u64 last_bl; u64 cached_bl; u32 last_str; u32 frame_count; u32 frmt_mode; u32 irdx_control_0; u32 tf_ctrl; u32 vc_control_0; struct ad4_roi_info last_roi_cfg; struct ad4_roi_info cached_roi_cfg; }; static struct ad4_info info[DSPP_MAX] = { Loading Loading @@ -319,7 +342,7 @@ static int ad4_no_op_setup(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg) static int ad4_setup_debug(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg) { u32 strength = 0; u32 in_str = 0, out_str = 0; struct sde_hw_mixer *hw_lm; hw_lm = cfg->hw_cfg->mixer_info; Loading @@ -327,9 +350,10 @@ static int ad4_setup_debug(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg) /* this AD core is the salve core */ return 0; strength = SDE_REG_READ(&dspp->hw, dspp->cap->sblk->ad.base + 0x4c); pr_debug("%s(): AD strength = %d\n", __func__, strength); in_str = SDE_REG_READ(&dspp->hw, dspp->cap->sblk->ad.base + 0x4c); out_str = SDE_REG_READ(&dspp->hw, dspp->cap->sblk->ad.base + 0x50); pr_debug("%s(): AD in strength %d, out strength %d\n", __func__, in_str, out_str); return 0; } Loading Loading @@ -368,6 +392,18 @@ static int ad4_mode_setup(struct sde_hw_dspp *dspp, enum ad4_modes mode) info[dspp->idx].cached_bl = U64_MAX; info[dspp->idx].last_als = 0x0; info[dspp->idx].cached_als = U64_MAX; info[dspp->idx].last_roi_cfg.h_start = 0x0; info[dspp->idx].last_roi_cfg.h_end = 0xffff; info[dspp->idx].last_roi_cfg.v_start = 0x0; info[dspp->idx].last_roi_cfg.v_end = 0xffff; info[dspp->idx].last_roi_cfg.f_in = 0x400; info[dspp->idx].last_roi_cfg.f_out = 0x400; info[dspp->idx].cached_roi_cfg.h_start = U32_MAX; info[dspp->idx].cached_roi_cfg.h_end = U32_MAX; info[dspp->idx].cached_roi_cfg.v_start = U32_MAX; info[dspp->idx].cached_roi_cfg.v_end = U32_MAX; info[dspp->idx].cached_roi_cfg.f_in = U32_MAX; info[dspp->idx].cached_roi_cfg.f_out = U32_MAX; } else { if (mode == AD4_MANUAL) { /*vc_control_0 */ Loading Loading @@ -768,15 +804,6 @@ static int ad4_cfg_setup(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg) } ad_cfg = cfg->hw_cfg->payload; blk_offset = 0x18; val = (ad_cfg->cfg_param_002 & (BIT(16) - 1)); val |= ((ad_cfg->cfg_param_001 & (BIT(16) - 1)) << 16); SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val); blk_offset += 4; val = (ad_cfg->cfg_param_004 & (BIT(16) - 1)); val |= ((ad_cfg->cfg_param_003 & (BIT(16) - 1)) << 16); SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val); blk_offset = 0x20; val = (ad_cfg->cfg_param_005 & (BIT(8) - 1)); SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val); Loading @@ -793,10 +820,6 @@ static int ad4_cfg_setup(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg) blk_offset = 0x3c; val = (ad_cfg->cfg_param_010 & (BIT(12) - 1)); SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val); blk_offset += 4; val = ((ad_cfg->cfg_param_011 & (BIT(16) - 1)) << 16); val |= (ad_cfg->cfg_param_012 & (BIT(16) - 1)); SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val); blk_offset = 0x88; val = (ad_cfg->cfg_param_013 & (BIT(8) - 1)); Loading Loading @@ -891,10 +914,6 @@ static int ad4_cfg_setup(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg) info[dspp->idx].vc_control_0 = (ad_cfg->cfg_param_041 & (BIT(7) - 1)); blk_offset = 0x160; val = (ad_cfg->cfg_param_043 & (BIT(10) - 1)); SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val); blk_offset = 0x16c; val = (ad_cfg->cfg_param_044 & (BIT(8) - 1)); SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val); Loading Loading @@ -934,6 +953,145 @@ static int ad4_input_setup(struct sde_hw_dspp *dspp, return 0; } static int ad4_roi_setup(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg) { int ret = 0; u32 blk_offset = 0, val = 0; struct ad4_roi_info roi_cfg = {}; ret = ad4_roi_coordinate_offset(cfg->hw_cfg, &roi_cfg); if (ret) { DRM_ERROR("params invalid\n"); return -EINVAL; } info[dspp->idx].last_roi_cfg = roi_cfg; /*roi h start and end*/ blk_offset = 0x18; val = (info[dspp->idx].last_roi_cfg.h_end & (BIT(16) - 1)); val |= ((info[dspp->idx].last_roi_cfg.h_start & (BIT(16) - 1)) << 16); SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val); /*roi v start and end*/ blk_offset += 4; val = (info[dspp->idx].last_roi_cfg.v_end & (BIT(16) - 1)); val |= ((info[dspp->idx].last_roi_cfg.v_start & (BIT(16) - 1)) << 16); SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val); /*roi factor in and out*/ blk_offset = 0x40; val = ((info[dspp->idx].last_roi_cfg.f_in & (BIT(16) - 1)) << 16); val |= (info[dspp->idx].last_roi_cfg.f_out & (BIT(16) - 1)); SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val); return ret; } static int ad4_roi_setup_ipcr(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg) { int ret = 0; struct ad4_roi_info roi_cfg = {}; ret = ad4_roi_coordinate_offset(cfg->hw_cfg, &roi_cfg); if (ret) { DRM_ERROR("params invalid\n"); return -EINVAL; } info[dspp->idx].cached_roi_cfg = roi_cfg; return 0; } static int ad4_roi_coordinate_offset(struct sde_hw_cp_cfg *hw_cfg, struct ad4_roi_info *output) { struct sde_hw_mixer *hw_lm = hw_cfg->mixer_info; struct drm_msm_ad4_roi_cfg *roi = NULL; if (!hw_cfg->payload) { output->h_start = 0x0; output->h_end = hw_cfg->displayh; output->v_start = 0x0; output->v_end = hw_cfg->displayv; output->f_in = 0x400; output->f_out = 0x400; return 0; } if (hw_cfg->len != sizeof(struct drm_msm_ad4_roi_cfg)) { DRM_ERROR("invalid sz param exp %zd given %d cfg %pK\n", sizeof(struct drm_msm_ad4_roi_cfg), hw_cfg->len, hw_cfg->payload); return -EINVAL; } roi = (struct drm_msm_ad4_roi_cfg *)hw_cfg->payload; if (roi->h_x >= hw_cfg->displayh || roi->v_x >= hw_cfg->displayv) { DRM_ERROR("invalid roi=[%u,%u,%u,%u], display=[%u,%u]\n", roi->h_x, roi->h_y, roi->v_x, roi->v_y, hw_cfg->displayh, hw_cfg->displayv); return -EINVAL; } if (roi->h_x >= roi->h_y || roi->v_x >= roi->v_y) { DRM_ERROR("invalid roi=[%u,%u,%u,%u], display=[%u,%u]\n", roi->h_x, roi->h_y, roi->v_x, roi->v_y, hw_cfg->displayh, hw_cfg->displayv); return -EINVAL; } if (roi->h_y > hw_cfg->displayh) roi->h_y = hw_cfg->displayh; if (roi->v_y > hw_cfg->displayv) roi->v_y = hw_cfg->displayv; /* single dspp cfg */ output->h_start = roi->h_x; output->h_end = roi->h_y; output->v_start = roi->v_x; output->v_end = roi->v_y; output->f_in = roi->factor_in; output->f_out = roi->factor_out; /* check whether dual dspp */ if (hw_cfg->num_of_mixers != 2) return 0; if (roi->h_y <= hw_lm->cfg.out_width) { if (hw_lm->cfg.right_mixer) { /* the region on the left of screen, clear right info */ output->h_start = 0; output->h_end = 0; output->v_start = 0; output->v_end = 0; } } else if (roi->h_x < hw_lm->cfg.out_width) { /* the region occupy both sides of screen: left and right */ if (hw_lm->cfg.right_mixer) { output->h_start = 0; output->h_end -= hw_lm->cfg.out_width; } else { output->h_end = hw_lm->cfg.out_width; } } else { /* the region on the right of the screen*/ if (hw_lm->cfg.right_mixer) { output->h_start -= hw_lm->cfg.out_width; output->h_end -= hw_lm->cfg.out_width; } else { output->h_start = 0; output->h_end = 0; output->v_start = 0; output->v_end = 0; } } return 0; } static int ad4_suspend_setup(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg) { Loading Loading @@ -1335,7 +1493,7 @@ void sde_read_intr_resp_ad4(struct sde_hw_dspp *dspp, u32 event, static int ad4_ipc_suspend_setup_run(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg) { u32 strength = 0, i = 0; u32 in_str = 0, out_str = 0, i = 0; struct sde_hw_mixer *hw_lm; hw_lm = cfg->hw_cfg->mixer_info; Loading @@ -1343,16 +1501,21 @@ static int ad4_ipc_suspend_setup_run(struct sde_hw_dspp *dspp, /* this AD core is the salve core */ for (i = DSPP_0; i < DSPP_MAX; i++) { if (info[i].is_master) { strength = info[i].last_str; in_str = info[i].last_str_inroi; out_str = info[i].last_str_outroi; break; } } } else { strength = SDE_REG_READ(&dspp->hw, in_str = SDE_REG_READ(&dspp->hw, dspp->cap->sblk->ad.base + 0x4c); pr_debug("%s(): AD strength = %d\n", __func__, strength); out_str = SDE_REG_READ(&dspp->hw, dspp->cap->sblk->ad.base + 0x50); pr_debug("%s(): AD in strength %d, out %d\n", __func__, in_str, out_str); } info[dspp->idx].last_str = strength; info[dspp->idx].last_str_inroi = in_str; info[dspp->idx].last_str_outroi = out_str; info[dspp->idx].state = ad4_state_ipcs; pr_debug("%s(): AD state move to ipcs\n", __func__); Loading @@ -1378,10 +1541,29 @@ static int ad4_ipc_resume_setup_ipcs(struct sde_hw_dspp *dspp, blk_offset = 0x34; val = (0x55 & (BIT(8) - 1)); SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val); /* set roi config */ blk_offset = 0x18; val = (info[dspp->idx].last_roi_cfg.h_end & (BIT(16) - 1)); val |= ((info[dspp->idx].last_roi_cfg.h_start & (BIT(16) - 1)) << 16); SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val); blk_offset += 4; val = (info[dspp->idx].last_roi_cfg.v_end & (BIT(16) - 1)); val |= ((info[dspp->idx].last_roi_cfg.v_start & (BIT(16) - 1)) << 16); SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val); blk_offset = 0x40; val = ((info[dspp->idx].last_roi_cfg.f_in & (BIT(16) - 1)) << 16); val |= (info[dspp->idx].last_roi_cfg.f_out & (BIT(16) - 1)); SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val); /* set manual strength */ blk_offset = 0x15c; val = (info[dspp->idx].last_str & (BIT(10) - 1)); val = (info[dspp->idx].last_str_inroi & (BIT(10) - 1)); SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val); blk_offset = 0x160; val = (info[dspp->idx].last_str_outroi & (BIT(10) - 1)); SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val); /* enable manual mode */ blk_offset = 0x138; SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, 0); Loading @@ -1401,7 +1583,7 @@ static int ad4_ipc_reset_setup_ipcr(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg) { int ret; u32 strength = 0, i = 0; u32 in_str = 0, out_str = 0, i = 0; struct sde_hw_mixer *hw_lm; /* Read AD calculator strength output during the 2 frames of manual Loading @@ -1414,20 +1596,25 @@ static int ad4_ipc_reset_setup_ipcr(struct sde_hw_dspp *dspp, /* this AD core is the salve core */ for (i = DSPP_0; i < DSPP_MAX; i++) { if (info[i].is_master) { strength = info[i].last_str; in_str = info[i].last_str_inroi; out_str = info[i].last_str_outroi; break; } } } else { strength = SDE_REG_READ(&dspp->hw, in_str = SDE_REG_READ(&dspp->hw, dspp->cap->sblk->ad.base + 0x4c); pr_debug("%s(): AD strength = %d\n", __func__, strength); out_str = SDE_REG_READ(&dspp->hw, dspp->cap->sblk->ad.base + 0x50); pr_debug("%s(): AD in strength %d, out %d\n", __func__, in_str, out_str); } if (info[dspp->idx].frame_count == AD_IPC_FRAME_COUNT) { info[dspp->idx].state = ad4_state_run; pr_debug("%s(): AD state move to run\n", __func__); info[dspp->idx].last_str = strength; info[dspp->idx].last_str_inroi = in_str; info[dspp->idx].last_str_outroi = out_str; ret = ad4_cfg_ipc_reset(dspp, cfg); if (ret) return ret; Loading @@ -1441,7 +1628,7 @@ static int ad4_ipc_reset_setup_ipcr(struct sde_hw_dspp *dspp, static int ad4_cfg_ipc_reset(struct sde_hw_dspp *dspp, struct sde_ad_hw_cfg *cfg) { u32 blk_offset; u32 blk_offset, val = 0; /* revert manual strength */ /* tf control */ Loading Loading @@ -1477,6 +1664,35 @@ static int ad4_cfg_ipc_reset(struct sde_hw_dspp *dspp, info[dspp->idx].cached_assertive = U8_MAX; } /*reset cached roi config*/ if (info[dspp->idx].cached_roi_cfg.h_start != U32_MAX) { blk_offset = 0x18; val = (info[dspp->idx].cached_roi_cfg.h_end & (BIT(16) - 1)); val |= ((info[dspp->idx].cached_roi_cfg.h_start & (BIT(16) - 1)) << 16); SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val); blk_offset += 4; val = (info[dspp->idx].cached_roi_cfg.v_end & (BIT(16) - 1)); val |= ((info[dspp->idx].cached_roi_cfg.v_start & (BIT(16) - 1)) << 16); SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val); blk_offset = 0x40; val = ((info[dspp->idx].cached_roi_cfg.f_in & (BIT(16) - 1)) << 16); val |= (info[dspp->idx].cached_roi_cfg.f_out & (BIT(16) - 1)); SDE_REG_WRITE(&dspp->hw, dspp->cap->sblk->ad.base + blk_offset, val); info[dspp->idx].last_roi_cfg = info[dspp->idx].cached_roi_cfg; info[dspp->idx].cached_roi_cfg.h_start = U32_MAX; info[dspp->idx].cached_roi_cfg.h_end = U32_MAX; info[dspp->idx].cached_roi_cfg.v_start = U32_MAX; info[dspp->idx].cached_roi_cfg.v_end = U32_MAX; info[dspp->idx].cached_roi_cfg.f_in = U32_MAX; info[dspp->idx].cached_roi_cfg.f_out = U32_MAX; } return 0; } Loading
include/uapi/drm/msm_drm_pp.h +19 −0 Original line number Diff line number Diff line Loading @@ -436,4 +436,23 @@ struct drm_msm_pa_dither { __u32 matrix[DITHER_MATRIX_SZ]; }; /** * struct drm_msm_ad4_roi_cfg - ad4 roi params config set * by user-space client. * @h_x - hotizontal direction start * @h_y - hotizontal direction end * @v_x - vertical direction start * @v_y - vertical direction end * @factor_in - the alpha value for inside roi region * @factor_out - the alpha value for outside roi region */ #define DRM_MSM_AD4_ROI struct drm_msm_ad4_roi_cfg { __u32 h_x; __u32 h_y; __u32 v_x; __u32 v_y; __u32 factor_in; __u32 factor_out; }; #endif /* _MSM_DRM_PP_H_ */