From 5ed42eb2439b43df4f5d21f6e010b5e91e802ed0 Mon Sep 17 00:00:00 2001 From: Alex Danila Date: Tue, 14 Dec 2021 13:37:22 -0500 Subject: [PATCH 1/9] disp: msm: dp: address race condition in LM allocation Addresses a race condition which could cause the RM to overcommiting LMs to DP when multiple DP displays are used. sde_rm_get_resource_info now uses the RM's mutex and assumes a null encoder is not a built in display so that it can return an accurate count of unreserved resources. DP layer now maintains internal accounting of LMs in use to avoid validating modes that have insufficient remaining resources. Change-Id: I908c1597c1d651b6f9c9b74a34137f30087d8801 Signed-off-by: Alex Danila --- msm/dp/dp_display.c | 65 ++++++++++++++++++++++++++++++++++++++------- msm/dp/dp_display.h | 1 + msm/dp/dp_drm.c | 4 +++ msm/dp/dp_mst_drm.c | 2 ++ msm/dp/dp_panel.h | 1 + msm/msm_drv.h | 2 ++ msm/sde/sde_rm.c | 24 +++++++++++------ 7 files changed, 82 insertions(+), 17 deletions(-) diff --git a/msm/dp/dp_display.c b/msm/dp/dp_display.c index 7559aba2..fd7eed54 100644 --- a/msm/dp/dp_display.c +++ b/msm/dp/dp_display.c @@ -202,6 +202,7 @@ struct dp_display_private { struct work_struct connect_work; struct work_struct attention_work; struct mutex session_lock; + struct mutex accounting_lock; bool hdcp_delayed_off; bool no_aux_switch; @@ -209,6 +210,7 @@ struct dp_display_private { struct dp_mst mst; u32 tot_dsc_blks_in_use; + u32 tot_lm_blks_in_use; bool process_hpd_connect; struct dev_pm_qos_request pm_qos_req[NR_CPUS]; @@ -1483,6 +1485,25 @@ static int dp_display_usbpd_configure_cb(struct device *dev) return 0; } +static void dp_display_clear_reservation(struct dp_display *dp, struct dp_panel *panel) +{ + struct dp_display_private *dp_display; + + if (!dp || !panel) { + DP_ERR("invalid params\n"); + return; + } + + dp_display = container_of(dp, struct dp_display_private, dp_display); + + mutex_lock(&dp_display->accounting_lock); + + dp_display->tot_lm_blks_in_use -= panel->max_lm; + panel->max_lm = 0; + + mutex_unlock(&dp_display->accounting_lock); +} + static void dp_display_clear_dsc_resources(struct dp_display_private *dp, struct dp_panel *panel) { @@ -1562,6 +1583,7 @@ static void dp_display_clean(struct dp_display_private *dp) dp_display_stream_pre_disable(dp, dp_panel); dp_display_stream_disable(dp, dp_panel); + dp_display_clear_reservation(&dp->dp_display, dp_panel); dp_panel->deinit(dp_panel, 0); } @@ -1589,6 +1611,8 @@ static int dp_display_handle_disconnect(struct dp_display_private *dp) dp_display_host_unready(dp); + dp->tot_lm_blks_in_use = 0; + mutex_unlock(&dp->session_lock); SDE_EVT32_EXTERNAL(SDE_EVTLOG_FUNC_EXIT, dp->state); @@ -2002,6 +2026,7 @@ static int dp_init_sub_modules(struct dp_display_private *dp) }; mutex_init(&dp->session_lock); + mutex_init(&dp->accounting_lock); dp->parser = dp_parser_get(dp->pdev); if (IS_ERR(dp->parser)) { @@ -2172,6 +2197,7 @@ static int dp_init_sub_modules(struct dp_display_private *dp) dp->cached_connector_status = connector_status_disconnected; dp->tot_dsc_blks_in_use = 0; + dp->tot_lm_blks_in_use = 0; dp->debug->hdcp_disabled = hdcp_disabled; dp_display_update_hdcp_status(dp, true); @@ -2806,6 +2832,8 @@ static int dp_display_unprepare(struct dp_display *dp_display, void *panel) /* log this as it results from user action of cable dis-connection */ DP_INFO("[OK]\n"); end: + dp->tot_lm_blks_in_use -= dp_panel->max_lm; + dp_panel->max_lm = 0; dp_panel->deinit(dp_panel, flags); mutex_unlock(&dp->session_lock); SDE_EVT32_EXTERNAL(SDE_EVTLOG_FUNC_EXIT, dp->state); @@ -2864,11 +2892,14 @@ static int dp_display_validate_topology(struct dp_display_private *dp, u32 num_lm = 0, num_dsc = 0, num_3dmux = 0; bool dsc_capable = dp_mode->capabilities & DP_PANEL_CAPS_DSC; u32 fps = dp_mode->timing.refresh_rate; + int avail_lm = 0; + + mutex_lock(&dp->accounting_lock); rc = msm_get_mixer_count(priv, mode, avail_res, &num_lm); if (rc) { DP_ERR("error getting mixer count. rc:%d\n", rc); - return rc; + goto end; } /* Merge using DSC, if enabled */ @@ -2876,7 +2907,7 @@ static int dp_display_validate_topology(struct dp_display_private *dp, rc = msm_get_dsc_count(priv, mode->hdisplay, &num_dsc); if (rc) { DP_ERR("error getting dsc count. rc:%d\n", rc); - return rc; + goto end; } num_dsc = max(num_lm, num_dsc); @@ -2886,7 +2917,8 @@ static int dp_display_validate_topology(struct dp_display_private *dp, avail_res->num_lm); /* Clear DSC caps and retry */ dp_mode->capabilities &= ~DP_PANEL_CAPS_DSC; - return -EAGAIN; + rc = -EAGAIN; + goto end; } else { /* Only DSCMERGE is supported on DP */ num_lm = num_dsc; @@ -2897,24 +2929,36 @@ static int dp_display_validate_topology(struct dp_display_private *dp, num_3dmux = 1; } - if (num_lm > avail_res->num_lm) { + avail_lm = avail_res->num_lm + avail_res->num_lm_in_use - dp->tot_lm_blks_in_use; + if ((num_lm > dp_panel->max_lm) && (num_lm > avail_lm)) { DP_DEBUG("mode %sx%d is invalid, not enough lm %d %d\n", - mode->name, fps, num_lm, num_lm, avail_res->num_lm); - return -EPERM; + mode->name, fps, num_lm, avail_res->num_lm); + rc = -EPERM; + goto end; } else if (!num_dsc && (num_lm == dual && !num_3dmux)) { DP_DEBUG("mode %sx%d is invalid, not enough 3dmux %d %d\n", mode->name, fps, num_3dmux, avail_res->num_3dmux); - return -EPERM; + rc = -EPERM; + goto end; } else if (num_lm == quad && num_dsc != quad) { DP_DEBUG("mode %sx%d is invalid, unsupported DP topology lm:%d dsc:%d\n", mode->name, fps, num_lm, num_dsc); - return -EPERM; + rc = -EPERM; + goto end; } DP_DEBUG_V("mode %sx%d is valid, supported DP topology lm:%d dsc:%d 3dmux:%d\n", mode->name, fps, num_lm, num_dsc, num_3dmux); - return 0; + dp->tot_lm_blks_in_use -= dp_panel->max_lm; + dp_panel->max_lm = num_lm > avail_res->num_lm_in_use ? max(dp_panel->max_lm, num_lm) : 0; + dp->tot_lm_blks_in_use += dp_panel->max_lm; + + rc = 0; + +end: + mutex_unlock(&dp->accounting_lock); + return rc; } static enum drm_mode_status dp_display_validate_mode( @@ -2970,6 +3014,8 @@ static enum drm_mode_status dp_display_validate_mode( mode_status = MODE_OK; end: + if (mode_status != MODE_OK) + dp_display_clear_reservation(dp_display, dp_panel); mutex_unlock(&dp->session_lock); DP_DEBUG_V("[%s] mode is %s\n", mode->name, @@ -3636,6 +3682,7 @@ static int dp_display_probe(struct platform_device *pdev) g_dp_display->set_colorspace = dp_display_setup_colospace; g_dp_display->get_available_dp_resources = dp_display_get_available_dp_resources; + g_dp_display->clear_reservation = dp_display_clear_reservation; rc = component_add(&pdev->dev, &dp_display_comp_ops); if (rc) { diff --git a/msm/dp/dp_display.h b/msm/dp/dp_display.h index 45f5fec0..11a0bb87 100644 --- a/msm/dp/dp_display.h +++ b/msm/dp/dp_display.h @@ -105,6 +105,7 @@ struct dp_display { int (*get_available_dp_resources)(struct dp_display *dp_display, const struct msm_resource_caps_info *avail_res, struct msm_resource_caps_info *max_dp_avail_res); + void (*clear_reservation)(struct dp_display *dp, struct dp_panel *panel); }; void *get_ipc_log_context(void); diff --git a/msm/dp/dp_drm.c b/msm/dp/dp_drm.c index 275f1044..4bcb3025 100644 --- a/msm/dp/dp_drm.c +++ b/msm/dp/dp_drm.c @@ -1,5 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2017-2021, The Linux Foundation. All rights reserved. */ @@ -256,6 +257,8 @@ static void dp_bridge_mode_set(struct drm_bridge *drm_bridge, dp->convert_to_dp_mode(dp, bridge->dp_panel, adjusted_mode, &bridge->dp_mode); + + dp->clear_reservation(dp, bridge->dp_panel); } static bool dp_bridge_mode_fixup(struct drm_bridge *drm_bridge, @@ -289,6 +292,7 @@ static bool dp_bridge_mode_fixup(struct drm_bridge *drm_bridge, dp = bridge->display; dp->convert_to_dp_mode(dp, bridge->dp_panel, mode, &dp_mode); + dp->clear_reservation(dp, bridge->dp_panel); convert_to_drm_mode(&dp_mode, adjusted_mode); end: return ret; diff --git a/msm/dp/dp_mst_drm.c b/msm/dp/dp_mst_drm.c index 5e72dcb7..477b5f5d 100644 --- a/msm/dp/dp_mst_drm.c +++ b/msm/dp/dp_mst_drm.c @@ -345,6 +345,7 @@ static bool dp_mst_bridge_mode_fixup(struct drm_bridge *drm_bridge, dp = bridge->display; dp->convert_to_dp_mode(dp, bridge_state->dp_panel, mode, &dp_mode); + dp->clear_reservation(dp, bridge_state->dp_panel); convert_to_drm_mode(&dp_mode, adjusted_mode); DP_MST_DEBUG("mst bridge [%d] mode:%s fixup\n", bridge->id, mode->name); @@ -775,6 +776,7 @@ static void dp_mst_bridge_mode_set(struct drm_bridge *drm_bridge, memcpy(&bridge->drm_mode, adjusted_mode, sizeof(bridge->drm_mode)); dp->convert_to_dp_mode(dp, bridge->dp_panel, adjusted_mode, &bridge->dp_mode); + dp->clear_reservation(dp, dp_bridge_state->dp_panel); DP_MST_INFO("mst bridge:%d conn:%d mode set complete %s\n", bridge->id, DP_MST_CONN_ID(bridge), mode->name); diff --git a/msm/dp/dp_panel.h b/msm/dp/dp_panel.h index 3e718820..92b0743b 100644 --- a/msm/dp/dp_panel.h +++ b/msm/dp/dp_panel.h @@ -137,6 +137,7 @@ struct dp_panel { u32 pbn; u32 dsc_blks_in_use; + u32 max_lm; /* DRM connector assosiated with this panel */ struct drm_connector *connector; diff --git a/msm/msm_drv.h b/msm/msm_drv.h index f97e9976..39f35fa0 100644 --- a/msm/msm_drv.h +++ b/msm/msm_drv.h @@ -828,6 +828,7 @@ struct msm_mode_info { /** * struct msm_resource_caps_info - defines hw resources + * @num_lm_in_use number of layer mixers allocated to a specified encoder * @num_lm number of layer mixers available * @num_dsc number of dsc available * @num_vdc number of vdc available @@ -836,6 +837,7 @@ struct msm_mode_info { * @max_mixer_width: max width supported by layer mixer */ struct msm_resource_caps_info { + uint32_t num_lm_in_use; uint32_t num_lm; uint32_t num_dsc; uint32_t num_vdc; diff --git a/msm/sde/sde_rm.c b/msm/sde/sde_rm.c index 76df522d..081e5c07 100644 --- a/msm/sde/sde_rm.c +++ b/msm/sde/sde_rm.c @@ -284,27 +284,33 @@ void sde_rm_get_resource_info(struct sde_rm *rm, { struct sde_rm_hw_blk *blk; enum sde_hw_blk_type type; - struct sde_rm_rsvp rsvp; const struct sde_lm_cfg *lm_cfg; bool is_built_in, is_pref; u32 lm_pref = (BIT(SDE_DISP_PRIMARY_PREF) | BIT(SDE_DISP_SECONDARY_PREF)); + mutex_lock(&rm->rm_lock); + /* Get all currently available resources */ memcpy(avail_res, &rm->avail_res, sizeof(rm->avail_res)); + /** + * When the encoder is null, assume display is external in order to return the count of + * availalbe non-preferred LMs + */ if (!drm_enc) - return; - - is_built_in = sde_encoder_is_built_in_display(drm_enc); - - rsvp.enc_id = drm_enc->base.id; + is_built_in = false; + else + is_built_in = sde_encoder_is_built_in_display(drm_enc); for (type = 0; type < SDE_HW_BLK_MAX; type++) { list_for_each_entry(blk, &rm->hw_blks[type], list) { /* Add back resources allocated to the given encoder */ - if (blk->rsvp && blk->rsvp->enc_id == rsvp.enc_id) + if (blk->rsvp && drm_enc && blk->rsvp->enc_id == drm_enc->base.id) { _sde_rm_inc_resource_info(rm, avail_res, blk); + if (type == SDE_HW_BLK_LM) + avail_res->num_lm_in_use++; + } /** * Remove unallocated preferred lms that cannot reserved @@ -314,11 +320,13 @@ void sde_rm_get_resource_info(struct sde_rm *rm, lm_cfg = to_sde_hw_mixer(blk->hw)->cap; is_pref = lm_cfg->features & lm_pref; - if (!blk->rsvp && !is_built_in && is_pref) + if (!blk->rsvp && !blk->rsvp_nxt && !is_built_in && is_pref) _sde_rm_dec_resource_info(rm, avail_res, blk); } } } + + mutex_unlock(&rm->rm_lock); } static void _sde_rm_print_rsvps( From e972b51d5c7bd415f58911ad8f0f9821a08c6f13 Mon Sep 17 00:00:00 2001 From: Veera Sundaram Sankaran Date: Fri, 29 Jul 2022 16:02:21 -0700 Subject: [PATCH 2/9] disp: msm: sde: reset wb output crop during cwb disable Reset the wb crop configs from hardware, while disabling concurrent writeback. This avoids stale configs which affects the subsequent writeback session. Change-Id: I4927effd0650bcdca2852a5d72c3e5478683a90f Signed-off-by: Veera Sundaram Sankaran --- msm/sde/sde_encoder_phys_wb.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/msm/sde/sde_encoder_phys_wb.c b/msm/sde/sde_encoder_phys_wb.c index 1fa6494a..44e713a5 100644 --- a/msm/sde/sde_encoder_phys_wb.c +++ b/msm/sde/sde_encoder_phys_wb.c @@ -549,6 +549,7 @@ static void _sde_encoder_phys_wb_setup_cwb(struct sde_encoder_phys *phys_enc, bo { struct sde_encoder_phys_wb *wb_enc = to_sde_encoder_phys_wb(phys_enc); struct sde_hw_wb *hw_wb = wb_enc->hw_wb; + struct sde_hw_wb_cfg *wb_cfg = &wb_enc->wb_cfg; struct sde_hw_ctl *hw_ctl = phys_enc->hw_ctl; struct sde_crtc *crtc = to_sde_crtc(wb_enc->crtc); struct sde_hw_pingpong *hw_pp = phys_enc->hw_pp; @@ -606,6 +607,9 @@ static void _sde_encoder_phys_wb_setup_cwb(struct sde_encoder_phys *phys_enc, bo test_bit(SDE_WB_DCWB_CTRL, &hw_wb->caps->features)) hw_wb->ops.bind_dcwb_pp_blk(hw_wb, enable, hw_pp->idx); + if (hw_wb->ops.setup_crop && !enable) + hw_wb->ops.setup_crop(hw_wb, wb_cfg, false); + if (hw_ctl->ops.update_intf_cfg) { hw_ctl->ops.update_intf_cfg(hw_ctl, &intf_cfg, enable); SDE_DEBUG("[enc:%d wb:%d] in CWB/DCWB mode on CTL_%d PP-%d merge3d:%d\n", From 9857e36ddb4d220b549084013832decfb0583604 Mon Sep 17 00:00:00 2001 From: Srihitha Tangudu Date: Tue, 22 Mar 2022 18:07:25 +0530 Subject: [PATCH 3/9] disp: msm: dsi: Avoid re-initializing PLL registers during dyn clk switch Currently we are always initializing PLL registers whenever PLL is configured. Re-initializing PLL registers during dynamic clock switch in case of cphy video mode is moving the PLL to some bad state resulting in display freeze. Avoid this by restricting initialization of PLL registers to only while turning on the PLL. Change-Id: I09eacbb37fff4e0e91d226ac08e7d5a2bfbbfe26 Signed-off-by: Srihitha Tangudu --- msm/dsi/dsi_pll_5nm.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/msm/dsi/dsi_pll_5nm.c b/msm/dsi/dsi_pll_5nm.c index 000be5e1..165cf5a7 100644 --- a/msm/dsi/dsi_pll_5nm.c +++ b/msm/dsi/dsi_pll_5nm.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */ #include @@ -1556,7 +1557,8 @@ int dsi_pll_5nm_configure(void *pll, bool commit) if (rsc->slave) dsi_pll_enable_pll_bias(rsc->slave); - dsi_pll_init_val(rsc); + if (commit) + dsi_pll_init_val(rsc); rc = dsi_pll_5nm_set_byteclk_div(rsc, commit); From ac427feb9e3cc41687ca3a85d14c59daf4285a15 Mon Sep 17 00:00:00 2001 From: Veera Sundaram Sankaran Date: Wed, 3 Aug 2022 14:10:47 -0700 Subject: [PATCH 4/9] disp: msm: sde: reduce stack size in _sde_crtc_check_rois Use pointer and allocate dynamic memory for msm_mode_info in _sde_crtc_check_rois instead of object to reduce the stack memory size. Change-Id: Ida8fc7e2b94e19b3c791dcda55a465a4107ef976 Signed-off-by: Veera Sundaram Sankaran Signed-off-by: Jeykumar Sankaran --- msm/sde/sde_crtc.c | 43 +++++++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 18 deletions(-) diff --git a/msm/sde/sde_crtc.c b/msm/sde/sde_crtc.c index a8143c8e..ae47ea51 100644 --- a/msm/sde/sde_crtc.c +++ b/msm/sde/sde_crtc.c @@ -1360,15 +1360,17 @@ static int _sde_crtc_check_rois(struct drm_crtc *crtc, { struct sde_crtc *sde_crtc; struct sde_crtc_state *sde_crtc_state; - struct msm_mode_info mode_info; + struct msm_mode_info *mode_info; u32 crtc_width, crtc_height, mixer_width, mixer_height; struct drm_display_mode *adj_mode; - int rc, lm_idx, i; + int rc = 0, lm_idx, i; if (!crtc || !state) return -EINVAL; - memset(&mode_info, 0, sizeof(mode_info)); + mode_info = kzalloc(sizeof(struct msm_mode_info), GFP_KERNEL); + if (!mode_info) + return -ENOMEM; sde_crtc = to_sde_crtc(crtc); sde_crtc_state = to_sde_crtc_state(state); @@ -1383,7 +1385,8 @@ static int _sde_crtc_check_rois(struct drm_crtc *crtc, SDE_ERROR("%s: invalid w/h crtc:%d,%d, mixer:%d,%d, num_mixers:%d\n", sde_crtc->name, crtc_width, crtc_height, mixer_width, mixer_height, sde_crtc->num_mixers); - return -EINVAL; + rc = -EINVAL; + goto end; } /* @@ -1396,54 +1399,58 @@ static int _sde_crtc_check_rois(struct drm_crtc *crtc, if (!conn || !conn->state) continue; - rc = sde_connector_state_get_mode_info(conn->state, &mode_info); + rc = sde_connector_state_get_mode_info(conn->state, mode_info); if (rc) { SDE_ERROR("failed to get mode info\n"); - return -EINVAL; + rc = -EINVAL; + goto end; } if (sde_connector_is_3d_merge_enabled(conn) && (mixer_width % 2)) { SDE_ERROR( "%s: invalid width w/ 3d-merge - mixer_w:%d, crtc_w:%d, num_mixers:%d\n", sde_crtc->name, crtc_width, mixer_width, sde_crtc->num_mixers); - return -EINVAL; + rc = -EINVAL; + goto end; } - if (!mode_info.roi_caps.enabled) + if (!mode_info->roi_caps.enabled) continue; if (sde_crtc_state->user_roi_list.num_rects > - mode_info.roi_caps.num_roi) { + mode_info->roi_caps.num_roi) { SDE_ERROR("roi count is exceeding limit, %d > %d\n", sde_crtc_state->user_roi_list.num_rects, - mode_info.roi_caps.num_roi); - return -E2BIG; + mode_info->roi_caps.num_roi); + rc = -E2BIG; + goto end; } rc = _sde_crtc_set_crtc_roi(crtc, state); if (rc) - return rc; + goto end; rc = _sde_crtc_check_autorefresh(crtc, state); if (rc) - return rc; + goto end; for (lm_idx = 0; lm_idx < sde_crtc->num_mixers; lm_idx++) { rc = _sde_crtc_set_lm_roi(crtc, state, lm_idx); if (rc) - return rc; + goto end; } rc = _sde_crtc_check_rois_centered_and_symmetric(crtc, state); if (rc) - return rc; + goto end; rc = _sde_crtc_check_planes_within_crtc_roi(crtc, state); if (rc) - return rc; + goto end; } - - return 0; +end: + kfree(mode_info); + return rc; } static u32 _sde_crtc_calc_gcd(u32 a, u32 b) From 5e0d93196bb2adca2387c1bed4d4d9fe3b580376 Mon Sep 17 00:00:00 2001 From: Nisarg Bhavsar Date: Tue, 21 Jun 2022 18:54:15 -0700 Subject: [PATCH 5/9] disp: msm: dsi: Enable TPG functionality Allow TPG patterns to be displayed on command mode and video mode panels. Change-Id: Ie9ba9b404ceb965f8a06d1f19e932dd2e051983b Signed-off-by: Nisarg Bhavsar --- msm/dsi/dsi_catalog.h | 4 +++- msm/dsi/dsi_ctrl.c | 46 ++++++++++++++++++++++++++++----------- msm/dsi/dsi_ctrl.h | 18 ++++++++++++++- msm/dsi/dsi_ctrl_hw.h | 32 ++++++++++++++++++++++++++- msm/dsi/dsi_ctrl_hw_cmn.c | 31 ++++++++++++++++++++++---- msm/dsi/dsi_display.c | 17 +++++++++++---- msm/dsi/dsi_display.h | 6 ++++- 7 files changed, 129 insertions(+), 25 deletions(-) diff --git a/msm/dsi/dsi_catalog.h b/msm/dsi/dsi_catalog.h index a364f36e..c89aa728 100644 --- a/msm/dsi/dsi_catalog.h +++ b/msm/dsi/dsi_catalog.h @@ -164,7 +164,9 @@ void dsi_ctrl_hw_cmn_cmd_test_pattern_setup(struct dsi_ctrl_hw *ctrl, enum dsi_test_pattern type, u32 init_val, u32 stream_id); -void dsi_ctrl_hw_cmn_test_pattern_enable(struct dsi_ctrl_hw *ctrl, bool enable); +void dsi_ctrl_hw_cmn_test_pattern_enable(struct dsi_ctrl_hw *ctrl, bool enable, + enum dsi_ctrl_tpg_pattern pattern, + enum dsi_op_mode panel_mode); void dsi_ctrl_hw_cmn_trigger_cmd_test_pattern(struct dsi_ctrl_hw *ctrl, u32 stream_id); diff --git a/msm/dsi/dsi_ctrl.c b/msm/dsi/dsi_ctrl.c index ba522e0b..120f15fc 100644 --- a/msm/dsi/dsi_ctrl.c +++ b/msm/dsi/dsi_ctrl.c @@ -3741,7 +3741,9 @@ error: * * Return: error code. */ -int dsi_ctrl_set_tpg_state(struct dsi_ctrl *dsi_ctrl, bool on) +int dsi_ctrl_set_tpg_state(struct dsi_ctrl *dsi_ctrl, bool on, + enum dsi_test_pattern type, u32 init_val, + enum dsi_ctrl_tpg_pattern pattern) { int rc = 0; @@ -3760,19 +3762,13 @@ int dsi_ctrl_set_tpg_state(struct dsi_ctrl *dsi_ctrl, bool on) } if (on) { - if (dsi_ctrl->host_config.panel_mode == DSI_OP_VIDEO_MODE) { - dsi_ctrl->hw.ops.video_test_pattern_setup(&dsi_ctrl->hw, - DSI_TEST_PATTERN_INC, - 0xFFFF); - } else { - dsi_ctrl->hw.ops.cmd_test_pattern_setup( - &dsi_ctrl->hw, - DSI_TEST_PATTERN_INC, - 0xFFFF, - 0x0); - } + if (dsi_ctrl->host_config.panel_mode == DSI_OP_VIDEO_MODE) + dsi_ctrl->hw.ops.video_test_pattern_setup(&dsi_ctrl->hw, type, init_val); + else + dsi_ctrl->hw.ops.cmd_test_pattern_setup(&dsi_ctrl->hw, type, init_val, 0x0); } - dsi_ctrl->hw.ops.test_pattern_enable(&dsi_ctrl->hw, on); + dsi_ctrl->hw.ops.test_pattern_enable(&dsi_ctrl->hw, on, pattern, + dsi_ctrl->host_config.panel_mode); DSI_CTRL_DEBUG(dsi_ctrl, "Set test pattern state=%d\n", on); dsi_ctrl_update_state(dsi_ctrl, DSI_CTRL_OP_TPG, on); @@ -3781,6 +3777,30 @@ error: return rc; } +/** + * dsi_ctrl_trigger_test_pattern() - trigger a command mode frame update with test pattern + * @dsi_ctrl: DSI controller handle. + * + * Trigger a command mode frame update with chosen test pattern. + * + * Return: error code. + */ +int dsi_ctrl_trigger_test_pattern(struct dsi_ctrl *dsi_ctrl) +{ + int ret = 0; + + if (!dsi_ctrl) { + DSI_CTRL_ERR(dsi_ctrl, "Invalid params\n"); + return -EINVAL; + } + + mutex_lock(&dsi_ctrl->ctrl_lock); + dsi_ctrl->hw.ops.trigger_cmd_test_pattern(&dsi_ctrl->hw, 0); + mutex_unlock(&dsi_ctrl->ctrl_lock); + + return ret; +} + /** * dsi_ctrl_set_host_engine_state() - set host engine state * @dsi_ctrl: DSI Controller handle. diff --git a/msm/dsi/dsi_ctrl.h b/msm/dsi/dsi_ctrl.h index b1a5a900..4735650a 100644 --- a/msm/dsi/dsi_ctrl.h +++ b/msm/dsi/dsi_ctrl.h @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. */ @@ -573,13 +574,28 @@ int dsi_ctrl_set_roi(struct dsi_ctrl *dsi_ctrl, struct dsi_rect *roi, * dsi_ctrl_set_tpg_state() - enable/disable test pattern on the controller * @dsi_ctrl: DSI controller handle. * @on: enable/disable test pattern. + * @type: type of test pattern to generate. + * @init_val: seed value for generating test pattern. + * @pattern: test pattern to generate. * * Test pattern can be enabled only after Video engine (for video mode panels) * or command engine (for cmd mode panels) is enabled. * * Return: error code. */ -int dsi_ctrl_set_tpg_state(struct dsi_ctrl *dsi_ctrl, bool on); +int dsi_ctrl_set_tpg_state(struct dsi_ctrl *dsi_ctrl, bool on, + enum dsi_test_pattern type, u32 init_val, + enum dsi_ctrl_tpg_pattern pattern); + +/** + * dsi_ctrl_trigger_test_pattern() - trigger a command mode frame update with test pattern + * @dsi_ctrl: DSI controller handle. + * + * Trigger a command mode frame update with chosen test pattern. + * + * Return: error code. + */ +int dsi_ctrl_trigger_test_pattern(struct dsi_ctrl *dsi_ctrl); /** * dsi_ctrl_transfer_prepare() - Set up a command transfer diff --git a/msm/dsi/dsi_ctrl_hw.h b/msm/dsi/dsi_ctrl_hw.h index ee01df53..2559e906 100644 --- a/msm/dsi/dsi_ctrl_hw.h +++ b/msm/dsi/dsi_ctrl_hw.h @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. */ @@ -41,6 +42,29 @@ */ #define DSI_CTRL_HW_CMD_WAIT_FOR_TRIGGER 0x1 +/** + * enum dsi_ctrl_tpg_pattern - type of TPG pattern + * @DSI_CTRL_TPG_COUNTER: + * @DSI_CTRL_TPG_FIXED: + * @DSI_CTRL_TPG_COLOR_RAMP_64L_64P: + * @DSI_CTRL_TPG_COLOR_RAMP_64L_256P: + * @DSI_CTRL_TPG_GRAYSCALE_RAMP: + * @DSI_CTRL_TPG_COLOR_SQUARE: + * @DSI_CTRL_TPG_CHECKERED_RECTANGLE: + * @DSI_CTRL_TPG_BASIC_COLOR_CHANGING: + */ +enum dsi_ctrl_tpg_pattern { + DSI_CTRL_TPG_COUNTER = 0, + DSI_CTRL_TPG_FIXED, + DSI_CTRL_TPG_COLOR_RAMP_64L_64P, + DSI_CTRL_TPG_COLOR_RAMP_64L_256P, + DSI_CTRL_TPG_BLACK_WHITE_VERTICAL_LINES, + DSI_CTRL_TPG_GRAYSCALE_RAMP, + DSI_CTRL_TPG_COLOR_SQUARE, + DSI_CTRL_TPG_CHECKERED_RECTANGLE, + DSI_CTRL_TPG_BASIC_COLOR_CHANGING +}; + /** * enum dsi_ctrl_version - version of the dsi host controller * @DSI_CTRL_VERSION_UNKNOWN: Unknown controller version @@ -92,12 +116,14 @@ enum dsi_ctrl_hw_features { * @DSI_TEST_PATTERN_FIXED: Test pattern is fixed, based on init value. * @DSI_TEST_PATTERN_INC: Incremental test pattern, base on init value. * @DSI_TEST_PATTERN_POLY: Pattern generated from polynomial and init val. + * @DSI_TEST_PATTERN_GENERAL: MDSS general test pattern. * @DSI_TEST_PATTERN_MAX: */ enum dsi_test_pattern { DSI_TEST_PATTERN_FIXED = 0, DSI_TEST_PATTERN_INC, DSI_TEST_PATTERN_POLY, + DSI_TEST_PATTERN_GENERAL, DSI_TEST_PATTERN_MAX }; @@ -727,8 +753,12 @@ struct dsi_ctrl_hw_ops { * test_pattern_enable() - enable test pattern engine * @ctrl: Pointer to the controller host hardware. * @enable: Enable/Disable test pattern engine. + * @pattern: Type of TPG pattern + * @panel_mode: DSI operation mode */ - void (*test_pattern_enable)(struct dsi_ctrl_hw *ctrl, bool enable); + void (*test_pattern_enable)(struct dsi_ctrl_hw *ctrl, bool enable, + enum dsi_ctrl_tpg_pattern pattern, + enum dsi_op_mode panel_mode); /** * clear_phy0_ln_err() - clear DSI PHY lane-0 errors diff --git a/msm/dsi/dsi_ctrl_hw_cmn.c b/msm/dsi/dsi_ctrl_hw_cmn.c index 1045e31e..576ab998 100644 --- a/msm/dsi/dsi_ctrl_hw_cmn.c +++ b/msm/dsi/dsi_ctrl_hw_cmn.c @@ -1516,20 +1516,23 @@ void dsi_ctrl_hw_cmn_video_test_pattern_setup(struct dsi_ctrl_hw *ctrl, enum dsi_test_pattern type, u32 init_val) { - u32 reg = 0; + u32 reg = 0, pattern_sel_shift = 4; DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_VIDEO_INIT_VAL, init_val); switch (type) { case DSI_TEST_PATTERN_FIXED: - reg |= (0x2 << 4); + reg |= (0x2 << pattern_sel_shift); break; case DSI_TEST_PATTERN_INC: - reg |= (0x1 << 4); + reg |= (0x1 << pattern_sel_shift); break; case DSI_TEST_PATTERN_POLY: DSI_W32(ctrl, DSI_TEST_PATTERN_GEN_VIDEO_POLY, 0xF0F0F); break; + case DSI_TEST_PATTERN_GENERAL: + reg |= (0x3 << pattern_sel_shift); + break; default: break; } @@ -1590,6 +1593,9 @@ void dsi_ctrl_hw_cmn_cmd_test_pattern_setup(struct dsi_ctrl_hw *ctrl, case DSI_TEST_PATTERN_POLY: DSI_W32(ctrl, poly_offset, 0xF0F0F); break; + case DSI_TEST_PATTERN_GENERAL: + reg |= (0x3 << pattern_sel_shift); + break; default: break; } @@ -1602,11 +1608,28 @@ void dsi_ctrl_hw_cmn_cmd_test_pattern_setup(struct dsi_ctrl_hw *ctrl, * test_pattern_enable() - enable test pattern engine * @ctrl: Pointer to the controller host hardware. * @enable: Enable/Disable test pattern engine. + * @pattern: Type of TPG pattern + * @panel_mode: DSI operation mode */ void dsi_ctrl_hw_cmn_test_pattern_enable(struct dsi_ctrl_hw *ctrl, - bool enable) + bool enable, enum dsi_ctrl_tpg_pattern pattern, + enum dsi_op_mode panel_mode) { u32 reg = DSI_R32(ctrl, DSI_TEST_PATTERN_GEN_CTRL); + u32 reg_tpg_main_control = 0; + u32 reg_tpg_video_config = BIT(0); + + reg_tpg_video_config |= BIT(2); + + if (panel_mode == DSI_OP_CMD_MODE) { + reg_tpg_main_control = BIT(pattern); + DSI_W32(ctrl, DSI_TPG_MAIN_CONTROL2, reg_tpg_main_control); + } else { + reg_tpg_main_control = BIT(pattern + 1); + DSI_W32(ctrl, DSI_TPG_MAIN_CONTROL, reg_tpg_main_control); + } + + DSI_W32(ctrl, DSI_TPG_VIDEO_CONFIG, reg_tpg_video_config); if (enable) reg |= BIT(0); diff --git a/msm/dsi/dsi_display.c b/msm/dsi/dsi_display.c index aa01890d..2f442bd4 100644 --- a/msm/dsi/dsi_display.c +++ b/msm/dsi/dsi_display.c @@ -7763,7 +7763,10 @@ error: return rc; } -int dsi_display_set_tpg_state(struct dsi_display *display, bool enable) +int dsi_display_set_tpg_state(struct dsi_display *display, bool enable, + enum dsi_test_pattern type, + u32 init_val, + enum dsi_ctrl_tpg_pattern pattern) { int rc = 0; int i; @@ -7776,12 +7779,18 @@ int dsi_display_set_tpg_state(struct dsi_display *display, bool enable) display_for_each_ctrl(i, display) { ctrl = &display->ctrl[i]; - rc = dsi_ctrl_set_tpg_state(ctrl->ctrl, enable); + rc = dsi_ctrl_set_tpg_state(ctrl->ctrl, enable, type, init_val, pattern); if (rc) { - DSI_ERR("[%s] failed to set tpg state for host_%d\n", - display->name, i); + DSI_ERR("[%s] failed to set tpg state for host_%d\n", display->name, i); goto error; } + if (enable && ctrl->ctrl->host_config.panel_mode == DSI_OP_CMD_MODE) { + rc = dsi_ctrl_trigger_test_pattern(ctrl->ctrl); + if (rc) { + DSI_ERR("[%s] failed to start tpg for host_%d\n", display->name, i); + goto error; + } + } } display->is_tpg_enabled = enable; diff --git a/msm/dsi/dsi_display.h b/msm/dsi/dsi_display.h index 5bdca429..ea7b5055 100644 --- a/msm/dsi/dsi_display.h +++ b/msm/dsi/dsi_display.h @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2015-2021, The Linux Foundation. All rights reserved. */ @@ -633,7 +634,10 @@ int dsi_pre_clkon_cb(void *priv, enum dsi_clk_type clk_type, */ int dsi_display_unprepare(struct dsi_display *display); -int dsi_display_set_tpg_state(struct dsi_display *display, bool enable); +int dsi_display_set_tpg_state(struct dsi_display *display, bool enable, + enum dsi_test_pattern type, + u32 init_val, + enum dsi_ctrl_tpg_pattern pattern); int dsi_display_clock_gate(struct dsi_display *display, bool enable); int dsi_dispaly_static_frame(struct dsi_display *display, bool enable); From fcaf279afdba65b71ad1850a90dc08c85ce98290 Mon Sep 17 00:00:00 2001 From: Renchao Liu Date: Wed, 3 Aug 2022 21:22:29 +0800 Subject: [PATCH 6/9] disp: msm: sde: Add scaler offset for de lpf Scaler offset is missed while writing de lpf register, which may cause DE works mainly on the left part of panel. this change adds the offset to fix this issue. Change-Id: I7cdc3afd3523cb9e15a7ae79adae07e2b52b8c2e Signed-off-by: Renchao Liu --- msm/sde/sde_hw_util.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/msm/sde/sde_hw_util.c b/msm/sde/sde_hw_util.c index 0ba7531b..d2b96155 100644 --- a/msm/sde/sde_hw_util.c +++ b/msm/sde/sde_hw_util.c @@ -445,9 +445,10 @@ void sde_hw_setup_scaler3(struct sde_hw_blk_reg_map *c, de_lpf_blend = (scaler3_cfg->de_lpf_l & 0x3FF) | ((scaler3_cfg->de_lpf_m & 0x3FF) << 10) | ((scaler3_cfg->de_lpf_h & 0x3FF) << 20); - SDE_REG_WRITE(c, QSEED3_DE_LPF_BLEND, de_lpf_blend); + SDE_REG_WRITE(c, QSEED3_DE_LPF_BLEND + + scaler_offset, de_lpf_blend); } else { - SDE_REG_WRITE(c, QSEED3_DE_LPF_BLEND, + SDE_REG_WRITE(c, QSEED3_DE_LPF_BLEND + scaler_offset, QSEED5_DEFAULT_DE_LPF_BLEND); } } From 0763e33723d658d1f9178728afab06007f0bae12 Mon Sep 17 00:00:00 2001 From: Sandeep Gangadharaiah Date: Wed, 3 Aug 2022 20:10:07 -0700 Subject: [PATCH 7/9] disp: msm: dp: fix aux state during individual plug out/in When a display is powered off, the DP driver currently clears the aux state and forces it to OFF, expecting a subsequent hpd_low. But in MST scenarios it is possible for individual displays to be unplugged and then plugged back in without disconnecting the hub. In this use case, after the unplug of last display, the aux state is in OFF, and on the subsequent plug-in, the driver appends the ON flag, leaving both flags to be set which is an incorrect state. This change removes this assumption and properly sets the ON/OFF state on enable/disable respectively. Change-Id: I96355938a14c77fe958b86bd5f1dabad67584e4e Signed-off-by: Sandeep Gangadharaiah --- msm/dp/dp_display.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/msm/dp/dp_display.c b/msm/dp/dp_display.c index 365121bc..25205014 100644 --- a/msm/dp/dp_display.c +++ b/msm/dp/dp_display.c @@ -2575,6 +2575,7 @@ static int dp_display_post_enable(struct dp_display *dp_display, void *panel) dp_panel->audio->on(dp_panel->audio); } + dp->aux->state &= ~DP_STATE_CTRL_POWERED_OFF; dp->aux->state |= DP_STATE_CTRL_POWERED_ON; complete_all(&dp->notification_comp); DP_DEBUG("display post enable complete. state: 0x%x\n", dp->state); @@ -2799,7 +2800,9 @@ static int dp_display_unprepare(struct dp_display *dp_display, void *panel) } dp_display_state_remove(DP_STATE_ENABLED); - dp->aux->state = DP_STATE_CTRL_POWERED_OFF; + + dp->aux->state &= ~DP_STATE_CTRL_POWERED_ON; + dp->aux->state |= DP_STATE_CTRL_POWERED_OFF; complete_all(&dp->notification_comp); From 965ac39c84915748932f678e2184a32e754cb6f7 Mon Sep 17 00:00:00 2001 From: Veera Sundaram Sankaran Date: Sun, 7 Aug 2022 23:16:50 -0700 Subject: [PATCH 8/9] disp: msm: sde: enable encoder resources before phys enc disable Enable the clks/irqs & update RSC state during encoder disable. This ensures RSC is in correct state during the non-primary disable commit as it might have entered idle power collapse before the disable. Change-Id: Idf82efb3a7bc895e1a97c6cdeeb62970184c8e5d Signed-off-by: Veera Sundaram Sankaran --- msm/sde/sde_encoder.c | 1 + 1 file changed, 1 insertion(+) diff --git a/msm/sde/sde_encoder.c b/msm/sde/sde_encoder.c index 75166d46..a7f8e79e 100644 --- a/msm/sde/sde_encoder.c +++ b/msm/sde/sde_encoder.c @@ -3272,6 +3272,7 @@ static void sde_encoder_virt_disable(struct drm_encoder *drm_enc) phys->ops.disable(phys); } } else { + sde_encoder_resource_control(drm_enc, SDE_ENC_RC_EVENT_KICKOFF); for (i = 0; i < sde_enc->num_phys_encs; i++) { struct sde_encoder_phys *phys = sde_enc->phys_encs[i]; From 18d42a6eb37f736dc6277ea28977b728e3d9e453 Mon Sep 17 00:00:00 2001 From: Amine Najahi Date: Fri, 5 Aug 2022 09:12:59 -0400 Subject: [PATCH 9/9] disp: msm: sde: use mode from new state during CP check phase Currently previous mode information is passed to CP check phase instead of the new incoming mode, which cause RC to silently pass the check phase when there is a resolution mismatch between the RC mask and new mode. This change also adds various event log to better track RC codeflow. Change-Id: I8953fd76e2cb0eb12e2df23038a7866edd3dcb1e Signed-off-by: Amine Najahi --- msm/sde/sde_color_processing.c | 17 ++++++++++------- msm/sde/sde_hw_rc.c | 14 +++++++++++++- 2 files changed, 23 insertions(+), 8 deletions(-) diff --git a/msm/sde/sde_color_processing.c b/msm/sde/sde_color_processing.c index ec96a78f..1f7059ce 100644 --- a/msm/sde/sde_color_processing.c +++ b/msm/sde/sde_color_processing.c @@ -1617,6 +1617,8 @@ static int _sde_cp_crtc_checkfeature(u32 feature, hw_cfg.num_of_mixers = sde_crtc->num_mixers; hw_cfg.last_feature = 0; + hw_cfg.panel_width = sde_crtc_state->base.adjusted_mode.hdisplay; + hw_cfg.panel_height = sde_crtc_state->base.adjusted_mode.vdisplay; for (i = 0; i < num_mixers; i++) { hw_dspp = sde_crtc->mixers[i].hw_dspp; @@ -1625,6 +1627,7 @@ static int _sde_cp_crtc_checkfeature(u32 feature, hw_cfg.dspp[i] = hw_dspp; } + SDE_EVT32(feature, hw_cfg.panel_width, hw_cfg.panel_height); for (i = 0; i < num_mixers && !ret; i++) { hw_lm = sde_crtc->mixers[i].hw_lm; hw_dspp = sde_crtc->mixers[i].hw_dspp; @@ -1639,8 +1642,6 @@ static int _sde_cp_crtc_checkfeature(u32 feature, hw_cfg.displayh = num_mixers * sde_crtc_state->lm_roi[i].w; hw_cfg.displayv = sde_crtc_state->lm_roi[i].h; - hw_cfg.panel_width = sde_crtc->base.state->adjusted_mode.hdisplay; - hw_cfg.panel_height = sde_crtc->base.state->adjusted_mode.vdisplay; DRM_DEBUG_DRIVER("check cp feature %d on mixer %d\n", feature, hw_lm->idx - LM_0); ret = check_feature(hw_dspp, &hw_cfg, sde_crtc); @@ -1685,7 +1686,7 @@ static void _sde_cp_crtc_commit_feature(struct sde_cp_node *prop_node, hw_cfg.num_ds_enabled = sde_crtc_state->num_ds_enabled; - SDE_EVT32(hw_cfg.panel_width, hw_cfg.panel_height); + SDE_EVT32(prop_node->feature, hw_cfg.panel_width, hw_cfg.panel_height); for (i = 0; i < num_mixers; i++) { hw_dspp = sde_crtc->mixers[i].hw_dspp; @@ -1888,6 +1889,9 @@ static int _sde_cp_crtc_check_pu_features(struct drm_crtc *crtc) hw_cfg.num_of_mixers = sde_crtc->num_mixers; hw_cfg.payload = &sde_crtc_state->user_roi_list; hw_cfg.len = sizeof(sde_crtc_state->user_roi_list); + hw_cfg.panel_height = sde_crtc_state->base.adjusted_mode.vdisplay; + hw_cfg.panel_width = sde_crtc_state->base.adjusted_mode.hdisplay; + for (i = 0; i < hw_cfg.num_of_mixers; i++) hw_cfg.dspp[i] = sde_crtc->mixers[i].hw_dspp; @@ -1899,6 +1903,7 @@ static int _sde_cp_crtc_check_pu_features(struct drm_crtc *crtc) !(sde_crtc->cp_pu_feature_mask & BIT(i))) continue; + SDE_EVT32(i, hw_cfg.panel_width, hw_cfg.panel_height); for (j = 0; j < hw_cfg.num_of_mixers; j++) { hw_dspp = sde_crtc->mixers[j].hw_dspp; @@ -1908,8 +1913,7 @@ static int _sde_cp_crtc_check_pu_features(struct drm_crtc *crtc) hw_cfg.displayh = hw_cfg.num_of_mixers * sde_crtc_state->lm_roi[j].w; hw_cfg.displayv = sde_crtc_state->lm_roi[j].h; - hw_cfg.panel_height = sde_crtc->base.state->adjusted_mode.vdisplay; - hw_cfg.panel_width = sde_crtc->base.state->adjusted_mode.hdisplay; + ret = check_pu_feature(hw_dspp, &hw_cfg, sde_crtc); if (ret) { DRM_ERROR("failed pu feature %d in mixer %d\n", @@ -2062,6 +2066,7 @@ static int _sde_cp_crtc_update_pu_features(struct drm_crtc *crtc, bool *need_flu !(sde_crtc->cp_pu_feature_mask & BIT(i))) continue; + SDE_EVT32(i, hw_cfg.panel_width, hw_cfg.panel_height); for (j = 0; j < hw_cfg.num_of_mixers; j++) { hw_lm = sde_crtc->mixers[j].hw_lm; hw_dspp = sde_crtc->mixers[j].hw_dspp; @@ -2071,8 +2076,6 @@ static int _sde_cp_crtc_update_pu_features(struct drm_crtc *crtc, bool *need_flu hw_cfg.displayh = hw_cfg.num_of_mixers * hw_lm->cfg.out_width; hw_cfg.displayv = hw_lm->cfg.out_height; - hw_cfg.panel_width = sde_crtc->base.state->adjusted_mode.hdisplay; - hw_cfg.panel_height = sde_crtc->base.state->adjusted_mode.vdisplay; ret = set_pu_feature(hw_dspp, &hw_cfg, sde_crtc); /* feature does not need flush when ret > 0 */ diff --git a/msm/sde/sde_hw_rc.c b/msm/sde/sde_hw_rc.c index 97c88be0..470d4a03 100644 --- a/msm/sde/sde_hw_rc.c +++ b/msm/sde/sde_hw_rc.c @@ -749,6 +749,7 @@ int sde_hw_rc_check_mask(struct sde_hw_dspp *hw_dspp, void *cfg) if ((hw_cfg->len == 0 && hw_cfg->payload == NULL)) { SDE_DEBUG("RC feature disabled, skip mask checks\n"); + SDE_EVT32(RC_IDX(hw_dspp)); return 0; } @@ -802,6 +803,7 @@ int sde_hw_rc_check_pu_roi(struct sde_hw_dspp *hw_dspp, void *cfg) SDE_DEBUG("full frame update\n"); memset(&empty_roi_list, 0, sizeof(struct msm_roi_list)); roi_list = &empty_roi_list; + SDE_EVT32(RC_IDX(hw_dspp)); } rc_mask_cfg = RC_STATE(hw_dspp).last_rc_mask_cfg; @@ -810,6 +812,7 @@ int sde_hw_rc_check_pu_roi(struct sde_hw_dspp *hw_dspp, void *cfg) /* early return when there is no mask in memory */ if (!mask_programmed || !rc_mask_cfg) { SDE_DEBUG("no previous rc mask programmed\n"); + SDE_EVT32(RC_IDX(hw_dspp)); return SDE_HW_RC_PU_SKIP_OP; } @@ -869,10 +872,12 @@ int sde_hw_rc_setup_pu_roi(struct sde_hw_dspp *hw_dspp, void *cfg) rc_mask_cfg = RC_STATE(hw_dspp).last_rc_mask_cfg; mask_programmed = RC_STATE(hw_dspp).mask_programmed; + SDE_EVT32(RC_IDX(hw_dspp), roi_list, rc_mask_cfg, mask_programmed); /* early return when there is no mask in memory */ if (!mask_programmed || !rc_mask_cfg) { SDE_DEBUG("no previous rc mask programmed\n"); + SDE_EVT32(RC_IDX(hw_dspp)); return SDE_HW_RC_PU_SKIP_OP; } @@ -936,7 +941,9 @@ int sde_hw_rc_setup_mask(struct sde_hw_dspp *hw_dspp, void *cfg) memset(RC_STATE(hw_dspp).last_roi_list, 0, sizeof(struct msm_roi_list)); RC_STATE(hw_dspp).roi_programmed = false; - + SDE_EVT32(RC_IDX(hw_dspp), RC_STATE(hw_dspp).last_rc_mask_cfg, + RC_STATE(hw_dspp).mask_programmed, + RC_STATE(hw_dspp).roi_programmed); return 0; } @@ -957,6 +964,7 @@ int sde_hw_rc_setup_mask(struct sde_hw_dspp *hw_dspp, void *cfg) SDE_DEBUG("partial frame update\n"); sde_kms_rect_merge_rectangles(last_roi_list, &merged_roi); } + SDE_EVT32(RC_IDX(hw_dspp), roi_programmed); rc = _sde_hw_rc_get_ajusted_roi(hw_cfg, &merged_roi, &rc_roi); if (rc) { @@ -1003,6 +1011,7 @@ int sde_hw_rc_setup_data_dma(struct sde_hw_dspp *hw_dspp, void *cfg) if ((hw_cfg->len == 0 && hw_cfg->payload == NULL)) { SDE_DEBUG("RC feature disabled, skip data programming\n"); + SDE_EVT32(RC_IDX(hw_dspp)); return 0; } @@ -1016,6 +1025,7 @@ int sde_hw_rc_setup_data_dma(struct sde_hw_dspp *hw_dspp, void *cfg) if (rc_mask_cfg->flags & SDE_HW_RC_SKIP_DATA_PROG) { SDE_DEBUG("skip data programming\n"); + SDE_EVT32(RC_IDX(hw_dspp)); return 0; } @@ -1042,6 +1052,7 @@ int sde_hw_rc_setup_data_ahb(struct sde_hw_dspp *hw_dspp, void *cfg) if ((hw_cfg->len == 0 && hw_cfg->payload == NULL)) { SDE_DEBUG("rc feature disabled, skip data programming\n"); + SDE_EVT32(RC_IDX(hw_dspp)); return 0; } @@ -1055,6 +1066,7 @@ int sde_hw_rc_setup_data_ahb(struct sde_hw_dspp *hw_dspp, void *cfg) if (rc_mask_cfg->flags & SDE_HW_RC_SKIP_DATA_PROG) { SDE_DEBUG("skip data programming\n"); + SDE_EVT32(RC_IDX(hw_dspp)); return 0; }