From ad40a300a1ac16dd17cd5ecc92e2fccd98bd1bab Mon Sep 17 00:00:00 2001 From: Jayaprakash Date: Tue, 24 Sep 2019 18:33:20 +0530 Subject: [PATCH 1/3] disp: msm: sde: allow qsync support along with VRR Allow Qsync and VRR features to be supported independently by display driver. Restrict the feature availability in same composition cycle. Change-Id: I696eb72a2b4f9451e142ffdc5acccc8987c36b6d Signed-off-by: Kalyan Thota Signed-off-by: Jayaprakash --- msm/dsi/dsi_panel.c | 15 ++++++------ msm/sde/sde_connector.c | 43 +++++++++++++++++++++++++++++----- msm/sde/sde_crtc.h | 19 +++++++++++++++ msm/sde/sde_encoder_phys_vid.c | 2 +- msm/sde/sde_hw_intf.c | 7 ++++-- 5 files changed, 70 insertions(+), 16 deletions(-) diff --git a/msm/dsi/dsi_panel.c b/msm/dsi/dsi_panel.c index e48deb214e..d37561c6a7 100644 --- a/msm/dsi/dsi_panel.c +++ b/msm/dsi/dsi_panel.c @@ -3257,13 +3257,14 @@ struct dsi_panel *dsi_panel_get(struct device *parent, if (rc) DSI_ERR("failed to parse dfps configuration, rc=%d\n", rc); - if (!(panel->dfps_caps.dfps_support)) { - /* qsync and dfps are mutually exclusive features */ - rc = dsi_panel_parse_qsync_caps(panel, of_node); - if (rc) - DSI_DEBUG("failed to parse qsync features, rc=%d\n", - rc); - } + rc = dsi_panel_parse_qsync_caps(panel, of_node); + if (rc) + DSI_DEBUG("failed to parse qsync features, rc=%d\n", rc); + + /* allow qsync support only if DFPS is with VFP approach */ + if ((panel->dfps_caps.dfps_support) && + !(panel->dfps_caps.type == DSI_DFPS_IMMEDIATE_VFP)) + panel->qsync_min_fps = 0; rc = dsi_panel_parse_dyn_clk_caps(panel); if (rc) diff --git a/msm/sde/sde_connector.c b/msm/sde/sde_connector.c index c45dc8ca52..1375a4eb2c 100644 --- a/msm/sde/sde_connector.c +++ b/msm/sde/sde_connector.c @@ -621,17 +621,24 @@ void sde_connector_set_colorspace(struct sde_connector *c_conn) void sde_connector_set_qsync_params(struct drm_connector *connector) { - struct sde_connector *c_conn = to_sde_connector(connector); - u32 qsync_propval; + struct sde_connector *c_conn; + struct sde_connector_state *c_state; + u32 qsync_propval = 0; + bool prop_dirty; if (!connector) return; + c_conn = to_sde_connector(connector); + c_state = to_sde_connector_state(connector->state); c_conn->qsync_updated = false; - qsync_propval = sde_connector_get_property(c_conn->base.state, - CONNECTOR_PROP_QSYNC_MODE); - if (qsync_propval != c_conn->qsync_mode) { + prop_dirty = msm_property_is_dirty(&c_conn->property_info, + &c_state->property_state, + CONNECTOR_PROP_QSYNC_MODE); + if (prop_dirty) { + qsync_propval = sde_connector_get_property(c_conn->base.state, + CONNECTOR_PROP_QSYNC_MODE); SDE_DEBUG("updated qsync mode %d -> %d\n", c_conn->qsync_mode, qsync_propval); c_conn->qsync_updated = true; @@ -1376,6 +1383,10 @@ static int sde_connector_atomic_set_property(struct drm_connector *connector, if (rc) SDE_ERROR_CONN(c_conn, "cannot set hdr info %d\n", rc); break; + case CONNECTOR_PROP_QSYNC_MODE: + msm_property_set_dirty(&c_conn->property_info, + &c_state->property_state, idx); + break; default: break; } @@ -2027,13 +2038,33 @@ static int sde_connector_atomic_check(struct drm_connector *connector, struct drm_connector_state *new_conn_state) { struct sde_connector *c_conn; + struct sde_connector_state *c_state; + bool qsync_dirty = false, has_modeset = false; if (!connector) { SDE_ERROR("invalid connector\n"); - return 0; + return -EINVAL; + } + + if (!new_conn_state) { + SDE_ERROR("invalid connector state\n"); + return -EINVAL; } c_conn = to_sde_connector(connector); + c_state = to_sde_connector_state(new_conn_state); + + has_modeset = sde_crtc_atomic_check_has_modeset(new_conn_state->state, + new_conn_state->crtc); + qsync_dirty = msm_property_is_dirty(&c_conn->property_info, + &c_state->property_state, + CONNECTOR_PROP_QSYNC_MODE); + + SDE_DEBUG("has_modeset %d qsync_dirty %d\n", has_modeset, qsync_dirty); + if (has_modeset && qsync_dirty) { + SDE_ERROR("invalid qsync update during modeset\n"); + return -EINVAL; + } if (c_conn->ops.atomic_check) return c_conn->ops.atomic_check(connector, diff --git a/msm/sde/sde_crtc.h b/msm/sde/sde_crtc.h index 8b8e32ed97..21e70ed9c2 100644 --- a/msm/sde/sde_crtc.h +++ b/msm/sde/sde_crtc.h @@ -714,6 +714,25 @@ static inline int sde_crtc_get_secure_level(struct drm_crtc *crtc, CRTC_PROP_SECURITY_LEVEL); } +/** sde_crtc_atomic_check_has_modeset - checks if the new_crtc_state in the + * drm_atomic_state has a modeset + * @state : pointer to drm_atomic_state + * @crtc : Pointer to drm crtc structure + * Returns true if crtc has modeset + */ +static inline bool sde_crtc_atomic_check_has_modeset( + struct drm_atomic_state *state, struct drm_crtc *crtc) +{ + struct drm_crtc_state *crtc_state; + + if (!state || !crtc) + return false; + + crtc_state = drm_atomic_get_new_crtc_state(state, + crtc); + return (crtc_state && drm_atomic_crtc_needs_modeset(crtc_state)); +} + /** * sde_crtc_get_secure_transition - determines the operations to be * performed before transitioning to secure state diff --git a/msm/sde/sde_encoder_phys_vid.c b/msm/sde/sde_encoder_phys_vid.c index f290c0e1e9..04da2e25f9 100644 --- a/msm/sde/sde_encoder_phys_vid.c +++ b/msm/sde/sde_encoder_phys_vid.c @@ -332,7 +332,7 @@ static void _sde_encoder_phys_vid_setup_avr( return; } - if (qsync_min_fps >= default_fps) { + if (qsync_min_fps > default_fps) { SDE_ERROR_VIDENC(vid_enc, "qsync fps %d must be less than default %d\n", qsync_min_fps, default_fps); diff --git a/msm/sde/sde_hw_intf.c b/msm/sde/sde_hw_intf.c index 2bebbca07e..8d23b4638b 100644 --- a/msm/sde/sde_hw_intf.c +++ b/msm/sde/sde_hw_intf.c @@ -129,7 +129,7 @@ static int sde_hw_intf_avr_setup(struct sde_hw_intf *ctx, u32 min_fps, default_fps, diff_fps; u32 vsync_period_slow; u32 avr_vtotal; - u32 add_porches; + u32 add_porches = 0; if (!ctx || !params || !avr_params) { SDE_ERROR("invalid input parameter(s)\n"); @@ -146,7 +146,10 @@ static int sde_hw_intf_avr_setup(struct sde_hw_intf *ctx, vsync_period = params->vsync_pulse_width + params->v_back_porch + params->height + params->v_front_porch; - add_porches = mult_frac(vsync_period, diff_fps, min_fps); + + if (diff_fps) + add_porches = mult_frac(vsync_period, diff_fps, min_fps); + vsync_period_slow = vsync_period + add_porches; avr_vtotal = vsync_period_slow * hsync_period; From 985ffddc71a8a01c37ddeedb470599c0402908f6 Mon Sep 17 00:00:00 2001 From: Jayaprakash Date: Thu, 26 Sep 2019 11:55:26 +0530 Subject: [PATCH 2/3] disp: msm: sde: add one-shot qsync mode support Add support to enable one-shot mode during qsync update. This feature ensures the frame drops can be reduced due to delayed software flush for the current commit. Also, add changes to disable the qsync feature post commit. Change-Id: Icb158853f52284bcf8fa641e5f62200c5460b660 Signed-off-by: Kalyan Thota Signed-off-by: Jayaprakash --- msm/dsi/dsi_drm.c | 10 +++++++++- msm/dsi/dsi_drm.h | 4 +++- msm/sde/sde_connector.c | 22 ++++++++++++++++++++++ msm/sde/sde_connector.h | 15 ++++++++++++++- msm/sde/sde_hw_intf.c | 6 ++---- msm/sde/sde_kms.c | 11 ++++++++++- msm/sde/sde_rm.h | 3 +++ 7 files changed, 63 insertions(+), 8 deletions(-) diff --git a/msm/dsi/dsi_drm.c b/msm/dsi/dsi_drm.c index 4bcdef3866..9fc723f522 100644 --- a/msm/dsi/dsi_drm.c +++ b/msm/dsi/dsi_drm.c @@ -915,7 +915,8 @@ void dsi_conn_enable_event(struct drm_connector *connector, event_idx, &event_info, enable); } -int dsi_conn_post_kickoff(struct drm_connector *connector) +int dsi_conn_post_kickoff(struct drm_connector *connector, + struct msm_display_kickoff_params *params) { struct drm_encoder *encoder; struct dsi_bridge *c_bridge; @@ -923,6 +924,7 @@ int dsi_conn_post_kickoff(struct drm_connector *connector) struct dsi_display *display; struct dsi_display_ctrl *m_ctrl, *ctrl; int i, rc = 0; + bool enable; if (!connector || !connector->state) { DSI_ERR("invalid connector or connector state\n"); @@ -968,6 +970,12 @@ int dsi_conn_post_kickoff(struct drm_connector *connector) /* ensure dynamic clk switch flag is reset */ c_bridge->dsi_mode.dsi_mode_flags &= ~DSI_MODE_FLAG_DYN_CLK; + if (params->qsync_update) { + enable = (params->qsync_mode > 0) ? true : false; + display_for_each_ctrl(i, display) + dsi_ctrl_setup_avr(display->ctrl[i].ctrl, enable); + } + return 0; } diff --git a/msm/dsi/dsi_drm.h b/msm/dsi/dsi_drm.h index 8e3386d56d..559635e87b 100644 --- a/msm/dsi/dsi_drm.h +++ b/msm/dsi/dsi_drm.h @@ -120,9 +120,11 @@ int dsi_conn_pre_kickoff(struct drm_connector *connector, /** * dsi_display_post_kickoff - program post kickoff-time features * @connector: Pointer to drm connector structure + * @params: Parameters for post kickoff programming * Returns: Zero on success */ -int dsi_conn_post_kickoff(struct drm_connector *connector); +int dsi_conn_post_kickoff(struct drm_connector *connector, + struct msm_display_kickoff_params *params); /** * dsi_convert_to_drm_mode - Update drm mode with dsi mode information diff --git a/msm/sde/sde_connector.c b/msm/sde/sde_connector.c index 1375a4eb2c..5016e42f56 100644 --- a/msm/sde/sde_connector.c +++ b/msm/sde/sde_connector.c @@ -58,6 +58,7 @@ static const struct drm_prop_enum_list e_power_mode[] = { static const struct drm_prop_enum_list e_qsync_mode[] = { {SDE_RM_QSYNC_DISABLED, "none"}, {SDE_RM_QSYNC_CONTINUOUS_MODE, "continuous"}, + {SDE_RM_QSYNC_ONE_SHOT_MODE, "one_shot"}, }; static const struct drm_prop_enum_list e_frame_trigger_mode[] = { {FRAME_DONE_WAIT_DEFAULT, "default"}, @@ -646,6 +647,27 @@ void sde_connector_set_qsync_params(struct drm_connector *connector) } } +void sde_connector_complete_qsync_commit(struct drm_connector *conn, + struct msm_display_kickoff_params *params) +{ + struct sde_connector *c_conn; + + if (!conn || !params) { + SDE_ERROR("invalid params\n"); + return; + } + + c_conn = to_sde_connector(conn); + + if (c_conn && c_conn->qsync_updated && + (c_conn->qsync_mode == SDE_RM_QSYNC_ONE_SHOT_MODE)) { + /* Reset qsync states if mode is one shot */ + params->qsync_mode = c_conn->qsync_mode = 0; + params->qsync_update = true; + SDE_EVT32(conn->base.id, c_conn->qsync_mode); + } +} + static int _sde_connector_update_hdr_metadata(struct sde_connector *c_conn, struct sde_connector_state *c_state) { diff --git a/msm/sde/sde_connector.h b/msm/sde/sde_connector.h index 117cc236eb..23c9e8a558 100644 --- a/msm/sde/sde_connector.h +++ b/msm/sde/sde_connector.h @@ -229,9 +229,12 @@ struct sde_connector_ops { /** * post_kickoff - display to program post kickoff-time features * @connector: Pointer to drm connector structure + * @params: Parameter bundle of connector-stored information for + * post kickoff programming into the display * Returns: Zero on success */ - int (*post_kickoff)(struct drm_connector *connector); + int (*post_kickoff)(struct drm_connector *connector, + struct msm_display_kickoff_params *params); /** * post_open - calls connector to process post open functionalities @@ -732,6 +735,16 @@ int sde_connector_get_dpms(struct drm_connector *connector); */ void sde_connector_set_qsync_params(struct drm_connector *connector); +/** + * sde_connector_complete_qsync_commit - callback signalling completion + * of qsync, if modified for the current commit + * @conn - Pointer to drm connector object + * @params - Parameter bundle of connector-stored information for + * post kickoff programming into the display + */ +void sde_connector_complete_qsync_commit(struct drm_connector *conn, + struct msm_display_kickoff_params *params); + /** * sde_connector_get_dyn_hdr_meta - returns pointer to connector state's dynamic * HDR metadata info diff --git a/msm/sde/sde_hw_intf.c b/msm/sde/sde_hw_intf.c index 8d23b4638b..a7a68189ac 100644 --- a/msm/sde/sde_hw_intf.c +++ b/msm/sde/sde_hw_intf.c @@ -83,9 +83,6 @@ #define INTF_TEAR_AUTOREFRESH_CONFIG 0x2B4 #define INTF_TEAR_TEAR_DETECT_CTRL 0x2B8 -#define AVR_CONTINUOUS_MODE 1 -#define AVR_ONE_SHOT_MODE 2 - static struct sde_intf_cfg *_intf_offset(enum sde_intf intf, struct sde_mdss_cfg *m, void __iomem *addr, @@ -171,7 +168,8 @@ static void sde_hw_intf_avr_ctrl(struct sde_hw_intf *ctx, c = &ctx->hw; if (avr_params->avr_mode) { avr_ctrl = BIT(0); - avr_mode = (avr_params->avr_mode == AVR_ONE_SHOT_MODE) ? + avr_mode = + (avr_params->avr_mode == SDE_RM_QSYNC_ONE_SHOT_MODE) ? (BIT(0) | BIT(8)) : 0x0; } diff --git a/msm/sde/sde_kms.c b/msm/sde/sde_kms.c index 2797a0be4f..8220dda6cf 100644 --- a/msm/sde/sde_kms.c +++ b/msm/sde/sde_kms.c @@ -46,6 +46,7 @@ #include "sde_plane.h" #include "sde_crtc.h" #include "sde_reg_dma.h" +#include "sde_connector.h" #include #include "soc/qcom/secure_buffer.h" @@ -948,6 +949,7 @@ static void sde_kms_complete_commit(struct msm_kms *kms, struct drm_crtc_state *old_crtc_state; struct drm_connector *connector; struct drm_connector_state *old_conn_state; + struct msm_display_kickoff_params params; int i, rc = 0; if (!kms || !old_state) @@ -980,7 +982,14 @@ static void sde_kms_complete_commit(struct msm_kms *kms, c_conn = to_sde_connector(connector); if (!c_conn->ops.post_kickoff) continue; - rc = c_conn->ops.post_kickoff(connector); + + params.rois = NULL; + params.hdr_meta = NULL; + params.qsync_update = false; + + sde_connector_complete_qsync_commit(connector, ¶ms); + + rc = c_conn->ops.post_kickoff(connector, ¶ms); if (rc) { pr_err("Connector Post kickoff failed rc=%d\n", rc); diff --git a/msm/sde/sde_rm.h b/msm/sde/sde_rm.h index 68823b9e0d..ea5a0e6a30 100644 --- a/msm/sde/sde_rm.h +++ b/msm/sde/sde_rm.h @@ -67,10 +67,13 @@ enum sde_rm_topology_control { * disable state. * @SDE_RM_QSYNC_CONTINUOUS_MODE: If set, Qsync is enabled in continuous * mode. + * @SDE_RM_QSYNC_ONE_SHOT_MODE: If set, Qsync is enabled in one shot mode. + * */ enum sde_rm_qsync_modes { SDE_RM_QSYNC_DISABLED, SDE_RM_QSYNC_CONTINUOUS_MODE, + SDE_RM_QSYNC_ONE_SHOT_MODE }; /** From aad3dd4525148340df04852af2b623a5e19c0ae4 Mon Sep 17 00:00:00 2001 From: Jayaprakash Date: Thu, 26 Sep 2019 12:17:07 +0530 Subject: [PATCH 3/3] disp: msm: sde: update avr mode config during commit prepare Add changes to support avr mode config update during prepare commit which happens before gpu fence wait for the input buffers. Change-Id: Ib2cb5b7e1f10501914c003f6cf066b85048f79d4 Signed-off-by: Kalyan Thota Signed-off-by: Jayaprakash --- msm/dsi/dsi_display.c | 33 ++++++++++++++------ msm/dsi/dsi_display.h | 10 ++++++ msm/dsi/dsi_drm.c | 13 +++++++- msm/dsi/dsi_drm.h | 12 +++++++- msm/msm_drv.h | 10 ++++-- msm/sde/sde_connector.c | 56 ++++++++++++++++++++++++++-------- msm/sde/sde_connector.h | 21 +++++++++++-- msm/sde/sde_encoder.c | 22 +++++++++---- msm/sde/sde_encoder_phys_vid.c | 18 +++++++++-- msm/sde/sde_kms.c | 6 ++-- 10 files changed, 160 insertions(+), 41 deletions(-) diff --git a/msm/dsi/dsi_display.c b/msm/dsi/dsi_display.c index 5db993622f..dc72ba6e95 100644 --- a/msm/dsi/dsi_display.c +++ b/msm/dsi/dsi_display.c @@ -7011,21 +7011,11 @@ int dsi_display_pre_kickoff(struct drm_connector *connector, { int rc = 0; int i; - bool enable; /* check and setup MISR */ if (display->misr_enable) _dsi_display_setup_misr(display); - if (params->qsync_update) { - enable = (params->qsync_mode > 0) ? true : false; - rc = dsi_display_qsync(display, enable); - if (rc) - DSI_ERR("%s failed to send qsync commands\n", - __func__); - SDE_EVT32(params->qsync_mode, rc); - } - rc = dsi_display_set_roi(display, params->rois); /* dynamic DSI clock setting */ @@ -7106,6 +7096,29 @@ error_out: return rc; } +int dsi_display_pre_commit(void *display, + struct msm_display_conn_params *params) +{ + bool enable = false; + int rc = 0; + + if (!display || !params) { + pr_err("Invalid params\n"); + return -EINVAL; + } + + if (params->qsync_update) { + enable = (params->qsync_mode > 0) ? true : false; + rc = dsi_display_qsync(display, enable); + if (rc) + pr_err("%s failed to send qsync commands\n", + __func__); + SDE_EVT32(params->qsync_mode, rc); + } + + return rc; +} + int dsi_display_enable(struct dsi_display *display) { int rc = 0; diff --git a/msm/dsi/dsi_display.h b/msm/dsi/dsi_display.h index 6dadddeb18..2e5115f200 100644 --- a/msm/dsi/dsi_display.h +++ b/msm/dsi/dsi_display.h @@ -679,6 +679,16 @@ int dsi_display_set_power(struct drm_connector *connector, int dsi_display_pre_kickoff(struct drm_connector *connector, struct dsi_display *display, struct msm_display_kickoff_params *params); + +/* + * dsi_display_pre_commit - program pre commit features + * @display: Pointer to private display structure + * @params: Parameters for pre commit time programming + * Returns: Zero on success + */ +int dsi_display_pre_commit(void *display, + struct msm_display_conn_params *params); + /** * dsi_display_get_dst_format() - get dst_format from DSI display * @connector: Pointer to drm connector structure diff --git a/msm/dsi/dsi_drm.c b/msm/dsi/dsi_drm.c index 9fc723f522..d1b6cc4bf8 100644 --- a/msm/dsi/dsi_drm.c +++ b/msm/dsi/dsi_drm.c @@ -901,6 +901,17 @@ int dsi_conn_pre_kickoff(struct drm_connector *connector, return dsi_display_pre_kickoff(connector, display, params); } +int dsi_conn_prepare_commit(void *display, + struct msm_display_conn_params *params) +{ + if (!display || !params) { + pr_err("Invalid params\n"); + return -EINVAL; + } + + return dsi_display_pre_commit(display, params); +} + void dsi_conn_enable_event(struct drm_connector *connector, uint32_t event_idx, bool enable, void *display) { @@ -916,7 +927,7 @@ void dsi_conn_enable_event(struct drm_connector *connector, } int dsi_conn_post_kickoff(struct drm_connector *connector, - struct msm_display_kickoff_params *params) + struct msm_display_conn_params *params) { struct drm_encoder *encoder; struct dsi_bridge *c_bridge; diff --git a/msm/dsi/dsi_drm.h b/msm/dsi/dsi_drm.h index 559635e87b..4a6b7c8fa9 100644 --- a/msm/dsi/dsi_drm.h +++ b/msm/dsi/dsi_drm.h @@ -124,7 +124,7 @@ int dsi_conn_pre_kickoff(struct drm_connector *connector, * Returns: Zero on success */ int dsi_conn_post_kickoff(struct drm_connector *connector, - struct msm_display_kickoff_params *params); + struct msm_display_conn_params *params); /** * dsi_convert_to_drm_mode - Update drm mode with dsi mode information @@ -136,4 +136,14 @@ void dsi_convert_to_drm_mode(const struct dsi_display_mode *dsi_mode, u64 dsi_drm_find_bit_clk_rate(void *display, const struct drm_display_mode *drm_mode); + +/** + * dsi_conn_prepare_commit - program pre commit time features + * @display: Pointer to private display structure + * @params: Parameters for pre commit programming + * Returns: Zero on success + */ +int dsi_conn_prepare_commit(void *display, + struct msm_display_conn_params *params); + #endif /* _DSI_DRM_H_ */ diff --git a/msm/msm_drv.h b/msm/msm_drv.h index 419b7c6b94..a9defc9e51 100644 --- a/msm/msm_drv.h +++ b/msm/msm_drv.h @@ -553,12 +553,18 @@ struct msm_roi_list { /** * struct - msm_display_kickoff_params - info for display features at kickoff * @rois: Regions of interest structure for mapping CRTC to Connector output - * @qsync_mode: Qsync mode, where 0: disabled 1: continuous mode - * @qsync_update: Qsync settings were changed/updated */ struct msm_display_kickoff_params { struct msm_roi_list *rois; struct drm_msm_ext_hdr_metadata *hdr_meta; +}; + +/** + * struct - msm_display_conn_params - info of dpu display features + * @qsync_mode: Qsync mode, where 0: disabled 1: continuous mode 2: oneshot + * @qsync_update: Qsync settings were changed/updated + */ +struct msm_display_conn_params { uint32_t qsync_mode; bool qsync_update; }; diff --git a/msm/sde/sde_connector.c b/msm/sde/sde_connector.c index 5016e42f56..7da379b92c 100644 --- a/msm/sde/sde_connector.c +++ b/msm/sde/sde_connector.c @@ -640,15 +640,17 @@ void sde_connector_set_qsync_params(struct drm_connector *connector) if (prop_dirty) { qsync_propval = sde_connector_get_property(c_conn->base.state, CONNECTOR_PROP_QSYNC_MODE); - SDE_DEBUG("updated qsync mode %d -> %d\n", c_conn->qsync_mode, - qsync_propval); - c_conn->qsync_updated = true; - c_conn->qsync_mode = qsync_propval; + if (qsync_propval != c_conn->qsync_mode) { + SDE_DEBUG("updated qsync mode %d -> %d\n", + c_conn->qsync_mode, qsync_propval); + c_conn->qsync_updated = true; + c_conn->qsync_mode = qsync_propval; + } } } void sde_connector_complete_qsync_commit(struct drm_connector *conn, - struct msm_display_kickoff_params *params) + struct msm_display_conn_params *params) { struct sde_connector *c_conn; @@ -782,13 +784,6 @@ int sde_connector_pre_kickoff(struct drm_connector *connector) params.rois = &c_state->rois; params.hdr_meta = &c_state->hdr_meta; - params.qsync_update = false; - - if (c_conn->qsync_updated) { - params.qsync_mode = c_conn->qsync_mode; - params.qsync_update = true; - SDE_EVT32(connector->base.id, params.qsync_mode); - } SDE_EVT32_VERBOSE(connector->base.id); @@ -798,6 +793,43 @@ end: return rc; } +int sde_connector_prepare_commit(struct drm_connector *connector) +{ + struct sde_connector *c_conn; + struct sde_connector_state *c_state; + struct msm_display_conn_params params; + int rc; + + if (!connector) { + SDE_ERROR("invalid argument\n"); + return -EINVAL; + } + + c_conn = to_sde_connector(connector); + c_state = to_sde_connector_state(connector->state); + if (!c_conn->display) { + SDE_ERROR("invalid connector display\n"); + return -EINVAL; + } + + if (!c_conn->ops.prepare_commit) + return 0; + + memset(¶ms, 0, sizeof(params)); + + if (c_conn->qsync_updated) { + params.qsync_mode = c_conn->qsync_mode; + params.qsync_update = true; + } + + rc = c_conn->ops.prepare_commit(c_conn->display, ¶ms); + + SDE_EVT32(connector->base.id, params.qsync_mode, + params.qsync_update, rc); + + return rc; +} + void sde_connector_helper_bridge_disable(struct drm_connector *connector) { int rc; diff --git a/msm/sde/sde_connector.h b/msm/sde/sde_connector.h index 23c9e8a558..9389f13510 100644 --- a/msm/sde/sde_connector.h +++ b/msm/sde/sde_connector.h @@ -234,7 +234,7 @@ struct sde_connector_ops { * Returns: Zero on success */ int (*post_kickoff)(struct drm_connector *connector, - struct msm_display_kickoff_params *params); + struct msm_display_conn_params *params); /** * post_open - calls connector to process post open functionalities @@ -328,6 +328,16 @@ struct sde_connector_ops { * Returns: zero for success, negetive for failure */ int (*get_default_lms)(void *display, u32 *num_lm); + + /** + * prepare_commit - trigger display to program pre-commit time features + * @display: Pointer to private display structure + * @params: Parameter bundle of connector-stored information for + * pre commit time programming into the display + * Returns: Zero on success + */ + int (*prepare_commit)(void *display, + struct msm_display_conn_params *params); }; /** @@ -743,7 +753,7 @@ void sde_connector_set_qsync_params(struct drm_connector *connector); * post kickoff programming into the display */ void sde_connector_complete_qsync_commit(struct drm_connector *conn, - struct msm_display_kickoff_params *params); + struct msm_display_conn_params *params); /** * sde_connector_get_dyn_hdr_meta - returns pointer to connector state's dynamic @@ -814,6 +824,13 @@ int sde_connector_register_custom_event(struct sde_kms *kms, */ int sde_connector_pre_kickoff(struct drm_connector *connector); +/** + * sde_connector_prepare_commit - trigger commit time feature programming + * @connector: Pointer to drm connector object + * Returns: Zero on success + */ +int sde_connector_prepare_commit(struct drm_connector *connector); + /** * sde_connector_needs_offset - adjust the output fence offset based on * display type diff --git a/msm/sde/sde_encoder.c b/msm/sde/sde_encoder.c index a1c9182ff8..a3e18f0e83 100644 --- a/msm/sde/sde_encoder.c +++ b/msm/sde/sde_encoder.c @@ -4703,11 +4703,6 @@ int sde_encoder_prepare_for_kickoff(struct drm_encoder *drm_enc, SDE_DEBUG_ENC(sde_enc, "\n"); SDE_EVT32(DRMID(drm_enc)); - /* update the qsync parameters for the current frame */ - if (sde_enc->cur_master) - sde_connector_set_qsync_params( - sde_enc->cur_master->connector); - is_cmd_mode = sde_encoder_check_curr_mode(drm_enc, MSM_DISPLAY_CMD_MODE); if (sde_enc->cur_master && sde_enc->cur_master->connector @@ -4960,7 +4955,7 @@ void sde_encoder_prepare_commit(struct drm_encoder *drm_enc) { struct sde_encoder_virt *sde_enc; struct sde_encoder_phys *phys; - int i; + int i, rc = 0; struct sde_hw_ctl *ctl; if (!drm_enc) { @@ -4969,6 +4964,11 @@ void sde_encoder_prepare_commit(struct drm_encoder *drm_enc) } sde_enc = to_sde_encoder_virt(drm_enc); + /* update the qsync parameters for the current frame */ + if (sde_enc->cur_master) + sde_connector_set_qsync_params( + sde_enc->cur_master->connector); + for (i = 0; i < sde_enc->num_phys_encs; i++) { phys = sde_enc->phys_encs[i]; if (phys && phys->ops.prepare_commit) @@ -4986,6 +4986,16 @@ void sde_encoder_prepare_commit(struct drm_encoder *drm_enc) ctl->ops.clear_pending_flush(ctl); } } + + if (sde_enc->cur_master && sde_enc->cur_master->connector) { + rc = sde_connector_prepare_commit( + sde_enc->cur_master->connector); + if (rc) + SDE_ERROR_ENC(sde_enc, + "prepare commit failed conn %d rc %d\n", + sde_enc->cur_master->connector->base.id, + rc); + } } void sde_encoder_helper_setup_misr(struct sde_encoder_phys *phys_enc, diff --git a/msm/sde/sde_encoder_phys_vid.c b/msm/sde/sde_encoder_phys_vid.c index 04da2e25f9..b2d043a98e 100644 --- a/msm/sde/sde_encoder_phys_vid.c +++ b/msm/sde/sde_encoder_phys_vid.c @@ -977,9 +977,6 @@ static int sde_encoder_phys_vid_prepare_for_kickoff( vid_enc->error_count = 0; } - if (sde_connector_is_qsync_updated(phys_enc->connector)) - _sde_encoder_phys_vid_avr_ctrl(phys_enc); - return rc; } @@ -1124,6 +1121,20 @@ static void sde_encoder_phys_vid_handle_post_kickoff( } } +static void sde_encoder_phys_vid_prepare_for_commit( + struct sde_encoder_phys *phys_enc) +{ + + if (!phys_enc) { + SDE_ERROR("invalid encoder parameters\n"); + return; + } + + if (sde_connector_is_qsync_updated(phys_enc->connector)) + _sde_encoder_phys_vid_avr_ctrl(phys_enc); + +} + static void sde_encoder_phys_vid_irq_control(struct sde_encoder_phys *phys_enc, bool enable) { @@ -1258,6 +1269,7 @@ static void sde_encoder_phys_vid_init_ops(struct sde_encoder_phys_ops *ops) ops->get_wr_line_count = sde_encoder_phys_vid_get_line_count; ops->wait_dma_trigger = sde_encoder_phys_vid_wait_dma_trigger; ops->wait_for_active = sde_encoder_phys_vid_wait_for_active; + ops->prepare_commit = sde_encoder_phys_vid_prepare_for_commit; } struct sde_encoder_phys *sde_encoder_phys_vid_init( diff --git a/msm/sde/sde_kms.c b/msm/sde/sde_kms.c index 8220dda6cf..4b5a12b6c3 100644 --- a/msm/sde/sde_kms.c +++ b/msm/sde/sde_kms.c @@ -949,7 +949,7 @@ static void sde_kms_complete_commit(struct msm_kms *kms, struct drm_crtc_state *old_crtc_state; struct drm_connector *connector; struct drm_connector_state *old_conn_state; - struct msm_display_kickoff_params params; + struct msm_display_conn_params params; int i, rc = 0; if (!kms || !old_state) @@ -983,9 +983,7 @@ static void sde_kms_complete_commit(struct msm_kms *kms, if (!c_conn->ops.post_kickoff) continue; - params.rois = NULL; - params.hdr_meta = NULL; - params.qsync_update = false; + memset(¶ms, 0, sizeof(params)); sde_connector_complete_qsync_commit(connector, ¶ms);