From 078d42797bd004d5bade47784f9530a2a01ea657 Mon Sep 17 00:00:00 2001 From: Gopikrishnaiah Anandan Date: Thu, 30 Jan 2020 15:44:10 -0800 Subject: [PATCH] disp: msm: add support for no blend planes Some of the features in the DPU hardware needs planes to be staged but it should not be blended in the layer mixer. Change adds support for drm driver client to set the blend type on the plane and updates driver code to skip staging the plane. Change-Id: I1e8c7f6ce5617820ea8b24419e0d4d27b481819b Signed-off-by: Gopikrishnaiah Anandan --- msm/sde/sde_crtc.c | 101 ++++++++++++++++++++++++++++++------------ msm/sde/sde_crtc.h | 2 + msm/sde/sde_encoder.c | 2 +- msm/sde/sde_hw_ctl.c | 15 ++++++- msm/sde/sde_hw_ctl.h | 4 +- msm/sde/sde_plane.c | 3 +- 6 files changed, 94 insertions(+), 33 deletions(-) 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"}