From 070934308cd58693ee33f782facf69e5be0e0f02 Mon Sep 17 00:00:00 2001 From: Krishna Manikandan Date: Fri, 8 Oct 2021 10:25:24 +0530 Subject: [PATCH 1/8] disp: msm: sde: protect file private structure with mutex lock Access file private data structures inside the mutex lock only to avoid use-after-free issues. Change-Id: If70731f517bcb47d4515f131fecafe702064cb45 Signed-off-by: Krishna Manikandan --- msm/msm_drv.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/msm/msm_drv.c b/msm/msm_drv.c index 5597b8d72da1..5eb8363e2198 100644 --- a/msm/msm_drv.c +++ b/msm/msm_drv.c @@ -1488,7 +1488,7 @@ void msm_mode_object_event_notify(struct drm_mode_object *obj, static int msm_release(struct inode *inode, struct file *filp) { - struct drm_file *file_priv = filp->private_data; + struct drm_file *file_priv; struct drm_minor *minor; struct drm_device *dev; struct msm_drm_private *priv; @@ -1500,6 +1500,7 @@ static int msm_release(struct inode *inode, struct file *filp) mutex_lock(&msm_release_lock); + file_priv = filp->private_data; if (!file_priv) { ret = -EINVAL; goto end; From 018e528ec314842739f9a1887b6ea43b83f25ecc Mon Sep 17 00:00:00 2001 From: Mahadevan Date: Mon, 18 Oct 2021 12:10:34 +0530 Subject: [PATCH 2/8] disp: rotator: remove warning log from spin_lock On rotator commit failure resync timeline will happen which gives continuous warning logs in console leads to cpu throttling. To resolve this the warning message is removed from spin_lock. Change-Id: I5ce66413556518668769cad3bc6a900f9bdada4b Signed-off-by: Mahadevan --- rotator/sde_rotator_sync.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/rotator/sde_rotator_sync.c b/rotator/sde_rotator_sync.c index 4f7f54aa62f5..75a205791609 100644 --- a/rotator/sde_rotator_sync.c +++ b/rotator/sde_rotator_sync.c @@ -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. */ #define pr_fmt(fmt) "%s: " fmt, __func__ @@ -249,11 +249,13 @@ void sde_rotator_resync_timeline(struct sde_rot_timeline *tl) spin_lock_irqsave(&tl->lock, flags); val = tl->next_value - tl->curr_value; - if (val > 0) { - SDEROT_WARN("flush %s:%d\n", tl->name, val); + if (val > 0) sde_rotator_inc_timeline_locked(tl, val); - } spin_unlock_irqrestore(&tl->lock, flags); + + if (val > 0) + SDEROT_WARN("flush %s:%d\n", tl->name, val); + } /* From c667c77f1f80b9a401174011459a255a7a3dfb52 Mon Sep 17 00:00:00 2001 From: Krishna Manikandan Date: Mon, 18 Oct 2021 16:40:40 +0530 Subject: [PATCH 3/8] disp: msm: sde: disable CWB crop after cwb session is ended Add changes to disable CWB crop params as part of writeback disable. Change-Id: I18582ceb502e759ec4b67568562ac95ff3f0d359 Signed-off-by: Krishna Manikandan --- msm/sde/sde_encoder_phys_wb.c | 3 +++ msm/sde/sde_hw_wb.c | 3 +-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/msm/sde/sde_encoder_phys_wb.c b/msm/sde/sde_encoder_phys_wb.c index 58ba064f73ec..43c03e87fb0e 100644 --- a/msm/sde/sde_encoder_phys_wb.c +++ b/msm/sde/sde_encoder_phys_wb.c @@ -1727,6 +1727,9 @@ static void sde_encoder_phys_wb_disable(struct sde_encoder_phys *phys_enc) } if (phys_enc->in_clone_mode) { + if (hw_wb->ops.setup_crop) + hw_wb->ops.setup_crop(hw_wb, NULL, false); + _sde_encoder_phys_wb_setup_cwb(phys_enc, false); _sde_encoder_phys_wb_update_cwb_flush(phys_enc, false); phys_enc->enable_state = SDE_ENC_DISABLING; diff --git a/msm/sde/sde_hw_wb.c b/msm/sde/sde_hw_wb.c index e6c61e68dd27..608d0ea492d7 100644 --- a/msm/sde/sde_hw_wb.c +++ b/msm/sde/sde_hw_wb.c @@ -215,9 +215,8 @@ static void sde_hw_wb_crop(struct sde_hw_wb *ctx, struct sde_hw_wb_cfg *wb, bool struct sde_hw_blk_reg_map *c = &ctx->hw; u32 crop_xy; - crop_xy = (wb->crop.y << 16) | wb->crop.x; - if (crop) { + crop_xy = (wb->crop.y << 16) | wb->crop.x; SDE_REG_WRITE(c, WB_CROP_CTRL, 0x1); SDE_REG_WRITE(c, WB_CROP_OFFSET, crop_xy); } else { From c0783f528e4b851aeafad4d7023bb9bf06b12b6b Mon Sep 17 00:00:00 2001 From: Rajeev Nandan Date: Wed, 6 Oct 2021 20:59:56 +0530 Subject: [PATCH 4/8] disp: msm: dsi: Do not call devm_clk_put() with invalid clk Do not call devm_clk_put() if devm_clk_get() was failed for a given clk. The devm_clk_put() does not check for the validity of the input clk argumnet, and can cause NULL pointer dereference or some other errors if called with invalid clk argument. Change-Id: Ie626a5afed52a146ebd1a2092c7d9db9226dbfe0 Signed-off-by: Rajeev Nandan --- msm/dsi/dsi_ctrl.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/msm/dsi/dsi_ctrl.c b/msm/dsi/dsi_ctrl.c index 506181bc8776..89092690a678 100644 --- a/msm/dsi/dsi_ctrl.c +++ b/msm/dsi/dsi_ctrl.c @@ -657,34 +657,34 @@ static int dsi_ctrl_clocks_deinit(struct dsi_ctrl *ctrl) struct dsi_link_hs_clk_info *hs_link = &ctrl->clk_info.hs_link_clks; struct dsi_clk_link_set *rcg = &ctrl->clk_info.rcg_clks; - if (core->mdp_core_clk) + if (!IS_ERR_OR_NULL(core->mdp_core_clk)) devm_clk_put(&ctrl->pdev->dev, core->mdp_core_clk); - if (core->iface_clk) + if (!IS_ERR_OR_NULL(core->iface_clk)) devm_clk_put(&ctrl->pdev->dev, core->iface_clk); - if (core->core_mmss_clk) + if (!IS_ERR_OR_NULL(core->core_mmss_clk)) devm_clk_put(&ctrl->pdev->dev, core->core_mmss_clk); - if (core->bus_clk) + if (!IS_ERR_OR_NULL(core->bus_clk)) devm_clk_put(&ctrl->pdev->dev, core->bus_clk); - if (core->mnoc_clk) + if (!IS_ERR_OR_NULL(core->mnoc_clk)) devm_clk_put(&ctrl->pdev->dev, core->mnoc_clk); memset(core, 0x0, sizeof(*core)); - if (hs_link->byte_clk) + if (!IS_ERR_OR_NULL(hs_link->byte_clk)) devm_clk_put(&ctrl->pdev->dev, hs_link->byte_clk); - if (hs_link->pixel_clk) + if (!IS_ERR_OR_NULL(hs_link->pixel_clk)) devm_clk_put(&ctrl->pdev->dev, hs_link->pixel_clk); - if (lp_link->esc_clk) + if (!IS_ERR_OR_NULL(lp_link->esc_clk)) devm_clk_put(&ctrl->pdev->dev, lp_link->esc_clk); - if (hs_link->byte_intf_clk) + if (!IS_ERR_OR_NULL(hs_link->byte_intf_clk)) devm_clk_put(&ctrl->pdev->dev, hs_link->byte_intf_clk); memset(hs_link, 0x0, sizeof(*hs_link)); memset(lp_link, 0x0, sizeof(*lp_link)); - if (rcg->byte_clk) + if (!IS_ERR_OR_NULL(rcg->byte_clk)) devm_clk_put(&ctrl->pdev->dev, rcg->byte_clk); - if (rcg->pixel_clk) + if (!IS_ERR_OR_NULL(rcg->pixel_clk)) devm_clk_put(&ctrl->pdev->dev, rcg->pixel_clk); memset(rcg, 0x0, sizeof(*rcg)); From 1cbd7ae15233d7712e57028be43c62ccaf4bbb5d Mon Sep 17 00:00:00 2001 From: Soutrik Mukhopadhyay Date: Tue, 19 Oct 2021 19:02:58 +0530 Subject: [PATCH 5/8] disp: msm: dp: replace pr_err with DP_ERR This change replaces pr_err with DP_ERR in dp_display driver source code. Change-Id: I5c621ead001c5b9364511495fceba1aa7f41488d Signed-off-by: Soutrik Mukhopadhyay --- msm/dp/dp_display.c | 2 +- msm/dp/dp_drm.c | 4 ++-- msm/dp/dp_panel.c | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/msm/dp/dp_display.c b/msm/dp/dp_display.c index 62544f4d6f73..3e0fdbd26fce 100644 --- a/msm/dp/dp_display.c +++ b/msm/dp/dp_display.c @@ -3051,7 +3051,7 @@ static int dp_display_setup_colospace(struct dp_display *dp_display, struct dp_display_private *dp; if (!dp_display || !panel) { - pr_err("invalid input\n"); + DP_ERR("invalid input\n"); return -EINVAL; } diff --git a/msm/dp/dp_drm.c b/msm/dp/dp_drm.c index f1e870af0811..3c29801249c3 100644 --- a/msm/dp/dp_drm.c +++ b/msm/dp/dp_drm.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ #include @@ -336,7 +336,7 @@ int dp_connector_set_colorspace(struct drm_connector *connector, sde_conn = to_sde_connector(connector); if (!sde_conn->drv_panel) { - pr_err("invalid dp panel\n"); + DP_ERR("invalid dp panel\n"); return -EINVAL; } diff --git a/msm/dp/dp_panel.c b/msm/dp/dp_panel.c index 0d63f3aa230a..5369ab30bdb4 100644 --- a/msm/dp/dp_panel.c +++ b/msm/dp/dp_panel.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2021, The Linux Foundation. All rights reserved. */ #include "dp_panel.h" @@ -2571,7 +2571,7 @@ static int dp_panel_set_colorspace(struct dp_panel *dp_panel, struct dp_panel_private *panel; if (!dp_panel) { - pr_err("invalid input\n"); + DP_ERR("invalid input\n"); rc = -EINVAL; goto end; } From c03772f2f2d19c5b17c224819ef8958ea3bd5ba5 Mon Sep 17 00:00:00 2001 From: Kalyan Thota Date: Tue, 19 Oct 2021 23:28:30 -0700 Subject: [PATCH 6/8] msm: disp: rotator: add ROT macros for logs Avoid pr_err and use SDEROT macros for console logging. Change-Id: I4c0c6cf1d482a55f82c73572b1327695b85c5501 Signed-off-by: Kalyan Thota --- rotator/sde_rotator_base.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/rotator/sde_rotator_base.c b/rotator/sde_rotator_base.c index 76681b967761..f17905a9b057 100644 --- a/rotator/sde_rotator_base.c +++ b/rotator/sde_rotator_base.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2012, 2015-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2012, 2015-2021, The Linux Foundation. All rights reserved. */ #define pr_fmt(fmt) "%s: " fmt, __func__ @@ -79,7 +79,7 @@ u32 sde_apply_comp_ratio_factor(u32 quota, return quota; } -#define RES_1080p (1088*1920) +#define RES_1080p (1088*1920) #define RES_UHD (3840*2160) #define RES_WQXGA (2560*1600) #define XIN_HALT_TIMEOUT_US 0x4000 @@ -507,10 +507,10 @@ int sde_update_reg_bus_vote(struct reg_bus_client *bus_client, u32 usecase_ndx) } if (ret) { - pr_err("rotator: reg_bus_hdl set failed ab=%llu, ib=%llu\n", + SDEROT_ERR("rotator: reg_bus_hdl set failed ab=%llu, ib=%llu\n", reg_bus_value->ab, reg_bus_value->ib); if (sde_res->reg_bus_usecase_ndx == VOTE_INDEX_DISABLE) - pr_err("rotator: reg_bus_hdl was disabled\n"); + SDEROT_ERR("rotator: reg_bus_hdl was disabled\n"); } else { sde_res->reg_bus_usecase_ndx = max_usecase_ndx; } @@ -841,7 +841,7 @@ static int sde_mdp_bus_scale_register(struct sde_rot_data_type *mdata) mdata->reg_bus_hdl = of_icc_get(&mdata->pdev->dev, "qcom,sde-reg-bus"); if (mdata->reg_bus_hdl == NULL) { - pr_err("rotator: reg bus dt node missing\n"); + SDEROT_ERR("rotator: reg bus dt node missing\n"); return 0; } else if (IS_ERR(mdata->reg_bus_hdl)) { SDEROT_ERR("reg bus handle parsing failed\n"); From cf6ecb421493de16684a0a2ae4b89cb13c544dd0 Mon Sep 17 00:00:00 2001 From: Andhavarapu Karthik Date: Wed, 20 Oct 2021 12:55:53 +0530 Subject: [PATCH 7/8] disp: msm: sde: add evt log in rsc timer calculation This change adds required log in rsc timer calculation. Change-Id: If16487ae8783651b3a2ac4839928a15131b678ee Signed-off-by: Andhavarapu Karthik --- msm/sde_rsc.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/msm/sde_rsc.c b/msm/sde_rsc.c index 75dcb932a77d..4b4c13bca0a5 100644 --- a/msm/sde_rsc.c +++ b/msm/sde_rsc.c @@ -352,6 +352,8 @@ static u32 sde_rsc_timer_calculate(struct sde_rsc_priv *rsc, line_time_ns, prefill_time_ns); pr_debug("static wakeup time:%lld cxo:%u\n", total, cxo_period_ns); + SDE_EVT32(rsc->cmd_config.fps, rsc->cmd_config.vtotal, total); + pdc_backoff_time_ns = rsc_backoff_time_ns; rsc_backoff_time_ns = div_u64(rsc_backoff_time_ns, cxo_period_ns); rsc->timer_config.rsc_backoff_time_ns = (u32) rsc_backoff_time_ns; From a245be26e4170d71593f5bda62664b14c168a620 Mon Sep 17 00:00:00 2001 From: Jayaprakash Madisetty Date: Thu, 30 Sep 2021 20:41:20 +0530 Subject: [PATCH 8/8] disp: msm: sde: add changes to allocate compatible cwb mixers in RM This change parses new dt property CWB_MIXER_MASK, which signifies the compatible mixer_mask for the corresponding CWB block. During mixer allocation for CWB usecase, we use this cwb_mixer_mask to decide compatible mixers for built-in primary and secondary displays. In the current issue case, mixer allocation is as below in multi display usecase: primary: LM0 secondary: LM1 external: LM2 RM loops through available mixers and tries to allocate LM3 when CWB is triggered on primary display. But from HW perspective, LM0 is not muxed to LM3 causing wb timeouts. With current change LM3 gets skipped and LM4 gets allocated. Change-Id: I95ce16a083c9b9976a9dff309d7754085ee08958 Signed-off-by: Jayaprakash Madisetty --- msm/sde/sde_connector.c | 2 +- msm/sde/sde_connector.h | 1 + msm/sde/sde_encoder.c | 6 +-- msm/sde/sde_encoder.h | 8 ++-- msm/sde/sde_hw_catalog.c | 13 +++++- msm/sde/sde_hw_catalog.h | 6 ++- msm/sde/sde_rm.c | 90 ++++++++++++++++++++++++++++------------ 7 files changed, 87 insertions(+), 39 deletions(-) diff --git a/msm/sde/sde_connector.c b/msm/sde/sde_connector.c index a6de23aab43b..013ebf81887f 100644 --- a/msm/sde/sde_connector.c +++ b/msm/sde/sde_connector.c @@ -1833,7 +1833,7 @@ static int _sde_connector_lm_preference(struct sde_connector *sde_conn, return -EINVAL; } - sde_hw_mixer_set_preference(sde_kms->catalog, num_lm, disp_type); + sde_conn->lm_mask = sde_hw_mixer_set_preference(sde_kms->catalog, num_lm, disp_type); return ret; } diff --git a/msm/sde/sde_connector.h b/msm/sde/sde_connector.h index 94f868ccff29..2407b7efed42 100644 --- a/msm/sde/sde_connector.h +++ b/msm/sde/sde_connector.h @@ -547,6 +547,7 @@ struct sde_connector { bool hdr_supported; u32 color_enc_fmt; + u32 lm_mask; u8 hdr_plus_app_ver; u32 qsync_mode; diff --git a/msm/sde/sde_encoder.c b/msm/sde/sde_encoder.c index dd3b2cc033da..c334b11ae77c 100644 --- a/msm/sde/sde_encoder.c +++ b/msm/sde/sde_encoder.c @@ -267,13 +267,11 @@ static int _sde_encoder_wait_timeout(int32_t drm_id, int32_t hw_id, return rc; } -bool sde_encoder_is_primary_display(struct drm_encoder *drm_enc) +u32 sde_encoder_get_display_type(struct drm_encoder *drm_enc) { struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(drm_enc); - return sde_enc && - (sde_enc->disp_info.display_type == - SDE_CONNECTOR_PRIMARY); + return sde_enc ? sde_enc->disp_info.display_type : 0; } bool sde_encoder_is_dsi_display(struct drm_encoder *drm_enc) diff --git a/msm/sde/sde_encoder.h b/msm/sde/sde_encoder.h index 27116034c11b..3bd432072c8b 100644 --- a/msm/sde/sde_encoder.h +++ b/msm/sde/sde_encoder.h @@ -523,12 +523,12 @@ bool sde_encoder_is_cwb_disabling(struct drm_encoder *drm_enc, struct drm_crtc *drm_crtc); /** - * sde_encoder_is_primary_display - checks if underlying display is primary - * display or not. + * sde_encoder_get_display_type - returns the display_type of underlying + * display * @drm_enc: Pointer to drm encoder structure - * @Return: true if it is primary display. false if secondary display + * @Return: display_type */ -bool sde_encoder_is_primary_display(struct drm_encoder *enc); +u32 sde_encoder_get_display_type(struct drm_encoder *enc); /** * sde_encoder_is_dsi_display - checks if underlying display is DSI diff --git a/msm/sde/sde_hw_catalog.c b/msm/sde/sde_hw_catalog.c index 51875f9cd02f..f19c495ed440 100644 --- a/msm/sde/sde_hw_catalog.c +++ b/msm/sde/sde_hw_catalog.c @@ -425,6 +425,7 @@ enum { MIXER_BLOCKS, MIXER_DISP, MIXER_CWB, + MIXER_CWB_MASK, MIXER_PROP_MAX, }; @@ -710,6 +711,7 @@ static struct sde_prop_type mixer_prop[] = { PROP_TYPE_STRING_ARRAY}, {MIXER_CWB, "qcom,sde-mixer-cwb-pref", false, PROP_TYPE_STRING_ARRAY}, + {MIXER_CWB_MASK, "qcom,sde-mixer-cwb-mask", false, PROP_TYPE_U32_ARRAY}, }; static struct sde_prop_type mixer_blocks_prop[] = { @@ -1976,10 +1978,10 @@ void sde_hw_ctl_set_preference(struct sde_mdss_cfg *sde_cfg, } } -void sde_hw_mixer_set_preference(struct sde_mdss_cfg *sde_cfg, u32 num_lm, +u32 sde_hw_mixer_set_preference(struct sde_mdss_cfg *sde_cfg, u32 num_lm, uint32_t disp_type) { - u32 i, cnt = 0, sec_cnt = 0; + u32 i, cnt = 0, sec_cnt = 0, lm_mask = 0; if (disp_type == SDE_CONNECTOR_PRIMARY) { for (i = 0; i < sde_cfg->mixer_count; i++) { @@ -1998,6 +2000,7 @@ void sde_hw_mixer_set_preference(struct sde_mdss_cfg *sde_cfg, u32 num_lm, if (cnt < num_lm) { set_bit(SDE_DISP_PRIMARY_PREF, &sde_cfg->mixer[i].features); + lm_mask |= BIT(sde_cfg->mixer[i].id - 1); cnt++; } @@ -2036,10 +2039,13 @@ void sde_hw_mixer_set_preference(struct sde_mdss_cfg *sde_cfg, u32 num_lm, BIT(SDE_DISP_PRIMARY_PREF))) { set_bit(SDE_DISP_SECONDARY_PREF, &sde_cfg->mixer[i].features); + lm_mask |= BIT(sde_cfg->mixer[i].id - 1); cnt++; } } } + + return lm_mask; } static int sde_mixer_parse_dt(struct device_node *np, @@ -2151,6 +2157,9 @@ static int sde_mixer_parse_dt(struct device_node *np, if (BIT(mixer->id - LM_0) & sde_cfg->cwb_virtual_mixers_mask) set_bit(SDE_MIXER_IS_VIRTUAL, &mixer->features); + mixer->cwb_mask = !props->exists[MIXER_CWB_MASK] ? 0x0 : + PROP_VALUE_ACCESS(props->values, MIXER_CWB_MASK, i); + mixer->pingpong = pp_count > 0 ? pp_idx + PINGPONG_0 : PINGPONG_MAX; mixer->dspp = dspp_count > 0 ? dspp_idx + DSPP_0 diff --git a/msm/sde/sde_hw_catalog.h b/msm/sde/sde_hw_catalog.h index 4ba0764ac7b3..3e7ab2ad90d2 100644 --- a/msm/sde/sde_hw_catalog.h +++ b/msm/sde/sde_hw_catalog.h @@ -977,6 +977,7 @@ struct sde_sspp_cfg { * @pingpong: ID of connected PingPong, PINGPONG_MAX if unsupported * @ds: ID of connected DS, DS_MAX if unsupported * @lm_pair_mask: Bitmask of LMs that can be controlled by same CTL + * @cwb_mask: Bitmask of LMs connected to cwb mux from this LM id */ struct sde_lm_cfg { SDE_HW_BLK_INFO; @@ -985,6 +986,7 @@ struct sde_lm_cfg { u32 pingpong; u32 ds; unsigned long lm_pair_mask; + u32 cwb_mask; }; /** @@ -1641,8 +1643,10 @@ struct sde_mdss_hw_cfg_handler { * @sde_cfg: pointer to sspp cfg * @num_lm: num lms to set preference * @disp_type: is the given display primary/secondary + * + * Return: layer mixer mask allocated for the disp_type */ -void sde_hw_mixer_set_preference(struct sde_mdss_cfg *sde_cfg, u32 num_lm, +u32 sde_hw_mixer_set_preference(struct sde_mdss_cfg *sde_cfg, u32 num_lm, uint32_t disp_type); /** diff --git a/msm/sde/sde_rm.c b/msm/sde/sde_rm.c index dafddd66f6ec..4367cf9d2055 100644 --- a/msm/sde/sde_rm.c +++ b/msm/sde/sde_rm.c @@ -111,6 +111,8 @@ struct sde_rm_requirements { uint64_t top_ctrl; const struct sde_rm_topology_def *topology; struct sde_encoder_hw_resources hw_res; + u32 cwb_requested_disp_type; + u32 conn_lm_mask; }; /** @@ -981,7 +983,8 @@ static bool _sde_rm_check_lm_and_get_connected_blks( struct sde_rm_hw_blk **dspp, struct sde_rm_hw_blk **ds, struct sde_rm_hw_blk **pp, - struct sde_rm_hw_blk *primary_lm) + struct sde_rm_hw_blk *primary_lm, + u32 conn_lm_mask) { const struct sde_lm_cfg *lm_cfg = to_sde_hw_mixer(lm->hw)->cap; const struct sde_pingpong_cfg *pp_cfg; @@ -1038,6 +1041,13 @@ static bool _sde_rm_check_lm_and_get_connected_blks( SDE_DEBUG("fail: cwb supported lm not allocated\n"); return false; } + + if (lm_cfg->cwb_mask && RM_RQ_CWB(reqs) && + !(BIT(ffs(conn_lm_mask) - 1) & lm_cfg->cwb_mask)) { + SDE_DEBUG("cwb mixer not compatible id:%d cwb_mask:0x%x lm_mask:0x%x\n", + lm_cfg->id, lm_cfg->cwb_mask, conn_lm_mask); + return false; + } } else if ((!is_conn_primary && lm_primary_pref) || (!is_conn_secondary && lm_secondary_pref)) { SDE_DEBUG( @@ -1083,7 +1093,7 @@ static int _sde_rm_reserve_lms( struct sde_rm_hw_blk *ds[MAX_BLOCKS]; struct sde_rm_hw_blk *pp[MAX_BLOCKS]; struct sde_rm_hw_iter iter_i, iter_j; - u32 lm_mask = 0; + u32 lm_mask = 0, conn_lm_mask = 0; int lm_count = 0; int i, rc = 0; @@ -1092,6 +1102,9 @@ static int _sde_rm_reserve_lms( return 0; } + if (RM_RQ_CWB(reqs)) + conn_lm_mask = reqs->conn_lm_mask; + /* Find a primary mixer */ sde_rm_init_hw_iter(&iter_i, 0, SDE_HW_BLK_LM); while (lm_count != reqs->topology->num_lm && @@ -1115,12 +1128,15 @@ static int _sde_rm_reserve_lms( if (!_sde_rm_check_lm_and_get_connected_blks( rm, rsvp, reqs, lm[lm_count], &dspp[lm_count], &ds[lm_count], - &pp[lm_count], NULL)) + &pp[lm_count], NULL, conn_lm_mask)) continue; lm_mask |= (1 << iter_i.blk->id); ++lm_count; + if (RM_RQ_CWB(reqs)) + conn_lm_mask = conn_lm_mask & ~BIT(ffs(conn_lm_mask) - 1); + /* Return if peer is not needed */ if (lm_count == reqs->topology->num_lm) break; @@ -1140,7 +1156,7 @@ static int _sde_rm_reserve_lms( if (!_sde_rm_check_lm_and_get_connected_blks( rm, rsvp, reqs, iter_j.blk, &dspp[lm_count], &ds[lm_count], - &pp[lm_count], iter_i.blk)) + &pp[lm_count], iter_i.blk, conn_lm_mask)) continue; SDE_DEBUG("blk id = %d, _lm_ids[%d] = %d\n", @@ -1153,6 +1169,10 @@ static int _sde_rm_reserve_lms( lm_mask |= (1 << iter_j.blk->id); ++lm_count; + + if (RM_RQ_CWB(reqs)) + conn_lm_mask = conn_lm_mask & ~BIT(ffs(conn_lm_mask) - 1); + break; } @@ -2005,6 +2025,26 @@ int sde_rm_cont_splash_res_init(struct msm_drm_private *priv, return 0; } +static struct drm_connector *_sde_rm_get_connector( + struct drm_encoder *enc) +{ + struct drm_connector *conn = NULL, *conn_search; + struct sde_connector *c_conn = NULL; + struct drm_connector_list_iter conn_iter; + + drm_connector_list_iter_begin(enc->dev, &conn_iter); + drm_for_each_connector_iter(conn_search, &conn_iter) { + c_conn = to_sde_connector(conn_search); + if (c_conn->encoder == enc) { + conn = conn_search; + break; + } + } + drm_connector_list_iter_end(&conn_iter); + + return conn; +} + static int _sde_rm_populate_requirements( struct sde_rm *rm, struct drm_encoder *enc, @@ -2013,6 +2053,8 @@ static int _sde_rm_populate_requirements( struct sde_rm_requirements *reqs) { const struct drm_display_mode *mode = &crtc_state->mode; + struct drm_encoder *encoder_iter; + struct drm_connector *conn; int i, num_lm; reqs->top_ctrl = sde_connector_get_property(conn_state, @@ -2041,7 +2083,7 @@ static int _sde_rm_populate_requirements( reqs->top_ctrl |= BIT(SDE_RM_TOPCTL_DSPP); if (!RM_RQ_DS(reqs) && rm->hw_mdp->caps->has_dest_scaler && - sde_encoder_is_primary_display(enc)) + (sde_encoder_get_display_type(enc) == SDE_CONNECTOR_PRIMARY)) reqs->top_ctrl |= BIT(SDE_RM_TOPCTL_DS); } @@ -2075,8 +2117,22 @@ static int _sde_rm_populate_requirements( reqs->topology->top_name, reqs->topology->num_ctl); } - SDE_DEBUG("top_ctrl: 0x%llX num_h_tiles: %d\n", reqs->top_ctrl, - reqs->hw_res.display_num_of_h_tiles); + if (RM_RQ_CWB(reqs)) { + drm_for_each_encoder_mask(encoder_iter, enc->dev, + crtc_state->encoder_mask) { + if (drm_encoder_mask(encoder_iter) == drm_encoder_mask(enc)) + continue; + + reqs->cwb_requested_disp_type = sde_encoder_get_display_type(encoder_iter); + conn = _sde_rm_get_connector(encoder_iter); + if (conn) + reqs->conn_lm_mask = to_sde_connector(conn)->lm_mask; + break; + } + } + + SDE_DEBUG("top_ctrl: 0x%llX num_h_tiles: %d cwb_req_disp_type:%d\n", reqs->top_ctrl, + reqs->hw_res.display_num_of_h_tiles, reqs->cwb_requested_disp_type); SDE_DEBUG("num_lm: %d num_ctl: %d topology: %d split_display: %d\n", reqs->topology->num_lm, reqs->topology->num_ctl, reqs->topology->top_name, @@ -2120,26 +2176,6 @@ static struct sde_rm_rsvp *_sde_rm_get_rsvp_cur(struct sde_rm *rm, return _sde_rm_get_rsvp(rm, enc, false); } -static struct drm_connector *_sde_rm_get_connector( - struct drm_encoder *enc) -{ - struct drm_connector *conn = NULL, *conn_search; - struct sde_connector *c_conn = NULL; - struct drm_connector_list_iter conn_iter; - - drm_connector_list_iter_begin(enc->dev, &conn_iter); - drm_for_each_connector_iter(conn_search, &conn_iter) { - c_conn = to_sde_connector(conn_search); - if (c_conn->encoder == enc) { - conn = conn_search; - break; - } - } - drm_connector_list_iter_end(&conn_iter); - - return conn; -} - int sde_rm_update_topology(struct sde_rm *rm, struct drm_connector_state *conn_state, struct msm_display_topology *topology)