From e121bd2026728de4924e4d048fd7e19a999adfa1 Mon Sep 17 00:00:00 2001 From: Anjaneya Prasad Musunuri Date: Thu, 16 Sep 2021 20:05:03 +0530 Subject: [PATCH 1/2] disp: msm: sde: handle partial update transitions in rounded corner This change handles partial update use case transitions. Rounded corner should be programmed to full ROI when transitioning out of partial update use case. This change also clear cached ROIs when rounded corner feature is disabled to ensure full frame ROI for first frame when feature is enabled again. This change depends on HAL change to disable PU for one frame when RC mask config is set. This change also moves cached rectangles from crtc state to crtc structure to avoid cached rectangles being incorrect due to race conditions between updating cached rectangles in crtc state and duplicating crtc state when next commit starts. Change-Id: I4c48ccd3f64409d1b0fa19f0e6f92eab5f86d099 Signed-off-by: Anjaneya Prasad Musunuri --- msm/sde/sde_color_processing.c | 39 ++++++++++++++++++++-------------- msm/sde/sde_crtc.h | 7 +++--- msm/sde/sde_hw_rc.c | 5 +++++ 3 files changed, 32 insertions(+), 19 deletions(-) diff --git a/msm/sde/sde_color_processing.c b/msm/sde/sde_color_processing.c index 8c40e4950080..799dfdd4495d 100644 --- a/msm/sde/sde_color_processing.c +++ b/msm/sde/sde_color_processing.c @@ -1675,27 +1675,32 @@ static int sde_cp_crtc_set_pu_features(struct drm_crtc *crtc, bool *need_flush) } /* early return if not a partial update frame or no change in rois */ - if (sde_crtc_state->user_roi_list.num_rects == 0) { + if ((sde_crtc_state->user_roi_list.num_rects == 0) && + (sde_crtc->cached_user_roi_list.num_rects == 0)) { DRM_DEBUG_DRIVER("no partial update required\n"); - memset(&sde_crtc_state->cached_user_roi_list, 0, + return 0; + } else if (sde_crtc_state->user_roi_list.num_rects == 0) { + DRM_DEBUG_DRIVER("transition from PU to full update\n"); + memset(&sde_crtc->cached_user_roi_list, 0, sizeof(struct msm_roi_list)); - return 0; - } - - sde_kms_rect_merge_rectangles(&sde_crtc_state->user_roi_list, - &user_rect); - sde_kms_rect_merge_rectangles(&sde_crtc_state->cached_user_roi_list, - &cached_rect); - if (sde_kms_rect_is_equal(&user_rect, &cached_rect)) { - DRM_DEBUG_DRIVER("no change in list of ROIs\n"); - return 0; + } else { + sde_kms_rect_merge_rectangles(&sde_crtc_state->user_roi_list, + &user_rect); + sde_kms_rect_merge_rectangles( + &sde_crtc->cached_user_roi_list, + &cached_rect); + if (sde_kms_rect_is_equal(&user_rect, &cached_rect)) { + DRM_DEBUG_DRIVER("no change in list of ROIs\n"); + return 0; + } } catalog = get_kms(&sde_crtc->base)->catalog; memset(&hw_cfg, 0, sizeof(hw_cfg)); hw_cfg.num_of_mixers = sde_crtc->num_mixers; hw_cfg.broadcast_disabled = catalog->dma_cfg.broadcast_disabled; - hw_cfg.payload = &sde_crtc_state->user_roi_list; + hw_cfg.payload = (sde_crtc_state->user_roi_list.num_rects) ? + &sde_crtc_state->user_roi_list : NULL; hw_cfg.len = sizeof(sde_crtc_state->user_roi_list); for (i = 0; i < hw_cfg.num_of_mixers; i++) hw_cfg.dspp[i] = sde_crtc->mixers[i].hw_dspp; @@ -1730,9 +1735,11 @@ static int sde_cp_crtc_set_pu_features(struct drm_crtc *crtc, bool *need_flush) } } - memcpy(&sde_crtc_state->cached_user_roi_list, - &sde_crtc_state->user_roi_list, - sizeof(struct msm_roi_list)); + if (sde_crtc_state->user_roi_list.num_rects != 0) { + memcpy(&sde_crtc->cached_user_roi_list, + &sde_crtc_state->user_roi_list, + sizeof(struct msm_roi_list)); + } return 0; } diff --git a/msm/sde/sde_crtc.h b/msm/sde/sde_crtc.h index da1aa8b6c6f5..bd16cd3da6fe 100644 --- a/msm/sde/sde_crtc.h +++ b/msm/sde/sde_crtc.h @@ -277,6 +277,7 @@ struct sde_crtc_misr_info { * @plane_mask_old: keeps track of the planes used in the previous commit * @frame_trigger_mode: frame trigger mode * @cp_pu_feature_mask: mask indicating cp feature enable for partial update + * @cached_user_roi_list : Copy of user_roi_list from previous PU frame * @ltm_buffer_cnt : number of ltm buffers * @ltm_buffers : struct stores ltm buffer related data * @ltm_buf_free : list of LTM buffers that are available @@ -361,6 +362,7 @@ struct sde_crtc { enum frame_trigger_mode_type frame_trigger_mode; u32 cp_pu_feature_mask; + struct msm_roi_list cached_user_roi_list; u32 ltm_buffer_cnt; struct sde_ltm_buffer *ltm_buffers[LTM_BUFFER_SIZE]; @@ -395,8 +397,7 @@ struct sde_crtc { * @lm_roi : Current LM ROI, possibly sub-rectangle of mode. * Origin top left of CRTC. * @user_roi_list : List of user's requested ROIs as from set property - * @cached_user_roi_list : Copy of user_roi_list from previous PU frame - * @property_state: Local storage for msm_prop properties + * @property_state: Local storage for msm_prop properties * @property_values: Current crtc property values * @input_fence_timeout_ns : Cached input fence timeout, in ns * @num_dim_layers: Number of dim layers @@ -423,7 +424,7 @@ struct sde_crtc_state { struct sde_rect crtc_roi; struct sde_rect lm_bounds[CRTC_DUAL_MIXERS]; struct sde_rect lm_roi[CRTC_DUAL_MIXERS]; - struct msm_roi_list user_roi_list, cached_user_roi_list; + struct msm_roi_list user_roi_list; struct msm_property_state property_state; struct msm_property_value property_values[CRTC_PROP_COUNT]; diff --git a/msm/sde/sde_hw_rc.c b/msm/sde/sde_hw_rc.c index bcf3f30a4a08..38106898b2f2 100644 --- a/msm/sde/sde_hw_rc.c +++ b/msm/sde/sde_hw_rc.c @@ -775,6 +775,7 @@ int sde_hw_rc_check_pu_roi(struct sde_hw_dspp *hw_dspp, void *cfg) roi_list = hw_cfg->payload; if (!roi_list) { SDE_DEBUG("full frame update\n"); + memset(&empty_roi_list, 0, sizeof(struct msm_roi_list)); roi_list = &empty_roi_list; } @@ -837,6 +838,7 @@ int sde_hw_rc_setup_pu_roi(struct sde_hw_dspp *hw_dspp, void *cfg) roi_list = hw_cfg->payload; if (!roi_list) { SDE_DEBUG("full frame update\n"); + memset(&empty_roi_list, 0, sizeof(struct msm_roi_list)); roi_list = &empty_roi_list; } @@ -906,6 +908,9 @@ int sde_hw_rc_setup_mask(struct sde_hw_dspp *hw_dspp, void *cfg) memset(RC_STATE(hw_dspp).last_rc_mask_cfg, 0, sizeof(struct drm_msm_rc_mask_cfg)); RC_STATE(hw_dspp).mask_programmed = false; + memset(RC_STATE(hw_dspp).last_roi_list, 0, + sizeof(struct msm_roi_list)); + RC_STATE(hw_dspp).roi_programmed = false; return 0; } From 5b6aedd27f558a420b9770c11e5c542335a1da21 Mon Sep 17 00:00:00 2001 From: Narender Ankam Date: Wed, 15 Sep 2021 15:10:07 +0530 Subject: [PATCH 2/2] disp: msm: dp: parse displayport label dt property Add logic in DP driver to parse "label" dt property. This info will be useful to configure DP as primary or secondary. Change-Id: I708179c5940c82256034bc6c8338b01ee52f2f79 Signed-off-by: Narender Ankam --- msm/dp/dp_display.c | 24 +++++++++++++++++++++++- msm/dp/dp_display.h | 5 ++++- msm/dp/dp_drm.c | 15 ++++++++++++++- msm/dp/dp_drm.h | 21 ++++++++++++++++++++- msm/dp/dp_parser.c | 6 +++++- msm/dp/dp_parser.h | 5 ++++- msm/sde/sde_kms.c | 3 ++- 7 files changed, 72 insertions(+), 7 deletions(-) diff --git a/msm/dp/dp_display.c b/msm/dp/dp_display.c index af3bc7365aba..623b3022054a 100644 --- a/msm/dp/dp_display.c +++ b/msm/dp/dp_display.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 @@ -2570,6 +2570,27 @@ static int dp_display_config_hdr(struct dp_display *dp_display, void *panel, core_clk_rate, flush_hdr); } +static int dp_display_get_display_type(struct dp_display *dp_display, + const char **display_type) +{ + struct dp_display_private *dp; + + if (!dp_display || !display_type) { + pr_err("invalid input\n"); + return -EINVAL; + } + + dp = container_of(dp_display, struct dp_display_private, dp_display); + + *display_type = dp->parser->display_type; + + if (!strcmp(*display_type, "primary")) + dp_display->is_primary = true; + + return 0; +} + + static int dp_display_setup_colospace(struct dp_display *dp_display, void *panel, u32 colorspace) @@ -3100,6 +3121,7 @@ static int dp_display_probe(struct platform_device *pdev) g_dp_display->post_open = NULL; g_dp_display->post_init = dp_display_post_init; g_dp_display->config_hdr = dp_display_config_hdr; + g_dp_display->get_display_type = dp_display_get_display_type; g_dp_display->mst_install = dp_display_mst_install; g_dp_display->mst_uninstall = dp_display_mst_uninstall; g_dp_display->mst_connector_install = dp_display_mst_connector_install; diff --git a/msm/dp/dp_display.h b/msm/dp/dp_display.h index ebfeb1d67423..3f4b8d9bc2d3 100644 --- a/msm/dp/dp_display.h +++ b/msm/dp/dp_display.h @@ -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. */ #ifndef _DP_DISPLAY_H_ @@ -72,6 +72,7 @@ struct dp_display { u32 max_pclk_khz; u32 no_mst_encoder; void *dp_mst_prv_info; + bool is_primary; int (*enable)(struct dp_display *dp_display, void *panel); int (*post_enable)(struct dp_display *dp_display, void *panel); @@ -126,6 +127,8 @@ struct dp_display { struct drm_connector *connector, char *pps_cmd); void (*wakeup_phy_layer)(struct dp_display *dp_display, bool wakeup); + int (*get_display_type)(struct dp_display *dp_display, + const char **display_type); }; #ifdef CONFIG_DRM_MSM_DP diff --git a/msm/dp/dp_drm.c b/msm/dp/dp_drm.c index 976e0ebb8faf..30446724cea7 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-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, 2021, The Linux Foundation. All rights reserved. */ #include @@ -580,6 +580,19 @@ int dp_connector_get_modes(struct drm_connector *connector, return rc; } +int dp_connnector_set_info_blob(struct drm_connector *connector, + void *info, void *display, struct msm_mode_info *mode_info) +{ + struct dp_display *dp_display = display; + const char *display_type = NULL; + + dp_display->get_display_type(dp_display, &display_type); + sde_kms_info_add_keystr(info, + "display type", display_type); + + return 0; +} + int dp_drm_bridge_init(void *data, struct drm_encoder *encoder) { int rc = 0; diff --git a/msm/dp/dp_drm.h b/msm/dp/dp_drm.h index 07f606e8a70b..930b3aa911cf 100644 --- a/msm/dp/dp_drm.h +++ b/msm/dp/dp_drm.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2017-2019, 2021, The Linux Foundation. All rights reserved. */ #ifndef _DP_DRM_H_ @@ -177,6 +177,18 @@ int dp_mst_init(struct dp_display *dp_display); * @display: Pointer to private display structure */ void dp_mst_deinit(struct dp_display *dp_display); + +/** + * dp_conn_set_info_blob - callback to perform info blob initialization + * @connector: Pointer to drm connector structure + * @info: Pointer to sde connector info structure + * @display: Pointer to private display handle + * @mode_info: Pointer to mode info structure + * Returns: Zero on success + */ +int dp_connnector_set_info_blob(struct drm_connector *connector, + void *info, void *display, struct msm_mode_info *mode_info); + #else static inline int dp_connector_config_hdr(struct drm_connector *connector, void *display, struct sde_connector_state *c_state) @@ -278,6 +290,13 @@ static inline int dp_mst_deinit(struct dp_display *dp_display) { return 0; } + +int dp_connnector_set_info_blob(struct drm_connector *connector, + void *info, void *display, struct msm_mode_info *mode_info) +{ + return 0; +} + #endif #endif /* _DP_DRM_H_ */ diff --git a/msm/dp/dp_parser.c b/msm/dp/dp_parser.c index 40a2401b1c4c..4c37aa2c33a2 100644 --- a/msm/dp/dp_parser.c +++ b/msm/dp/dp_parser.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 @@ -166,6 +166,10 @@ static int dp_parser_misc(struct dp_parser *parser) if (rc) parser->max_lclk_khz = DP_MAX_LINK_CLK_KHZ; + parser->display_type = of_get_property(of_node, "label", NULL); + if (!parser->display_type) + parser->display_type = "unknown"; + return 0; } diff --git a/msm/dp/dp_parser.h b/msm/dp/dp_parser.h index 0970dff71ed0..5d937ca274d4 100644 --- a/msm/dp/dp_parser.h +++ b/msm/dp/dp_parser.h @@ -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. */ #ifndef _DP_PARSER_H_ @@ -198,6 +198,7 @@ static inline char *dp_phy_aux_config_type_to_string(u32 cfg_type) * @max_dp_dsc_input_width_pixs: Maximum input width for DSC block * @has_widebus: widebus (2PPC) feature eanble status *@mst_fixed_port: mst port_num reserved for fixed topology + * @display_type: display type as defined in device tree. * @parse: function to be called by client to parse device tree. * @get_io: function to be called by client to get io data. * @get_io_buf: function to be called by client to get io buffers. @@ -230,6 +231,8 @@ struct dp_parser { bool lphw_hpd; u32 mst_fixed_port[MAX_DP_MST_STREAMS]; + const char *display_type; + int (*parse)(struct dp_parser *parser); struct dp_io_data *(*get_io)(struct dp_parser *parser, char *name); void (*get_io_buf)(struct dp_parser *parser, char *name); diff --git a/msm/sde/sde_kms.c b/msm/sde/sde_kms.c index f2f5f9714dd4..d5ac13a62314 100644 --- a/msm/sde/sde_kms.c +++ b/msm/sde/sde_kms.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2014-2021, The Linux Foundation. All rights reserved. * Copyright (C) 2013 Red Hat * Author: Rob Clark * @@ -1450,6 +1450,7 @@ static int _sde_kms_setup_displays(struct drm_device *dev, .get_panel_vfp = NULL, }; static const struct sde_connector_ops dp_ops = { + .set_info_blob = dp_connnector_set_info_blob, .post_init = dp_connector_post_init, .detect = dp_connector_detect, .get_modes = dp_connector_get_modes,