diff --git a/msm/sde/sde_crtc.c b/msm/sde/sde_crtc.c index 7ed658d358..3d2e9a5db1 100644 --- a/msm/sde/sde_crtc.c +++ b/msm/sde/sde_crtc.c @@ -93,6 +93,8 @@ static struct sde_crtc_custom_events custom_events[] = { #define MAX_FRAME_COUNT 1000 #define MILI_TO_MICRO 1000 +#define SKIP_STAGING_PIPE_ZPOS 255 + static inline struct sde_kms *_sde_crtc_get_kms(struct drm_crtc *crtc) { struct msm_drm_private *priv; @@ -491,6 +493,11 @@ static void _sde_crtc_setup_blend_cfg(struct sde_crtc_mixer *mixer, } } break; + + case SDE_DRM_BLEND_OP_SKIP: + SDE_ERROR("skip the blending for plane\n"); + return; + default: /* do nothing */ break; @@ -1326,6 +1333,24 @@ static void _sde_crtc_set_src_split_order(struct drm_crtc *crtc, cur_pstate->sde_pstate->pipe_order_flags); } } + +static void __sde_crtc_assign_active_cfg(struct sde_crtc *sdecrtc, + struct drm_plane *plane) +{ + u8 found = 0; + int i; + + for (i = 0; i < SDE_STAGE_MAX && !found; i++) { + if (sdecrtc->active_cfg.stage[i][0] == SSPP_NONE) + found = 1; + } + if (!found) { + SDE_ERROR("All active configs are allocated\n"); + return; + } + sdecrtc->active_cfg.stage[i][0] = sde_plane_pipe(plane); +} + static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc, struct drm_crtc_state *old_state, struct sde_crtc *sde_crtc, struct sde_crtc_mixer *mixer) @@ -1345,6 +1370,7 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc, int zpos_cnt[SDE_STAGE_MAX + 1] = { 0 }; int i, cnt = 0; bool bg_alpha_enable = false; + u32 blend_type; if (!sde_crtc || !crtc->state || !mixer) { SDE_ERROR("invalid sde_crtc or mixer\n"); @@ -1388,38 +1414,50 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc, goto end; } - if (pstate->stage == SDE_STAGE_BASE && format->alpha_enable) - bg_alpha_enable = true; + blend_type = sde_plane_get_property(pstate, + PLANE_PROP_BLEND_OP); - SDE_EVT32(DRMID(crtc), DRMID(plane), - state->fb ? state->fb->base.id : -1, - state->src_x >> 16, state->src_y >> 16, - state->src_w >> 16, state->src_h >> 16, - state->crtc_x, state->crtc_y, - state->crtc_w, state->crtc_h, - pstate->rotation); + if (blend_type == SDE_DRM_BLEND_OP_SKIP) { + __sde_crtc_assign_active_cfg(sde_crtc, plane); + } else { + if (pstate->stage == SDE_STAGE_BASE && + format->alpha_enable) + bg_alpha_enable = true; - stage_idx = zpos_cnt[pstate->stage]++; - stage_cfg->stage[pstate->stage][stage_idx] = - sde_plane_pipe(plane); - stage_cfg->multirect_index[pstate->stage][stage_idx] = - pstate->multirect_index; + SDE_EVT32(DRMID(crtc), DRMID(plane), + state->fb ? state->fb->base.id : -1, + state->src_x >> 16, state->src_y >> 16, + state->src_w >> 16, state->src_h >> 16, + state->crtc_x, state->crtc_y, + state->crtc_w, state->crtc_h, + pstate->rotation); - SDE_EVT32(DRMID(crtc), DRMID(plane), stage_idx, - sde_plane_pipe(plane) - SSPP_VIG0, pstate->stage, - pstate->multirect_index, pstate->multirect_mode, - format->base.pixel_format, fb ? fb->modifier : 0); + stage_idx = zpos_cnt[pstate->stage]++; + stage_cfg->stage[pstate->stage][stage_idx] = + sde_plane_pipe(plane); + stage_cfg->multirect_index[pstate->stage][stage_idx] = + pstate->multirect_index; - /* blend config update */ - for (lm_idx = 0; lm_idx < sde_crtc->num_mixers; lm_idx++) { - _sde_crtc_setup_blend_cfg(mixer + lm_idx, pstate, - format); + SDE_EVT32(DRMID(crtc), DRMID(plane), stage_idx, + sde_plane_pipe(plane) - SSPP_VIG0, + pstate->stage, + pstate->multirect_index, + pstate->multirect_mode, + format->base.pixel_format, + fb ? fb->modifier : 0); - if (bg_alpha_enable && !format->alpha_enable) - mixer[lm_idx].mixer_op_mode = 0; - else - mixer[lm_idx].mixer_op_mode |= - 1 << pstate->stage; + /* blend config update */ + for (lm_idx = 0; lm_idx < sde_crtc->num_mixers; + lm_idx++) { + _sde_crtc_setup_blend_cfg(mixer + lm_idx, + pstate, format); + + if (bg_alpha_enable && !format->alpha_enable) + mixer[lm_idx].mixer_op_mode = 0; + else + mixer[lm_idx].mixer_op_mode |= + 1 << pstate->stage; + } } if (cnt >= SDE_PSTATES_MAX) @@ -1427,7 +1465,11 @@ static void _sde_crtc_blend_setup_mixer(struct drm_crtc *crtc, pstates[cnt].sde_pstate = pstate; pstates[cnt].drm_pstate = state; - pstates[cnt].stage = sde_plane_get_property( + + if (blend_type == SDE_DRM_BLEND_OP_SKIP) + pstates[cnt].stage = SKIP_STAGING_PIPE_ZPOS; + else + pstates[cnt].stage = sde_plane_get_property( pstates[cnt].sde_pstate, PLANE_PROP_ZPOS); pstates[cnt].pipe_id = sde_plane_pipe(plane); @@ -1562,6 +1604,7 @@ static void _sde_crtc_blend_setup(struct drm_crtc *crtc, /* initialize stage cfg */ memset(&sde_crtc->stage_cfg, 0, sizeof(struct sde_hw_stage_cfg)); + memset(&sde_crtc->active_cfg, 0, sizeof(sde_crtc->active_cfg)); if (add_planes) _sde_crtc_blend_setup_mixer(crtc, old_state, sde_crtc, mixer); @@ -1593,7 +1636,7 @@ static void _sde_crtc_blend_setup(struct drm_crtc *crtc, cfg.pending_flush_mask); ctl->ops.setup_blendstage(ctl, mixer[i].hw_lm->idx, - &sde_crtc->stage_cfg); + &sde_crtc->stage_cfg, &sde_crtc->active_cfg); } _sde_crtc_program_lm_output_roi(crtc); diff --git a/msm/sde/sde_crtc.h b/msm/sde/sde_crtc.h index c5bbf06d68..b027f15c6c 100644 --- a/msm/sde/sde_crtc.h +++ b/msm/sde/sde_crtc.h @@ -207,6 +207,7 @@ struct sde_crtc_misr_info { * @property_defaults : Array of default values for generic property support * @output_fence : output release fence context * @stage_cfg : H/w mixer stage configuration + * @active_cfg : H/w pipes active that shouldn't be staged * @debugfs_root : Parent of debugfs node * @priv_handle : Pointer to external private handle, if present * @vblank_cb_count : count of vblank callback since last reset @@ -275,6 +276,7 @@ struct sde_crtc { struct sde_fence_context *output_fence; struct sde_hw_stage_cfg stage_cfg; + struct sde_hw_stage_cfg active_cfg; struct dentry *debugfs_root; void *priv_handle; diff --git a/msm/sde/sde_encoder.c b/msm/sde/sde_encoder.c index d6bc4cf32e..a5c7b51eb9 100644 --- a/msm/sde/sde_encoder.c +++ b/msm/sde/sde_encoder.c @@ -4178,7 +4178,7 @@ int sde_encoder_helper_reset_mixers(struct sde_encoder_phys *phys_enc, /* only enable border color on LM */ if (phys_enc->hw_ctl->ops.setup_blendstage) phys_enc->hw_ctl->ops.setup_blendstage( - phys_enc->hw_ctl, hw_lm->idx, NULL); + phys_enc->hw_ctl, hw_lm->idx, NULL, NULL); } if (!lm_valid) { diff --git a/msm/sde/sde_hw_ctl.c b/msm/sde/sde_hw_ctl.c index 27b43a1a91..e198595457 100644 --- a/msm/sde/sde_hw_ctl.c +++ b/msm/sde/sde_hw_ctl.c @@ -806,7 +806,8 @@ static void sde_hw_ctl_clear_all_blendstages(struct sde_hw_ctl *ctx) } static void sde_hw_ctl_setup_blendstage(struct sde_hw_ctl *ctx, - enum sde_lm lm, struct sde_hw_stage_cfg *stage_cfg) + enum sde_lm lm, struct sde_hw_stage_cfg *stage_cfg, + struct sde_hw_stage_cfg *active_cfg) { struct sde_hw_blk_reg_map *c; u32 mixercfg = 0, mixercfg_ext = 0, mix, ext; @@ -939,6 +940,18 @@ static void sde_hw_ctl_setup_blendstage(struct sde_hw_ctl *ctx, } } + for (i = 0; i <= stages && active_cfg; i++) { + enum sde_sspp pipe = active_cfg->stage[i][0]; + + if (pipe == SSPP_NONE) + break; + if (fetch_tbl[pipe] != CTL_INVALID_BIT) { + active_fetch_pipes |= BIT(fetch_tbl[pipe]); + SDE_DEBUG("fetch pipe %d active pipes %x\n", + pipe, active_fetch_pipes); + } + } + exit: if ((!mixercfg && !mixercfg_ext && !mixercfg_ext2 && !mixercfg_ext3) || (stage_cfg && !stage_cfg->stage[0][0])) diff --git a/msm/sde/sde_hw_ctl.h b/msm/sde/sde_hw_ctl.h index 9f1e6e90e7..0514692f8e 100644 --- a/msm/sde/sde_hw_ctl.h +++ b/msm/sde/sde_hw_ctl.h @@ -426,9 +426,11 @@ struct sde_hw_ctl_ops { * @ctx : ctl path ctx pointer * @lm : layer mixer enumeration * @cfg : blend stage configuration + * @active_cfg: active no blend stage configuration */ void (*setup_blendstage)(struct sde_hw_ctl *ctx, - enum sde_lm lm, struct sde_hw_stage_cfg *cfg); + enum sde_lm lm, struct sde_hw_stage_cfg *cfg, + struct sde_hw_stage_cfg *active_cfg); /** * Get all the sspp staged on a layer mixer diff --git a/msm/sde/sde_plane.c b/msm/sde/sde_plane.c index d8c68db59c..0fea6745f3 100644 --- a/msm/sde/sde_plane.c +++ b/msm/sde/sde_plane.c @@ -3421,7 +3421,8 @@ static void _sde_plane_install_properties(struct drm_plane *plane, {SDE_DRM_BLEND_OP_NOT_DEFINED, "not_defined"}, {SDE_DRM_BLEND_OP_OPAQUE, "opaque"}, {SDE_DRM_BLEND_OP_PREMULTIPLIED, "premultiplied"}, - {SDE_DRM_BLEND_OP_COVERAGE, "coverage"} + {SDE_DRM_BLEND_OP_COVERAGE, "coverage"}, + {SDE_DRM_BLEND_OP_SKIP, "skip_blending"}, }; static const struct drm_prop_enum_list e_src_config[] = { {SDE_DRM_DEINTERLACE, "deinterlace"}