diff --git a/msm/sde/sde_hw_ctl.c b/msm/sde/sde_hw_ctl.c index 25b541eb..5cead153 100644 --- a/msm/sde/sde_hw_ctl.c +++ b/msm/sde/sde_hw_ctl.c @@ -638,6 +638,28 @@ static void sde_hw_ctl_set_fetch_pipe_active(struct sde_hw_ctl *ctx, SDE_REG_WRITE(&ctx->hw, CTL_FETCH_PIPE_ACTIVE, val); } +static u32 sde_hw_ctl_get_active_fetch_pipes(struct sde_hw_ctl *ctx) +{ + int i; + u32 fetch_info, fetch_active = 0; + + if (!ctx) { + DRM_ERROR("invalid args - ctx invalid\n"); + return 0; + } + + fetch_info = SDE_REG_READ(&ctx->hw, CTL_FETCH_PIPE_ACTIVE); + + for (i = SSPP_VIG0; i < SSPP_MAX; i++) { + if (fetch_tbl[i] != CTL_INVALID_BIT && + fetch_info & BIT(fetch_tbl[i])) { + fetch_active |= BIT(i); + } + } + + return fetch_active; +} + static inline void _sde_hw_ctl_write_dspp_flushes(struct sde_hw_ctl *ctx) { int i; bool has_dspp_flushes = ctx->caps->features & @@ -1275,6 +1297,7 @@ static void _setup_ctl_ops(struct sde_hw_ctl_ops *ops, ops->get_scheduler_status = sde_hw_ctl_get_scheduler_status; ops->read_active_status = sde_hw_ctl_read_active_status; ops->set_active_pipes = sde_hw_ctl_set_fetch_pipe_active; + ops->get_active_pipes = sde_hw_ctl_get_active_fetch_pipes; } else { ops->update_pending_flush = sde_hw_ctl_update_pending_flush; ops->trigger_flush = sde_hw_ctl_trigger_flush; diff --git a/msm/sde/sde_hw_ctl.h b/msm/sde/sde_hw_ctl.h index 1ea29dad..7d1a91c3 100644 --- a/msm/sde/sde_hw_ctl.h +++ b/msm/sde/sde_hw_ctl.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2015-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. */ #ifndef _SDE_HW_CTL_H @@ -466,6 +466,13 @@ struct sde_hw_ctl_ops { */ void (*set_active_pipes)(struct sde_hw_ctl *ctx, unsigned long *fetch_active); + + /** + * Get all the sspp marked for fetching on the control path. + * @ctx : ctl path ctx pointer + * @Return: bitmap of enum sde_sspp pipes found + */ + u32 (*get_active_pipes)(struct sde_hw_ctl *ctx); }; /** diff --git a/msm/sde/sde_hw_mdss.h b/msm/sde/sde_hw_mdss.h index ceedfeb2..3d6b3f47 100644 --- a/msm/sde/sde_hw_mdss.h +++ b/msm/sde/sde_hw_mdss.h @@ -161,6 +161,12 @@ enum sde_sspp_type { SSPP_TYPE_MAX }; +enum sde_sspp_rect { + R0, + R1, + R_MAX +}; + enum sde_lm { LM_0 = 1, LM_1, @@ -655,7 +661,7 @@ struct sde_splash_display { u8 lm_ids[MAX_DATA_PATH_PER_DSIPLAY]; u8 dsc_ids[MAX_DATA_PATH_PER_DSIPLAY]; u8 vdc_ids[MAX_DATA_PATH_PER_DSIPLAY]; - struct sde_sspp_index_info pipes[MAX_DATA_PATH_PER_DSIPLAY]; + struct sde_sspp_index_info pipes[SSPP_MAX]; u8 ctl_cnt; u8 lm_cnt; u8 dsc_cnt; diff --git a/msm/sde/sde_plane.c b/msm/sde/sde_plane.c index 5b28672f..f385dc33 100644 --- a/msm/sde/sde_plane.c +++ b/msm/sde/sde_plane.c @@ -60,13 +60,6 @@ #define TIME_MULTIPLEX_RECT(r0, r1, buffer_lines) \ ((r0).y >= ((r1).y + (r1).h + buffer_lines)) -/* multirect rect index */ -enum { - R0, - R1, - R_MAX -}; - #define SDE_QSEED_DEFAULT_DYN_EXP 0x0 /** diff --git a/msm/sde/sde_rm.c b/msm/sde/sde_rm.c index 0ddd1540..bebc7b94 100644 --- a/msm/sde/sde_rm.c +++ b/msm/sde/sde_rm.c @@ -1857,6 +1857,60 @@ static int _sde_rm_make_next_rsvp(struct sde_rm *rm, struct drm_encoder *enc, return ret; } +static int _sde_rm_update_pipe_cnt_from_active( + struct sde_splash_display *splash_display, + u32 active_pipes_mask) +{ + int i; + u32 sspp_present = 0, space_remain = 0; + + if (!active_pipes_mask) { + return 0; + } else if (!splash_display) { + SDE_ERROR("invalid splash display provided\n"); + return -EINVAL; + } else if (splash_display->pipe_cnt >= + ARRAY_SIZE(splash_display->pipes)) { + SDE_ERROR("no room to add active pipes to pipe array\n"); + return -EINVAL; + } + + for (i = 0; i < splash_display->pipe_cnt; i++) + sspp_present |= BIT(splash_display->pipes[i].sspp); + + space_remain = ARRAY_SIZE(splash_display->pipes) + - splash_display->pipe_cnt; + + for (i = SSPP_VIG0; i < SSPP_MAX; i++) { + /* Skip planes already present in the array */ + if (!(active_pipes_mask & BIT(i)) || + (sspp_present & BIT(i))) + continue; + + if (space_remain < R_MAX) { + SDE_ERROR("not enough room to add active pipe %d", i); + return -EINVAL; + } + + /* + * A plane in active but not sspp_present indicates a non-pixel + * plane. Register both rectangles as we can't differentiate + */ + splash_display->pipes[splash_display->pipe_cnt].sspp = i; + splash_display->pipes[splash_display->pipe_cnt].is_virtual = + false; + splash_display->pipe_cnt++; + space_remain--; + splash_display->pipes[splash_display->pipe_cnt].sspp = i; + splash_display->pipes[splash_display->pipe_cnt].is_virtual = + true; + splash_display->pipe_cnt++; + space_remain--; + } + + return 0; +} + /** * _sde_rm_get_hw_blk_for_cont_splash - retrieve the LM blocks on given CTL * and populate the connected HW blk ids in sde_splash_display @@ -1869,9 +1923,10 @@ static int _sde_rm_get_hw_blk_for_cont_splash(struct sde_rm *rm, struct sde_hw_ctl *ctl, struct sde_splash_display *splash_display) { - u32 lm_reg; + u32 lm_reg, max_cnt, active_pipes_mask = 0; struct sde_rm_hw_iter iter_lm, iter_dsc; struct sde_kms *sde_kms; + size_t start_count; if (!rm || !ctl || !splash_display) { SDE_ERROR("invalid input parameters\n"); @@ -1879,6 +1934,7 @@ static int _sde_rm_get_hw_blk_for_cont_splash(struct sde_rm *rm, } sde_kms = container_of(rm, struct sde_kms, rm); + max_cnt = ARRAY_SIZE(splash_display->pipes); sde_rm_init_hw_iter(&iter_lm, 0, SDE_HW_BLK_LM); sde_rm_init_hw_iter(&iter_dsc, 0, SDE_HW_BLK_DSC); @@ -1895,24 +1951,41 @@ static int _sde_rm_get_hw_blk_for_cont_splash(struct sde_rm *rm, SDE_DEBUG("lm_cnt=%d lm_reg[%d]=0x%x\n", splash_display->lm_cnt, iter_lm.blk->id - LM_0, lm_reg); - if (ctl->ops.get_staged_sspp && - ctl->ops.get_staged_sspp(ctl, iter_lm.blk->id, - &splash_display->pipes[ - splash_display->pipe_cnt], 1)) { - splash_display->pipe_cnt++; - } else if (sde_kms->splash_data.type == SDE_VM_HANDOFF) { + start_count = splash_display->pipe_cnt; + if (ctl->ops.get_staged_sspp) { + struct sde_sspp_index_info *start = + &splash_display->pipes[ + splash_display->pipe_cnt]; + + splash_display->pipe_cnt += ctl->ops.get_staged_sspp( + ctl, iter_lm.blk->id, start, + max_cnt - splash_display->pipe_cnt); + } + + if (sde_kms->splash_data.type == SDE_VM_HANDOFF) { /* Allow VM handoff without any pipes, as it is a * valid case to have NULL commit before the * transition. */ SDE_DEBUG("VM handoff with no pipes staged\n"); - } else { - SDE_ERROR("no pipe detected on LM-%d\n", + } else if (start_count == splash_display->pipe_cnt) { + SDE_ERROR("no pipes detected on LM-%d\n", iter_lm.blk->id - LM_0); return 0; + } else if (splash_display->pipe_cnt > max_cnt) { + SDE_ERROR("found %d pipes exceed max of %d\n", + splash_display->pipe_cnt, max_cnt); + return 0; } } + if (ctl->ops.get_active_pipes) + active_pipes_mask = ctl->ops.get_active_pipes(ctl); + + if (_sde_rm_update_pipe_cnt_from_active(splash_display, + active_pipes_mask)) + return 0; + while (_sde_rm_get_hw_locked(rm, &iter_dsc)) { if (ctl->ops.read_active_status && !(ctl->ops.read_active_status(ctl,