diff --git a/msm/sde/sde_color_processing.c b/msm/sde/sde_color_processing.c index e38a520149..3ee567ca77 100644 --- a/msm/sde/sde_color_processing.c +++ b/msm/sde/sde_color_processing.c @@ -1632,6 +1632,11 @@ static void _sde_cp_crtc_commit_feature(struct sde_cp_node *prop_node, hw_cfg.last_feature = 0; hw_cfg.panel_width = sde_crtc->base.state->adjusted_mode.hdisplay; hw_cfg.panel_height = sde_crtc->base.state->adjusted_mode.vdisplay; + hw_cfg.valid_skip_blend_plane = sde_crtc->valid_skip_blend_plane; + hw_cfg.skip_blend_plane = sde_crtc->skip_blend_plane; + hw_cfg.skip_blend_plane_h = sde_crtc->skip_blend_plane_h; + hw_cfg.skip_blend_plane_w = sde_crtc->skip_blend_plane_w; + SDE_EVT32(hw_cfg.panel_width, hw_cfg.panel_height); for (i = 0; i < num_mixers; i++) { @@ -4709,6 +4714,10 @@ void sde_cp_crtc_disable(struct drm_crtc *drm_crtc) &crtc->dspp_blob_info, info->data, SDE_KMS_INFO_DATALEN(info), CRTC_PROP_DSPP_INFO); + crtc->valid_skip_blend_plane = false; + crtc->skip_blend_plane = SSPP_NONE; + crtc->skip_blend_plane_h = 0; + crtc->skip_blend_plane_w = 0; mutex_unlock(&crtc->crtc_cp_lock); kfree(info); } @@ -4770,3 +4779,31 @@ void sde_cp_duplicate_state_info(struct drm_crtc_state *drm_old_state, curr_state->cp_range_payload[i].len); } } + +void sde_cp_set_skip_blend_plane_info(struct drm_crtc *drm_crtc, + struct sde_cp_crtc_skip_blend_plane *skip_blend) +{ + struct sde_crtc *crtc; + + if (!drm_crtc || !skip_blend) { + DRM_ERROR("invalid crtc handle drm_crtc %pK skip_blend %pK\n", + drm_crtc, skip_blend); + return; + } + crtc = to_sde_crtc(drm_crtc); + mutex_lock(&crtc->crtc_cp_lock); + if (!skip_blend->valid_plane) { + crtc->valid_skip_blend_plane = false; + crtc->skip_blend_plane = SSPP_NONE; + crtc->skip_blend_plane_h = 0; + crtc->skip_blend_plane_w = 0; + mutex_unlock(&crtc->crtc_cp_lock); + return; + } + crtc->valid_skip_blend_plane = true; + crtc->skip_blend_plane = skip_blend->plane; + crtc->skip_blend_plane_h = skip_blend->height; + crtc->skip_blend_plane_w = skip_blend->width; + mutex_unlock(&crtc->crtc_cp_lock); +} + diff --git a/msm/sde/sde_color_processing.h b/msm/sde/sde_color_processing.h index b53086054b..a2fef78910 100644 --- a/msm/sde/sde_color_processing.h +++ b/msm/sde/sde_color_processing.h @@ -5,6 +5,7 @@ #ifndef _SDE_COLOR_PROCESSING_H #define _SDE_COLOR_PROCESSING_H +#include "sde_hw_mdss.h" #include struct sde_irq_callback; @@ -139,6 +140,21 @@ struct sde_cp_crtc_range_prop_payload { u32 len; }; +/** + * struct sde_cp_crtc_skip_blend_plane: struct to define skip blend plane configuration + * @valid_plane: flag to indicate plane is valid + * @plane: plane that has been enabled and skipped blending + * @width: plane width + * @height: plane height + */ + +struct sde_cp_crtc_skip_blend_plane { + bool valid_plane; + enum sde_sspp plane; + u32 width; + u32 height; +}; + /** * sde_cp_crtc_init(): Initialize color processing lists for a crtc. * Should be called during crtc initialization. @@ -330,7 +346,18 @@ void sde_cp_clear_state_info(struct drm_crtc_state *state); */ void sde_cp_duplicate_state_info(struct drm_crtc_state *old_state, struct drm_crtc_state *state); - +/** + * sde_cp_disable_features(): disable cp features + * @crtc: Pointer to drm_crtc. + */ void sde_cp_disable_features(struct drm_crtc *crtc); +/** + * sde_cp_set_skip_blend_plane_info(): set/clear the skip blend plane + * @crtc: Pointer to drm_crtc. + * @skip_blend: Pointer to sde_cp_crtc_skip_blend_plane + */ + +void sde_cp_set_skip_blend_plane_info(struct drm_crtc *crtc, + struct sde_cp_crtc_skip_blend_plane *skip_blend); #endif /*_SDE_COLOR_PROCESSING_H */ diff --git a/msm/sde/sde_crtc.c b/msm/sde/sde_crtc.c index baecaab90b..98178de5d6 100644 --- a/msm/sde/sde_crtc.c +++ b/msm/sde/sde_crtc.c @@ -1511,6 +1511,7 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc, int i, mode, cnt = 0; bool bg_alpha_enable = false; u32 blend_type; + struct sde_cp_crtc_skip_blend_plane skip_blend_plane; DECLARE_BITMAP(fetch_active, SSPP_MAX); if (!sde_crtc || !crtc->state || !mixer) { @@ -1564,6 +1565,14 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc, blend_type = sde_plane_get_property(pstate, PLANE_PROP_BLEND_OP); + if (blend_type == SDE_DRM_BLEND_OP_SKIP) { + skip_blend_plane.valid_plane = true; + skip_blend_plane.plane = sde_plane_pipe(plane); + skip_blend_plane.height = plane_crtc_roi.h; + skip_blend_plane.width = plane_crtc_roi.w; + sde_cp_set_skip_blend_plane_info(crtc, &skip_blend_plane); + } + if (blend_type != SDE_DRM_BLEND_OP_SKIP) { if (pstate->stage == SDE_STAGE_BASE && format->alpha_enable) @@ -4819,6 +4828,7 @@ static int _sde_crtc_check_get_pstates(struct drm_crtc *crtc, int rc = 0, multirect_count = 0, i, mixer_width, mixer_height; int inc_sde_stage = 0; struct sde_kms *kms; + u32 blend_type; sde_crtc = to_sde_crtc(crtc); cstate = to_sde_crtc_state(state); @@ -4853,6 +4863,8 @@ static int _sde_crtc_check_get_pstates(struct drm_crtc *crtc, pstates[*cnt].stage = sde_plane_get_property( pstates[*cnt].sde_pstate, PLANE_PROP_ZPOS); pstates[*cnt].pipe_id = sde_plane_pipe(plane); + blend_type = sde_plane_get_property(pstates[*cnt].sde_pstate, + PLANE_PROP_BLEND_OP); if (!kms->catalog->has_base_layer) inc_sde_stage = SDE_STAGE_0; @@ -4893,7 +4905,7 @@ static int _sde_crtc_check_get_pstates(struct drm_crtc *crtc, return -E2BIG; } - if (cstate->num_ds_enabled && + if (blend_type != SDE_DRM_BLEND_OP_SKIP && cstate->num_ds_enabled && ((pstate->crtc_h > mixer_height) || (pstate->crtc_w > mixer_width))) { SDE_ERROR("plane w/h:%x*%x > mixer w/h:%x*%x\n", diff --git a/msm/sde/sde_crtc.h b/msm/sde/sde_crtc.h index e46dfeec79..0e02b13dbe 100644 --- a/msm/sde/sde_crtc.h +++ b/msm/sde/sde_crtc.h @@ -296,6 +296,11 @@ struct sde_crtc_misr_info { * @cache_state : Current static image cache state * @dspp_blob_info : blob containing dspp hw capability information * @cached_encoder_mask : cached encoder_mask for vblank work + * @valid_skip_blend_plane: flag to indicate if skip blend plane is valid + * @skip_blend_plane: enabled plane that has skip blending + * @skip_blend_plane_w: skip blend plane width + * @skip_blend_plane_h: skip blend plane height + * */ struct sde_crtc { struct drm_crtc base; @@ -387,6 +392,11 @@ struct sde_crtc { struct drm_property_blob *dspp_blob_info; u32 cached_encoder_mask; + + bool valid_skip_blend_plane; + enum sde_sspp skip_blend_plane; + u32 skip_blend_plane_w; + u32 skip_blend_plane_h; }; enum sde_crtc_dirty_flags { diff --git a/msm/sde/sde_hw_mdss.h b/msm/sde/sde_hw_mdss.h index b6406f5cd8..1b041c79ce 100644 --- a/msm/sde/sde_hw_mdss.h +++ b/msm/sde/sde_hw_mdss.h @@ -584,6 +584,10 @@ struct sde_mdss_color { * using LUTDMA * @panel_height: height of display panel in pixels. * @panel_width: width of display panel in pixels. + * @valid_skip_blend_plane: true if skip plane params are valid + * @skip_blend_plane: plane which has been skipped staging into layer mixer + * @skip_blend_plane_w: skip plane width + * @skip_blend_plane_h: skip plane height */ struct sde_hw_cp_cfg { void *payload; @@ -598,6 +602,10 @@ struct sde_hw_cp_cfg { bool broadcast_disabled; u32 panel_height; u32 panel_width; + bool valid_skip_blend_plane; + enum sde_sspp skip_blend_plane; + u32 skip_blend_plane_w; + u32 skip_blend_plane_h; }; /** diff --git a/msm/sde/sde_hw_reg_dma_v1_color_proc.c b/msm/sde/sde_hw_reg_dma_v1_color_proc.c index b5db78f35c..4aed5cedc8 100644 --- a/msm/sde/sde_hw_reg_dma_v1_color_proc.c +++ b/msm/sde/sde_hw_reg_dma_v1_color_proc.c @@ -5260,14 +5260,54 @@ static int __reg_dmav1_setup_demurav1_cfg5(struct sde_hw_dspp *ctx, return rc; } +static bool __reg_dmav1_valid_hfc_en_cfg(struct drm_msm_dem_cfg *dcfg, + struct sde_hw_cp_cfg *hw_cfg) +{ + u32 h, w, temp; + if (!hw_cfg->valid_skip_blend_plane) { + DRM_ERROR("HFC plane not set\n"); + return false; + } + + h = hw_cfg->panel_height; + w = hw_cfg->panel_width; + temp = hw_cfg->panel_width / 2; + if (dcfg->pentile) { + w = dcfg->c0_depth * (temp / 2) + dcfg->c1_depth * temp + + dcfg->c2_depth * (temp / 2); + if (w % 32) + w = 32 - (w % 32) + w; + w = 2 * (w / 32); + w = w / (hw_cfg->num_of_mixers ? hw_cfg->num_of_mixers : 1); + } + if (h != hw_cfg->skip_blend_plane_h || w != hw_cfg->skip_blend_plane_w) { + DRM_ERROR("invalid hfc cfg exp h %d exp w %d act h %d act w %d\n", + h, w, hw_cfg->skip_blend_plane_h, hw_cfg->skip_blend_plane_w); + DRM_ERROR("c0_depth %d c1_depth %d c2 depth %d hw_cfg->panel_width %d\n", + dcfg->c0_depth, dcfg->c1_depth, dcfg->c2_depth, hw_cfg->panel_width); + return false; + } + + if (dcfg->src_id == BIT(3) && hw_cfg->skip_blend_plane == SSPP_DMA3) + return true; + + if (dcfg->src_id == BIT(1) && hw_cfg->skip_blend_plane == SSPP_DMA1) + return true; + + DRM_ERROR("invalid HFC plane dcfg->src_id %d hw_cfg->skip_blend_plane %d\n", + dcfg->src_id, hw_cfg->skip_blend_plane); + return false; +} static int __reg_dmav1_setup_demurav1_en(struct sde_hw_dspp *ctx, struct drm_msm_dem_cfg *dcfg, struct sde_reg_dma_setup_ops_cfg *dma_write_cfg, - struct sde_hw_reg_dma_ops *dma_ops) + struct sde_hw_reg_dma_ops *dma_ops, + struct sde_hw_cp_cfg *hw_cfg) { u32 en = 0, backl; int rc; + bool valid_hfc_cfg = false; u32 demura_base = ctx->cap->sblk->demura.base + ctx->hw.blk_off; backl = (1024 << 16) | 1024; @@ -5288,7 +5328,10 @@ static int __reg_dmav1_setup_demurav1_en(struct sde_hw_dspp *ctx, en |= (dcfg->cfg3_en) ? BIT(5) : 0; en |= (dcfg->cfg4_en) ? BIT(4) : 0; en |= (dcfg->cfg2_en) ? BIT(3) : 0; - en |= (dcfg->cfg0_en) ? BIT(2) : 0; + if (dcfg->cfg0_en) + valid_hfc_cfg = __reg_dmav1_valid_hfc_en_cfg(dcfg, hw_cfg); + if (valid_hfc_cfg) + en |= (dcfg->cfg0_en) ? BIT(2) : 0; en |= (dcfg->cfg1_en) ? BIT(1) : 0; DRM_DEBUG_DRIVER("demura en %x\n", en); SDE_EVT32(en); @@ -5404,7 +5447,7 @@ void reg_dmav1_setup_demurav1(struct sde_hw_dspp *ctx, void *cfx) } rc = __reg_dmav1_setup_demurav1_en(ctx, dcfg, &dma_write_cfg, - dma_ops); + dma_ops, hw_cfg); if (rc) { DRM_ERROR("failed setup_demurav1_en rc %d", rc); return; diff --git a/msm/sde/sde_plane.c b/msm/sde/sde_plane.c index 85604ddcf3..ffe56cf9bf 100644 --- a/msm/sde/sde_plane.c +++ b/msm/sde/sde_plane.c @@ -3336,6 +3336,7 @@ static void _sde_plane_atomic_disable(struct drm_plane *plane, struct drm_plane_state *state; struct sde_plane_state *pstate; u32 multirect_index = SDE_SSPP_RECT_0; + struct sde_cp_crtc_skip_blend_plane skip_blend_plane; u32 blend_type; if (!plane) { @@ -3358,8 +3359,12 @@ static void _sde_plane_atomic_disable(struct drm_plane *plane, /* some of the color features are dependent on plane with skip blend. * if skip blend plane is being disabled, we need to disable color properties. */ - if (blend_type == SDE_DRM_BLEND_OP_SKIP && old_state->crtc) + if (blend_type == SDE_DRM_BLEND_OP_SKIP && old_state->crtc) { + skip_blend_plane.valid_plane = false; + skip_blend_plane.plane = SSPP_NONE; + sde_cp_set_skip_blend_plane_info(old_state->crtc, &skip_blend_plane); sde_crtc_disable_cp_features(old_state->crtc); + } SDE_EVT32(DRMID(plane), is_sde_plane_virtual(plane), pstate->multirect_mode);