From 2e3ba9430cff4f815dd685d5e691f64ced958a3d Mon Sep 17 00:00:00 2001 From: Veera Sundaram Sankaran Date: Fri, 20 Jan 2023 15:20:10 -0800 Subject: [PATCH] disp: msm: expose qsync avr step as part of conn mode caps Add capability to read avr step for each timing mode. This will be in addition to the existing avr-step-list which is defined when dfps is enabled. Expose the avr-step as part of each mode in connector caps to user-mode. Additionally, change the avr_step connector property to enum to give usermode just the capability to enable/disable avr-step and not alter the step value as its fixed from the device tree. Change-Id: I6d7f8e9fcf03f98abef7640fc741e5e1be8597a1 Signed-off-by: Veera Sundaram Sankaran --- msm/dsi/dsi_defs.h | 6 +++- msm/dsi/dsi_display.c | 43 +++++++++---------------- msm/dsi/dsi_display.h | 9 ------ msm/dsi/dsi_drm.c | 42 +++++++++++------------- msm/dsi/dsi_drm.h | 9 ++++++ msm/dsi/dsi_panel.c | 18 +++++++++-- msm/dsi/dsi_panel.h | 3 +- msm/msm_drv.h | 10 +++--- msm/sde/sde_connector.c | 58 +++++++++++++++++++--------------- msm/sde/sde_connector.h | 28 ++++++++-------- msm/sde/sde_encoder.c | 47 +++++++++++---------------- msm/sde/sde_encoder_phys_vid.c | 21 +++++++++--- msm/sde/sde_kms.c | 2 +- 13 files changed, 155 insertions(+), 141 deletions(-) diff --git a/msm/dsi/dsi_defs.h b/msm/dsi/dsi_defs.h index 2c7a18f350..94a0de042f 100644 --- a/msm/dsi/dsi_defs.h +++ b/msm/dsi/dsi_defs.h @@ -418,7 +418,8 @@ struct dsi_panel_cmd_set { * @vdc: VDC compression configuration. * @pclk_scale: pclk scale factor, target bpp to source bpp * @roi_caps: Panel ROI capabilities. - * @qsync_min_fps: Qsync min fps rate + * @qsync_min_fps: Qsync min fps rate + * @avr_step_fps: AVR step fps rate */ struct dsi_mode_info { u32 h_active; @@ -446,6 +447,7 @@ struct dsi_mode_info { struct msm_ratio pclk_scale; struct msm_roi_caps roi_caps; u32 qsync_min_fps; + u32 avr_step_fps; }; /** @@ -625,6 +627,7 @@ struct dsi_host_config { * for command mode panels in microseconds. * @dsi_transfer_time_us: Specifies the dsi transfer time for cmd panels. * @qsync_min_fps: Qsync min fps value for the mode + * @avr_step_fps: AVR step fps value for the mode * @clk_rate_hz: DSI bit clock per lane in hz. * @min_dsi_clk_hz: Min dsi clk per lane to transfer frame in vsync time. * @bit_clk_list: List of dynamic bit clock rates supported. @@ -654,6 +657,7 @@ struct dsi_display_mode_priv_info { u32 mdp_transfer_time_us_max; u32 dsi_transfer_time_us; u32 qsync_min_fps; + u32 avr_step_fps; u64 clk_rate_hz; u64 min_dsi_clk_hz; struct msm_dyn_clk_list bit_clk_list; diff --git a/msm/dsi/dsi_display.c b/msm/dsi/dsi_display.c index eb3b337dc1..9f2ba40ad6 100644 --- a/msm/dsi/dsi_display.c +++ b/msm/dsi/dsi_display.c @@ -6754,7 +6754,7 @@ int dsi_display_get_info(struct drm_connector *connector, info->max_height = 1080; info->qsync_min_fps = display->panel->qsync_caps.qsync_min_fps; info->has_qsync_min_fps_list = (display->panel->qsync_caps.qsync_min_fps_list_len > 0); - info->has_avr_step_req = (display->panel->avr_caps.avr_step_fps_list_len > 0); + info->avr_step_fps = display->panel->avr_caps.avr_step_fps; info->poms_align_vsync = display->panel->poms_align_vsync; switch (display->panel->panel_mode) { @@ -7040,7 +7040,7 @@ void dsi_display_put_mode(struct dsi_display *display, int dsi_display_get_modes_helper(struct dsi_display *display, struct dsi_display_ctrl *ctrl, u32 timing_mode_count, struct dsi_dfps_capabilities dfps_caps, struct dsi_qsync_capabilities *qsync_caps, - struct dsi_dyn_clk_caps *dyn_clk_caps) + struct dsi_dyn_clk_caps *dyn_clk_caps, struct dsi_avr_capabilities *avr_caps) { int dsc_modes = 0, nondsc_modes = 0, rc = 0, i, start, end; u32 num_dfps_rates, mode_idx, sublinks_count, array_idx = 0; @@ -7143,6 +7143,10 @@ int dsi_display_get_modes_helper(struct dsi_display *display, if (!sub_mode->timing.qsync_min_fps && qsync_caps->qsync_min_fps) sub_mode->timing.qsync_min_fps = qsync_caps->qsync_min_fps; + /* populate avr step fps, same way as qsync min fps */ + if (!sub_mode->timing.avr_step_fps && avr_caps->avr_step_fps) + sub_mode->timing.avr_step_fps = avr_caps->avr_step_fps; + /* * Qsync min fps for the mode will be populated in the timing info * in dsi_panel_get_mode function. @@ -7175,6 +7179,12 @@ int dsi_display_get_modes_helper(struct dsi_display *display, sub_mode->priv_info->qsync_min_fps = sub_mode->timing.qsync_min_fps; } + /* Override with avr step fps list in dfps usecases */ + if (avr_caps->avr_step_fps_list_len) { + sub_mode->timing.avr_step_fps = avr_caps->avr_step_fps_list[i]; + sub_mode->priv_info->avr_step_fps = sub_mode->timing.avr_step_fps; + } + dsi_display_get_dfps_timing(display, sub_mode, curr_refresh_rate); sub_mode->panel_mode_caps = DSI_OP_VIDEO_MODE; @@ -7215,6 +7225,7 @@ int dsi_display_get_modes(struct dsi_display *display, struct dsi_dyn_clk_caps *dyn_clk_caps; int rc = -EINVAL; struct dsi_qsync_capabilities *qsync_caps; + struct dsi_avr_capabilities *avr_caps; if (!display || !out_modes) { DSI_ERR("Invalid params\n"); @@ -7247,6 +7258,7 @@ int dsi_display_get_modes(struct dsi_display *display, qsync_caps = &(display->panel->qsync_caps); dyn_clk_caps = &(display->panel->dyn_clk_caps); + avr_caps = &(display->panel->avr_caps); timing_mode_count = display->panel->num_timing_nodes; @@ -7256,7 +7268,7 @@ int dsi_display_get_modes(struct dsi_display *display, display->cmdline_timing = NO_OVERRIDE; rc = dsi_display_get_modes_helper(display, ctrl, timing_mode_count, - dfps_caps, qsync_caps, dyn_clk_caps); + dfps_caps, qsync_caps, dyn_clk_caps, avr_caps); if (rc) goto error; @@ -7353,31 +7365,6 @@ int dsi_display_get_default_lms(void *dsi_display, u32 *num_lm) return rc; } -int dsi_display_get_avr_step_req_fps(void *display_dsi, u32 mode_fps) -{ - struct dsi_display *display = (struct dsi_display *)display_dsi; - struct dsi_panel *panel; - u32 i, step = 0; - - if (!display || !display->panel) - return -EINVAL; - - panel = display->panel; - - /* support a single fixed rate, or rate corresponding to dfps list entry */ - if (panel->avr_caps.avr_step_fps_list_len == 1) { - step = panel->avr_caps.avr_step_fps_list[0]; - } else if (panel->avr_caps.avr_step_fps_list_len > 1) { - for (i = 0; i < panel->dfps_caps.dfps_list_len; i++) { - if (panel->dfps_caps.dfps_list[i] == mode_fps) - step = panel->avr_caps.avr_step_fps_list[i]; - } - } - - DSI_DEBUG("mode_fps %u, avr_step fps %u\n", mode_fps, step); - return step; -} - int dsi_display_update_transfer_time(void *display, u32 transfer_time) { struct dsi_display *disp = (struct dsi_display *)display; diff --git a/msm/dsi/dsi_display.h b/msm/dsi/dsi_display.h index d3635a357a..caeb225533 100644 --- a/msm/dsi/dsi_display.h +++ b/msm/dsi/dsi_display.h @@ -421,15 +421,6 @@ void dsi_display_put_mode(struct dsi_display *display, */ int dsi_display_get_default_lms(void *dsi_display, u32 *num_lm); -/** - * dsi_display_get_avr_step_req_fps() - get avr step rate for given fps - * @display: Handle to display. - * @mode_fps: Fps value of current mode - * - * Return: AVR step rate or -ve error code. - */ -int dsi_display_get_avr_step_req_fps(void *dsi_display, u32 mode_fps); - /* * dsi_conn_get_lm_from_mode() - retrieves LM count from dsi mode priv info * @display: Handle to display. diff --git a/msm/dsi/dsi_drm.c b/msm/dsi/dsi_drm.c index 4314d12928..7303d72b7f 100644 --- a/msm/dsi/dsi_drm.c +++ b/msm/dsi/dsi_drm.c @@ -641,6 +641,7 @@ int dsi_conn_get_mode_info(struct drm_connector *connector, mode_info->mdp_transfer_time_us_max = dsi_mode->priv_info->mdp_transfer_time_us_max; mode_info->disable_rsc_solver = dsi_mode->priv_info->disable_rsc_solver; mode_info->qsync_min_fps = dsi_mode->timing.qsync_min_fps; + mode_info->avr_step_fps = dsi_mode->timing.avr_step_fps; mode_info->wd_jitter = dsi_mode->priv_info->wd_jitter; mode_info->vpadding = dsi_display->panel->host_config.vpadding; @@ -711,28 +712,6 @@ static const struct drm_bridge_funcs dsi_bridge_ops = { .mode_set = dsi_bridge_mode_set, }; -int dsi_conn_set_avr_step_info(struct dsi_panel *panel, void *info) -{ - u32 i; - int idx = 0; - size_t buff_sz = PAGE_SIZE; - char *buff; - - buff = kzalloc(buff_sz, GFP_KERNEL); - if (!buff) - return -ENOMEM; - - for (i = 0; i < panel->avr_caps.avr_step_fps_list_len && (idx < (buff_sz - 1)); i++) - idx += scnprintf(&buff[idx], buff_sz - idx, "%u@%u ", - panel->avr_caps.avr_step_fps_list[i], - panel->dfps_caps.dfps_list[i]); - - sde_kms_info_add_keystr(info, "avr step requirement", buff); - kfree(buff); - - return 0; -} - int dsi_conn_get_qsync_min_fps(struct drm_connector_state *conn_state) { struct sde_connector_state *sde_conn_state = to_sde_connector_state(conn_state); @@ -750,6 +729,23 @@ int dsi_conn_get_qsync_min_fps(struct drm_connector_state *conn_state) return priv_info->qsync_min_fps; } +int dsi_conn_get_avr_step_fps(struct drm_connector_state *conn_state) +{ + struct sde_connector_state *sde_conn_state = to_sde_connector_state(conn_state); + struct msm_display_mode *msm_mode; + struct dsi_display_mode_priv_info *priv_info; + + if (!sde_conn_state) + return -EINVAL; + + msm_mode = &sde_conn_state->msm_mode; + if (!msm_mode || !msm_mode->private) + return -EINVAL; + + priv_info = (struct dsi_display_mode_priv_info *)(msm_mode->private); + return priv_info->avr_step_fps; +} + int dsi_conn_set_info_blob(struct drm_connector *connector, void *info, void *display, struct msm_mode_info *mode_info) { @@ -798,8 +794,6 @@ int dsi_conn_set_info_blob(struct drm_connector *connector, switch (panel->panel_mode) { case DSI_OP_VIDEO_MODE: sde_kms_info_add_keystr(info, "panel mode", "video"); - if (panel->avr_caps.avr_step_fps_list_len) - dsi_conn_set_avr_step_info(panel, info); break; case DSI_OP_CMD_MODE: sde_kms_info_add_keystr(info, "panel mode", "command"); diff --git a/msm/dsi/dsi_drm.h b/msm/dsi/dsi_drm.h index 98ee1941d5..ac73d9be40 100644 --- a/msm/dsi/dsi_drm.h +++ b/msm/dsi/dsi_drm.h @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* + * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ @@ -179,4 +180,12 @@ void dsi_conn_set_submode_blob_info(struct drm_connector *conn, * Return: Qsync min fps rate or -ve error code. */ int dsi_conn_get_qsync_min_fps(struct drm_connector_state *conn_state); + +/** + * dsi_conn_get_avr_step_fps() - get avr step fps for given mode + * @conn_state: Pointer to drm_connector_state structure + * + * Return: AVR step fps rate or -ve error code. + */ +int dsi_conn_get_avr_step_fps(struct drm_connector_state *conn_state); #endif /* _DSI_DRM_H_ */ diff --git a/msm/dsi/dsi_panel.c b/msm/dsi/dsi_panel.c index 643c9a0129..b51319dfde 100644 --- a/msm/dsi/dsi_panel.c +++ b/msm/dsi/dsi_panel.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ @@ -925,6 +925,12 @@ static int dsi_panel_parse_timing(struct dsi_mode_info *mode, rc = 0; } + rc = utils->read_u32(utils->data, "qcom,dsi-qsync-mode-avr-step-fps", &mode->avr_step_fps); + if (rc) { + DSI_DEBUG("avr step fps not defined in timing node\n"); + rc = 0; + } + DSI_DEBUG("panel vert active:%d front_portch:%d back_porch:%d pulse_width:%d\n", mode->v_active, mode->v_front_porch, mode->v_back_porch, mode->v_sync_width); @@ -1292,14 +1298,22 @@ static int dsi_panel_parse_avr_caps(struct dsi_panel *panel, struct dsi_parser_utils *utils = &panel->utils; int val, rc = 0; + rc = of_property_read_u32(of_node, "qcom,dsi-qsync-avr-step-fps", &val); + if (rc) + DSI_DEBUG("[%s] avr step fps not defined rc:%d\n", panel->name, rc); + avr_caps->avr_step_fps = rc ? 0 : val; + val = utils->count_u32_elems(utils->data, "qcom,dsi-qsync-avr-step-list"); if (val <= 0) { DSI_DEBUG("[%s] optional avr step list not defined, val:%d\n", panel->name, val); - return rc; + return 0; } else if (val > 1 && val != panel->dfps_caps.dfps_list_len) { DSI_ERR("[%s] avr step list size %d not same as dfps list %d\n", panel->name, val, panel->dfps_caps.dfps_list_len); return -EINVAL; + } else if ((val > 0) && (avr_caps->avr_step_fps)) { + DSI_ERR("[%s] both modes of avr-steps are defined\n", panel->name); + return -EINVAL; } avr_caps->avr_step_fps_list = kcalloc(val, sizeof(u32), GFP_KERNEL); diff --git a/msm/dsi/dsi_panel.h b/msm/dsi/dsi_panel.h index 92645302b5..f679d5568e 100644 --- a/msm/dsi/dsi_panel.h +++ b/msm/dsi/dsi_panel.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved. * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved. */ @@ -99,6 +99,7 @@ struct dsi_qsync_capabilities { }; struct dsi_avr_capabilities { + u32 avr_step_fps; u32 *avr_step_fps_list; u32 avr_step_fps_list_len; }; diff --git a/msm/msm_drv.h b/msm/msm_drv.h index d4d0627c63..aaa011c331 100644 --- a/msm/msm_drv.h +++ b/msm/msm_drv.h @@ -246,7 +246,7 @@ enum msm_mdp_conn_property { CONNECTOR_PROP_QSYNC_MODE, CONNECTOR_PROP_CMD_FRAME_TRIGGER_MODE, CONNECTOR_PROP_SET_PANEL_MODE, - CONNECTOR_PROP_AVR_STEP, + CONNECTOR_PROP_AVR_STEP_STATE, CONNECTOR_PROP_EPT, CONNECTOR_PROP_CACHE_STATE, CONNECTOR_PROP_DSC_MODE, @@ -814,6 +814,7 @@ struct msm_display_wd_jitter_config { * @disable_rsc_solver: Dynamically disable RSC solver for the timing mode due to lower bitclk rate. * @dyn_clk_list: List of dynamic clock rates for RFI. * @qsync_min_fps: qsync min fps rate + * @avr_step_fps: AVR step fps rate * @wd_jitter: Info for WD jitter. * @vpadding: panel stacking height */ @@ -837,6 +838,7 @@ struct msm_mode_info { bool disable_rsc_solver; struct msm_dyn_clk_list dyn_clk_list; u32 qsync_min_fps; + u32 avr_step_fps; struct msm_display_wd_jitter_config wd_jitter; u32 vpadding; }; @@ -883,9 +885,9 @@ struct msm_resource_caps_info { * used instead of panel TE in cmd mode panels * @poms_align_vsync: poms with vsync aligned * @roi_caps: Region of interest capability info - * @qsync_min_fps Minimum fps supported by Qsync feature + * @qsync_min_fps Minimum fps supported by Qsync feature * @has_qsync_min_fps_list True if dsi-supported-qsync-min-fps-list exits - * @has_avr_step_req Panel has defined requirement for AVR steps + * @avr_step_fps AVR step fps supported * @te_source vsync source pin information * @dsc_count: max dsc hw blocks used by display (only available * for dsi display) @@ -915,7 +917,7 @@ struct msm_display_info { uint32_t qsync_min_fps; bool has_qsync_min_fps_list; - bool has_avr_step_req; + uint32_t avr_step_fps; uint32_t te_source; diff --git a/msm/sde/sde_connector.c b/msm/sde/sde_connector.c index 61438bd68a..754ffd316e 100644 --- a/msm/sde/sde_connector.c +++ b/msm/sde/sde_connector.c @@ -854,7 +854,7 @@ void sde_connector_set_qsync_params(struct drm_connector *connector) { struct sde_connector *c_conn; struct sde_connector_state *c_state; - u32 qsync_propval = 0, step_val = 0; + u32 qsync_propval = 0; bool prop_dirty; if (!connector) @@ -879,15 +879,9 @@ void sde_connector_set_qsync_params(struct drm_connector *connector) } prop_dirty = msm_property_is_dirty(&c_conn->property_info, &c_state->property_state, - CONNECTOR_PROP_AVR_STEP); - if (prop_dirty) { - step_val = sde_connector_get_property(c_conn->base.state, CONNECTOR_PROP_AVR_STEP); - if (step_val != c_conn->avr_step) { - SDE_DEBUG("updated avr step %d -> %d\n", c_conn->avr_step, step_val); - c_conn->qsync_updated = true; - c_conn->avr_step = step_val; - } - } + CONNECTOR_PROP_AVR_STEP_STATE); + if (prop_dirty) + c_conn->qsync_updated = true; } void sde_connector_complete_qsync_commit(struct drm_connector *conn, @@ -2932,6 +2926,7 @@ static int sde_connector_populate_mode_info(struct drm_connector *conn, } sde_kms_info_add_keyint(info, "qsync_min_fps", mode_info.qsync_min_fps); + sde_kms_info_add_keyint(info, "avr_step_fps", mode_info.avr_step_fps); sde_kms_info_add_keyint(info, "has_cwb_crop", test_bit(SDE_FEATURE_CWB_CROP, sde_kms->catalog->features)); sde_kms_info_add_keyint(info, "has_dedicated_cwb_support", @@ -3058,6 +3053,33 @@ exit: return rc; } +static void _sde_connector_install_qsync_properties(struct sde_kms *sde_kms, + struct sde_connector *c_conn, struct dsi_display *dsi_display, + struct msm_display_info *display_info) +{ + static const struct drm_prop_enum_list e_avr_step_state[] = { + {AVR_STEP_NONE, "avr_step_none"}, + {AVR_STEP_ENABLE, "avr_step_enable"}, + {AVR_STEP_DISABLE, "avr_step_disable"}, + }; + + if (test_bit(SDE_FEATURE_QSYNC, sde_kms->catalog->features) && dsi_display && + dsi_display->panel && dsi_display->panel->qsync_caps.qsync_support) { + msm_property_install_enum(&c_conn->property_info, "qsync_mode", 0, 0, e_qsync_mode, + ARRAY_SIZE(e_qsync_mode), 0, CONNECTOR_PROP_QSYNC_MODE); + + if (test_bit(SDE_FEATURE_EPT, sde_kms->catalog->features)) + msm_property_install_range(&c_conn->property_info, "EPT", 0x0, 0, U64_MAX, + 0, CONNECTOR_PROP_EPT); + + if (test_bit(SDE_FEATURE_AVR_STEP, sde_kms->catalog->features) && + (display_info->capabilities & MSM_DISPLAY_CAP_VID_MODE)) + msm_property_install_enum(&c_conn->property_info, "avr_step_state", + 0, 0, e_avr_step_state, ARRAY_SIZE(e_avr_step_state), 0, + CONNECTOR_PROP_AVR_STEP_STATE); + } +} + static int _sde_connector_install_properties(struct drm_device *dev, struct sde_kms *sde_kms, struct sde_connector *c_conn, int connector_type, void *display, @@ -3169,21 +3191,7 @@ static int _sde_connector_install_properties(struct drm_device *dev, CONNECTOR_PROP_AUTOREFRESH); if (connector_type == DRM_MODE_CONNECTOR_DSI) { - if (test_bit(SDE_FEATURE_QSYNC, sde_kms->catalog->features) && dsi_display && - dsi_display->panel && dsi_display->panel->qsync_caps.qsync_support) { - msm_property_install_enum(&c_conn->property_info, - "qsync_mode", 0, 0, e_qsync_mode, - ARRAY_SIZE(e_qsync_mode), 0, - CONNECTOR_PROP_QSYNC_MODE); - if (test_bit(SDE_FEATURE_EPT, sde_kms->catalog->features)) - msm_property_install_range(&c_conn->property_info, - "EPT", 0x0, 0, U64_MAX, 0, - CONNECTOR_PROP_EPT); - if (test_bit(SDE_FEATURE_AVR_STEP, sde_kms->catalog->features)) - msm_property_install_range(&c_conn->property_info, - "avr_step", 0x0, 0, U32_MAX, 0, - CONNECTOR_PROP_AVR_STEP); - } + _sde_connector_install_qsync_properties(sde_kms, c_conn, dsi_display, display_info); msm_property_install_enum(&c_conn->property_info, "dsc_mode", 0, 0, e_dsc_mode, ARRAY_SIZE(e_dsc_mode), 0, CONNECTOR_PROP_DSC_MODE); diff --git a/msm/sde/sde_connector.h b/msm/sde/sde_connector.h index f700309ae8..2f5781a865 100644 --- a/msm/sde/sde_connector.h +++ b/msm/sde/sde_connector.h @@ -408,12 +408,11 @@ struct sde_connector_ops { int (*get_qsync_min_fps)(struct drm_connector_state *conn_state); /** - * get_avr_step_req - Get the required avr_step for given fps rate - * @display: Pointer to private display structure - * @mode_fps: Fps value in dfps list + * get_avr_step_fps - Get the required avr_step for given fps rate + * @conn_state: Pointer to drm_connector_state structure * Returns: AVR step fps value on success */ - int (*get_avr_step_req)(void *display, u32 mode_fps); + int (*get_avr_step_fps)(struct drm_connector_state *conn_state); /** * set_submode_info - populate given sub mode blob @@ -449,6 +448,18 @@ struct sde_connector_ops { }; +/** + * enum sde_connector_avr_step_state: states of avr step fps + * @AVR_STEP_NONE: no-op + * @AVR_STEP_ENABLE: enable AVR step + * #AVR_STEP_DISABLE: disable AVR step + */ +enum sde_connector_avr_step_state { + AVR_STEP_NONE, + AVR_STEP_ENABLE, + AVR_STEP_DISABLE, +}; + /** * enum sde_connector_display_type - list of display types */ @@ -556,7 +567,6 @@ struct sde_misr_sign { * @dimming_bl_notify_enabled: Flag to indicate if dimming bl notify is enabled or not * @qsync_mode: Cached Qsync mode, 0=disabled, 1=continuous mode * @qsync_updated: Qsync settings were updated - * @avr_step: fps rate for fixed steps in AVR mode; 0 means step is disabled * @colorspace_updated: Colorspace property was updated * @last_cmd_tx_sts: status of the last command transfer * @hdr_capable: external hdr support present @@ -631,7 +641,6 @@ struct sde_connector { u8 hdr_plus_app_ver; u32 qsync_mode; bool qsync_updated; - u32 avr_step; bool colorspace_updated; @@ -687,13 +696,6 @@ struct sde_connector { #define sde_connector_get_qsync_mode(C) \ ((C) ? to_sde_connector((C))->qsync_mode : 0) -/** - * sde_connector_get_avr_step - get sde connector's avr_step - * @C: Pointer to drm connector structure - * Returns: Current cached avr_step value for given connector - */ -#define sde_connector_get_avr_step(C) ((C) ? to_sde_connector((C))->avr_step : 0) - /** * sde_connector_get_propinfo - get sde connector's property info pointer * @C: Pointer to drm connector structure diff --git a/msm/sde/sde_encoder.c b/msm/sde/sde_encoder.c index e121d5c7bf..2f7e704286 100644 --- a/msm/sde/sde_encoder.c +++ b/msm/sde/sde_encoder.c @@ -1215,40 +1215,32 @@ static void _sde_encoder_get_qsync_fps_callback(struct drm_encoder *drm_enc, } static int _sde_encoder_avr_step_check(struct sde_connector *sde_conn, - struct sde_connector_state *sde_conn_state, u32 step) + struct sde_connector_state *sde_conn_state) { - struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(sde_conn_state->base.best_encoder); u32 nom_fps = drm_mode_vrefresh(sde_conn_state->msm_mode.base); - u32 min_fps, req_fps = 0; + u32 min_fps, step_fps = 0; u32 vtotal = sde_conn_state->msm_mode.base->vtotal; - bool has_panel_req = sde_enc->disp_info.has_avr_step_req; u32 qsync_mode = sde_connector_get_property(&sde_conn_state->base, CONNECTOR_PROP_QSYNC_MODE); + u32 avr_step_state = sde_connector_get_property(&sde_conn_state->base, + CONNECTOR_PROP_AVR_STEP_STATE); - if (has_panel_req) { - if (!sde_conn->ops.get_avr_step_req) { - SDE_ERROR("unable to retrieve required step rate\n"); - return -EINVAL; - } + if ((avr_step_state == AVR_STEP_NONE) || !sde_conn->ops.get_avr_step_fps) + return 0; - req_fps = sde_conn->ops.get_avr_step_req(sde_conn->display, nom_fps); - /* when qsync is enabled, the step fps *must* be set to the panel requirement */ - if (qsync_mode && req_fps != step) { - SDE_ERROR("invalid avr_step %u, panel requires %u at nominal %u fps\n", - step, req_fps, nom_fps); - return -EINVAL; - } + if (!qsync_mode && avr_step_state) { + SDE_ERROR("invalid config: avr-step enabled without qsync\n"); + return -EINVAL; } - if (!step) - return 0; + step_fps = sde_conn->ops.get_avr_step_fps(&sde_conn_state->base); _sde_encoder_get_qsync_fps_callback(sde_conn_state->base.best_encoder, &min_fps, &sde_conn_state->base); - if (!min_fps || !nom_fps || step % nom_fps || step % min_fps || step < nom_fps || - (vtotal * nom_fps) % step) { + if (!min_fps || !nom_fps || step_fps % nom_fps || step_fps % min_fps + || step_fps < nom_fps || (vtotal * nom_fps) % step_fps) { SDE_ERROR("invalid avr_step rate! nom:%u min:%u step:%u vtotal:%u\n", nom_fps, - min_fps, step, vtotal); + min_fps, step_fps, vtotal); return -EINVAL; } @@ -1259,11 +1251,9 @@ static int _sde_encoder_atomic_check_qsync(struct sde_connector *sde_conn, struct sde_connector_state *sde_conn_state) { int rc = 0; - u32 avr_step; bool qsync_dirty, has_modeset, ept; struct drm_connector_state *conn_state = &sde_conn_state->base; - u32 qsync_mode = sde_connector_get_property(&sde_conn_state->base, - CONNECTOR_PROP_QSYNC_MODE); + u32 qsync_mode; has_modeset = sde_crtc_atomic_check_has_modeset(conn_state->state, conn_state->crtc); qsync_dirty = msm_property_is_dirty(&sde_conn->property_info, @@ -1279,9 +1269,9 @@ static int _sde_encoder_atomic_check_qsync(struct sde_connector *sde_conn, return -EINVAL; } - avr_step = sde_connector_get_property(conn_state, CONNECTOR_PROP_AVR_STEP); - if (qsync_dirty || (avr_step != sde_conn->avr_step) || (qsync_mode && has_modeset)) - rc = _sde_encoder_avr_step_check(sde_conn, sde_conn_state, avr_step); + qsync_mode = sde_connector_get_property(conn_state, CONNECTOR_PROP_QSYNC_MODE); + if (qsync_dirty || (qsync_mode && has_modeset)) + rc = _sde_encoder_avr_step_check(sde_conn, sde_conn_state); return rc; } @@ -4670,6 +4660,7 @@ void _sde_encoder_delay_kickoff_processing(struct sde_encoder_virt *sde_enc) u32 avr_step_fps, min_fps = 0, qsync_mode; u64 timeout_us = 0, ept; struct drm_connector *drm_conn; + struct msm_mode_info *info = &sde_enc->mode_info; if (!sde_enc->cur_master || !sde_enc->cur_master->connector) return; @@ -4679,13 +4670,13 @@ void _sde_encoder_delay_kickoff_processing(struct sde_encoder_virt *sde_enc) if (!ept) return; - avr_step_fps = sde_connector_get_avr_step(drm_conn); qsync_mode = sde_connector_get_property(drm_conn->state, CONNECTOR_PROP_QSYNC_MODE); if (qsync_mode) _sde_encoder_get_qsync_fps_callback(&sde_enc->base, &min_fps, drm_conn->state); /* use min qsync fps, if feature is enabled; otherwise min default fps */ min_fps = min_fps ? min_fps : DEFAULT_MIN_FPS; + avr_step_fps = info->avr_step_fps; current_ts = ktime_get_ns(); /* ept is in ns and avr_step is mulitple of refresh rate */ ept_ts = avr_step_fps ? ept - DIV_ROUND_UP(NSEC_PER_SEC, avr_step_fps) + NSEC_PER_MSEC diff --git a/msm/sde/sde_encoder_phys_vid.c b/msm/sde/sde_encoder_phys_vid.c index ccba77683a..8151cf725a 100644 --- a/msm/sde/sde_encoder_phys_vid.c +++ b/msm/sde/sde_encoder_phys_vid.c @@ -373,19 +373,30 @@ static void _sde_encoder_phys_vid_avr_ctrl(struct sde_encoder_phys *phys_enc) { struct intf_avr_params avr_params; struct sde_encoder_phys_vid *vid_enc = to_sde_encoder_phys_vid(phys_enc); - u32 avr_step_fps = sde_connector_get_avr_step(phys_enc->connector); + struct drm_connector *conn = phys_enc->connector; + struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(phys_enc->parent); + struct msm_mode_info *info = &sde_enc->mode_info; + u32 avr_step_state; + + if (!conn || !conn->state) + return; + + avr_step_state = sde_connector_get_property(conn->state, CONNECTOR_PROP_AVR_STEP_STATE); + if (avr_step_state == AVR_STEP_NONE) + return; memset(&avr_params, 0, sizeof(avr_params)); avr_params.avr_mode = sde_connector_get_qsync_mode(phys_enc->connector); - if (avr_step_fps) + + if (info->avr_step_fps && (avr_step_state == AVR_STEP_ENABLE)) avr_params.avr_step_lines = mult_frac(phys_enc->cached_mode.vtotal, - vid_enc->timing_params.vrefresh, avr_step_fps); + vid_enc->timing_params.vrefresh, info->avr_step_fps); if (vid_enc->base.hw_intf->ops.avr_ctrl) vid_enc->base.hw_intf->ops.avr_ctrl(vid_enc->base.hw_intf, &avr_params); - SDE_EVT32(DRMID(phys_enc->parent), phys_enc->hw_intf->idx - INTF_0, - avr_params.avr_mode, avr_params.avr_step_lines, avr_step_fps); + SDE_EVT32(DRMID(phys_enc->parent), phys_enc->hw_intf->idx - INTF_0, avr_params.avr_mode, + avr_params.avr_step_lines, info->avr_step_fps, avr_step_state); } static void sde_encoder_phys_vid_setup_timing_engine( diff --git a/msm/sde/sde_kms.c b/msm/sde/sde_kms.c index 36c7c340d2..8206bf4188 100644 --- a/msm/sde/sde_kms.c +++ b/msm/sde/sde_kms.c @@ -1829,7 +1829,7 @@ static int _sde_kms_setup_displays(struct drm_device *dev, .set_allowed_mode_switch = dsi_conn_set_allowed_mode_switch, .set_dyn_bit_clk = dsi_conn_set_dyn_bit_clk, .get_qsync_min_fps = dsi_conn_get_qsync_min_fps, - .get_avr_step_req = dsi_display_get_avr_step_req_fps, + .get_avr_step_fps = dsi_conn_get_avr_step_fps, .prepare_commit = dsi_conn_prepare_commit, .set_submode_info = dsi_conn_set_submode_blob_info, .get_num_lm_from_mode = dsi_conn_get_lm_from_mode,