diff options
author | qctecmdr <qctecmdr@localhost> | 2020-11-24 07:20:14 -0800 |
---|---|---|
committer | Gerrit - the friendly Code Review server <code-review@localhost> | 2020-11-24 07:20:14 -0800 |
commit | 8d51384c716e2c7e6ce50e17b026ec5f3c4c06c9 (patch) | |
tree | 8785fbc108a2e1baf4f2c3a4e8154e6fd75e603b | |
parent | e5fa7117cce191447ecf58ea35a6e102e9fcf092 (diff) | |
parent | 72944c5100849d76c554d1ebb33d2ca6e49772ce (diff) | |
download | display-drivers-8d51384c716e2c7e6ce50e17b026ec5f3c4c06c9.tar.gz |
Merge "disp: msm: sde: add support to handle qsync-min-fps list property"
-rw-r--r-- | msm/dsi/dsi_display.c | 28 | ||||
-rw-r--r-- | msm/dsi/dsi_display.h | 10 | ||||
-rw-r--r-- | msm/dsi/dsi_drm.c | 6 | ||||
-rw-r--r-- | msm/dsi/dsi_panel.c | 83 | ||||
-rw-r--r-- | msm/dsi/dsi_panel.h | 9 | ||||
-rw-r--r-- | msm/msm_drv.h | 3 | ||||
-rw-r--r-- | msm/sde/sde_connector.h | 10 | ||||
-rw-r--r-- | msm/sde/sde_encoder.c | 29 | ||||
-rw-r--r-- | msm/sde/sde_encoder_phys.h | 2 | ||||
-rw-r--r-- | msm/sde/sde_encoder_phys_cmd.c | 2 | ||||
-rw-r--r-- | msm/sde/sde_encoder_phys_vid.c | 2 | ||||
-rw-r--r-- | msm/sde/sde_kms.c | 1 |
12 files changed, 167 insertions, 18 deletions
diff --git a/msm/dsi/dsi_display.c b/msm/dsi/dsi_display.c index b1d66c45..acb1f7db 100644 --- a/msm/dsi/dsi_display.c +++ b/msm/dsi/dsi_display.c @@ -6064,7 +6064,10 @@ int dsi_display_get_info(struct drm_connector *connector, info->max_width = 1920; info->max_height = 1080; info->qsync_min_fps = - display->panel->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) ? + true : false; switch (display->panel->panel_mode) { case DSI_OP_VIDEO_MODE: @@ -6509,6 +6512,25 @@ int dsi_display_get_default_lms(void *dsi_display, u32 *num_lm) return rc; } +int dsi_display_get_qsync_min_fps(void *display_dsi, u32 mode_fps) +{ + struct dsi_display *display = (struct dsi_display *)display_dsi; + struct dsi_panel *panel; + u32 i; + + if (display == NULL || display->panel == NULL) + return -EINVAL; + + panel = display->panel; + for (i = 0; i < panel->dfps_caps.dfps_list_len; i++) { + if (panel->dfps_caps.dfps_list[i] == mode_fps) + return panel->qsync_caps.qsync_min_fps_list[i]; + } + SDE_EVT32(mode_fps); + DSI_DEBUG("Invalid mode_fps %d\n", mode_fps); + return -EINVAL; +} + int dsi_display_find_mode(struct dsi_display *display, const struct dsi_display_mode *cmp, struct dsi_display_mode **out_mode) @@ -7340,7 +7362,7 @@ static int dsi_display_qsync(struct dsi_display *display, bool enable) int i; int rc = 0; - if (!display->panel->qsync_min_fps) { + if (!display->panel->qsync_caps.qsync_min_fps) { DSI_ERR("%s:ERROR: qsync set, but no fps\n", __func__); return 0; } @@ -7368,7 +7390,7 @@ static int dsi_display_qsync(struct dsi_display *display, bool enable) } exit: - SDE_EVT32(enable, display->panel->qsync_min_fps, rc); + SDE_EVT32(enable, display->panel->qsync_caps.qsync_min_fps, rc); mutex_unlock(&display->display_lock); return rc; } diff --git a/msm/dsi/dsi_display.h b/msm/dsi/dsi_display.h index 00f6133a..d254dfe7 100644 --- a/msm/dsi/dsi_display.h +++ b/msm/dsi/dsi_display.h @@ -395,6 +395,16 @@ void dsi_display_put_mode(struct dsi_display *display, int dsi_display_get_default_lms(void *dsi_display, u32 *num_lm); /** + * dsi_display_get_qsync_min_fps() - get qsync min fps for given fps + * @display: Handle to display. + * @mode_fps: Fps value of current mode + * + * Return: error code. + */ +int dsi_display_get_qsync_min_fps(void *dsi_display, u32 mode_fps); + + +/** * dsi_display_find_mode() - retrieve cached DSI mode given relevant params * @display: Handle to display. * @cmp: Mode to use as comparison to find original diff --git a/msm/dsi/dsi_drm.c b/msm/dsi/dsi_drm.c index c7002f58..aeb89a7e 100644 --- a/msm/dsi/dsi_drm.c +++ b/msm/dsi/dsi_drm.c @@ -587,14 +587,16 @@ int dsi_conn_set_info_blob(struct drm_connector *connector, case DSI_OP_VIDEO_MODE: sde_kms_info_add_keystr(info, "panel mode", "video"); sde_kms_info_add_keystr(info, "qsync support", - panel->qsync_min_fps ? "true" : "false"); + panel->qsync_caps.qsync_min_fps ? + "true" : "false"); break; case DSI_OP_CMD_MODE: sde_kms_info_add_keystr(info, "panel mode", "command"); sde_kms_info_add_keyint(info, "mdp_transfer_time_us", mode_info->mdp_transfer_time_us); sde_kms_info_add_keystr(info, "qsync support", - panel->qsync_min_fps ? "true" : "false"); + panel->qsync_caps.qsync_min_fps ? + "true" : "false"); break; default: DSI_DEBUG("invalid panel type:%d\n", panel->panel_mode); diff --git a/msm/dsi/dsi_panel.c b/msm/dsi/dsi_panel.c index f2b575d0..40c892d2 100644 --- a/msm/dsi/dsi_panel.c +++ b/msm/dsi/dsi_panel.c @@ -1314,8 +1314,15 @@ static int dsi_panel_parse_qsync_caps(struct dsi_panel *panel, struct device_node *of_node) { int rc = 0; - u32 val = 0; + u32 val = 0, i; + struct dsi_qsync_capabilities *qsync_caps = &panel->qsync_caps; + struct dsi_parser_utils *utils = &panel->utils; + const char *name = panel->name; + /** + * "mdss-dsi-qsync-min-refresh-rate" is defined in cmd mode and + * video mode when there is only one qsync min fps present. + */ rc = of_property_read_u32(of_node, "qcom,mdss-dsi-qsync-min-refresh-rate", &val); @@ -1323,8 +1330,75 @@ static int dsi_panel_parse_qsync_caps(struct dsi_panel *panel, DSI_DEBUG("[%s] qsync min fps not defined rc:%d\n", panel->name, rc); - panel->qsync_min_fps = val; + qsync_caps->qsync_min_fps = val; + + /** + * "dsi-supported-qsync-min-fps-list" may be defined in video + * mode, only in dfps case when "qcom,dsi-supported-dfps-list" + * is defined. + */ + qsync_caps->qsync_min_fps_list_len = utils->count_u32_elems(utils->data, + "qcom,dsi-supported-qsync-min-fps-list"); + if (qsync_caps->qsync_min_fps_list_len < 1) + goto qsync_support; + + /** + * qcom,dsi-supported-qsync-min-fps-list cannot be defined + * along with qcom,mdss-dsi-qsync-min-refresh-rate. + */ + if (qsync_caps->qsync_min_fps_list_len >= 1 && + qsync_caps->qsync_min_fps) { + DSI_ERR("[%s] Both qsync nodes are defined\n", + name); + rc = -EINVAL; + goto error; + } + + if (panel->dfps_caps.dfps_list_len != + qsync_caps->qsync_min_fps_list_len) { + DSI_ERR("[%s] Qsync min fps list mismatch with dfps\n", name); + rc = -EINVAL; + goto error; + } + + qsync_caps->qsync_min_fps_list = + kcalloc(qsync_caps->qsync_min_fps_list_len, sizeof(u32), + GFP_KERNEL); + if (!qsync_caps->qsync_min_fps_list) { + rc = -ENOMEM; + goto error; + } + + rc = utils->read_u32_array(utils->data, + "qcom,dsi-supported-qsync-min-fps-list", + qsync_caps->qsync_min_fps_list, + qsync_caps->qsync_min_fps_list_len); + if (rc) { + DSI_ERR("[%s] Qsync min fps list parse failed\n", name); + rc = -EINVAL; + goto error; + } + + qsync_caps->qsync_min_fps = qsync_caps->qsync_min_fps_list[0]; + for (i = 1; i < qsync_caps->qsync_min_fps_list_len; i++) { + if (qsync_caps->qsync_min_fps_list[i] < + qsync_caps->qsync_min_fps) + qsync_caps->qsync_min_fps = + qsync_caps->qsync_min_fps_list[i]; + } + +qsync_support: + /* 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_caps.qsync_min_fps = 0; + +error: + if (rc < 0) { + qsync_caps->qsync_min_fps = 0; + qsync_caps->qsync_min_fps_list_len = 0; + } return rc; } @@ -3313,11 +3387,6 @@ struct dsi_panel *dsi_panel_get(struct device *parent, 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) DSI_ERR("failed to parse dynamic clk config, rc=%d\n", rc); diff --git a/msm/dsi/dsi_panel.h b/msm/dsi/dsi_panel.h index d483e535..9f0e1cb1 100644 --- a/msm/dsi/dsi_panel.h +++ b/msm/dsi/dsi_panel.h @@ -84,6 +84,13 @@ struct dsi_dfps_capabilities { bool dfps_support; }; +struct dsi_qsync_capabilities { + /* qsync disabled if qsync_min_fps = 0 */ + u32 qsync_min_fps; + u32 *qsync_min_fps_list; + int qsync_min_fps_list_len; +}; + struct dsi_dyn_clk_caps { bool dyn_clk_support; u32 *bit_clk_list; @@ -207,7 +214,7 @@ struct dsi_panel { bool panel_initialized; bool te_using_watchdog_timer; - u32 qsync_min_fps; + struct dsi_qsync_capabilities qsync_caps; char dsc_pps_cmd[DSI_CMD_PPS_SIZE]; enum dsi_dms_mode dms_mode; diff --git a/msm/msm_drv.h b/msm/msm_drv.h index bd784d4a..20969665 100644 --- a/msm/msm_drv.h +++ b/msm/msm_drv.h @@ -512,6 +512,7 @@ struct msm_resource_caps_info { * used instead of panel TE in cmd mode panels * @roi_caps: Region of interest capability info * @qsync_min_fps Minimum fps supported by Qsync feature + * @has_qsync_min_fps_list True if dsi-supported-qsync-min-fps-list exits * @te_source vsync source pin information */ struct msm_display_info { @@ -535,6 +536,8 @@ struct msm_display_info { struct msm_roi_caps roi_caps; uint32_t qsync_min_fps; + bool has_qsync_min_fps_list; + uint32_t te_source; }; diff --git a/msm/sde/sde_connector.h b/msm/sde/sde_connector.h index 9389f135..cbc6bfa0 100644 --- a/msm/sde/sde_connector.h +++ b/msm/sde/sde_connector.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2016-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2016-2020, The Linux Foundation. All rights reserved. */ #ifndef _SDE_CONNECTOR_H_ @@ -338,6 +338,14 @@ struct sde_connector_ops { */ int (*prepare_commit)(void *display, struct msm_display_conn_params *params); + + /** + * get_qsync_min_fps - Get qsync min fps from qsync-min-fps-list + * @display: Pointer to private display structure + * @mode_fps: Fps value in dfps list + * Returns: Qsync min fps value on success + */ + int (*get_qsync_min_fps)(void *display, u32 mode_fps); }; /** diff --git a/msm/sde/sde_encoder.c b/msm/sde/sde_encoder.c index 1a34c0ba..4c43e13c 100644 --- a/msm/sde/sde_encoder.c +++ b/msm/sde/sde_encoder.c @@ -3879,10 +3879,12 @@ static void sde_encoder_frame_done_callback( static void sde_encoder_get_qsync_fps_callback( struct drm_encoder *drm_enc, - u32 *qsync_fps) + u32 *qsync_fps, u32 vrr_fps) { struct msm_display_info *disp_info; struct sde_encoder_virt *sde_enc; + int rc = 0; + struct sde_connector *sde_conn; if (!qsync_fps) return; @@ -3896,6 +3898,31 @@ static void sde_encoder_get_qsync_fps_callback( sde_enc = to_sde_encoder_virt(drm_enc); disp_info = &sde_enc->disp_info; *qsync_fps = disp_info->qsync_min_fps; + + /** + * If "dsi-supported-qsync-min-fps-list" is defined, get + * the qsync min fps corresponding to the fps in dfps list + */ + if (disp_info->has_qsync_min_fps_list) { + + if (!sde_enc->cur_master || + !(sde_enc->disp_info.capabilities & + MSM_DISPLAY_CAP_VID_MODE)) { + SDE_ERROR("invalid qsync settings %b\n", + !sde_enc->cur_master); + return; + } + sde_conn = to_sde_connector(sde_enc->cur_master->connector); + + if (sde_conn->ops.get_qsync_min_fps) + rc = sde_conn->ops.get_qsync_min_fps(sde_conn->display, + vrr_fps); + if (rc <= 0) { + SDE_ERROR("invalid qsync min fps %d\n", rc); + return; + } + *qsync_fps = rc; + } } int sde_encoder_idle_request(struct drm_encoder *drm_enc) diff --git a/msm/sde/sde_encoder_phys.h b/msm/sde/sde_encoder_phys.h index a7fa9bda..22355dc9 100644 --- a/msm/sde/sde_encoder_phys.h +++ b/msm/sde/sde_encoder_phys.h @@ -82,7 +82,7 @@ struct sde_encoder_virt_ops { void (*handle_frame_done)(struct drm_encoder *parent, struct sde_encoder_phys *phys, u32 event); void (*get_qsync_fps)(struct drm_encoder *parent, - u32 *qsync_fps); + u32 *qsync_fps, u32 vrr_fps); }; /** diff --git a/msm/sde/sde_encoder_phys_cmd.c b/msm/sde/sde_encoder_phys_cmd.c index 4f99a496..f9f3873e 100644 --- a/msm/sde/sde_encoder_phys_cmd.c +++ b/msm/sde/sde_encoder_phys_cmd.c @@ -949,7 +949,7 @@ static int _get_tearcheck_threshold(struct sde_encoder_phys *phys_enc, if (phys_enc->parent_ops.get_qsync_fps) phys_enc->parent_ops.get_qsync_fps( - phys_enc->parent, &qsync_min_fps); + phys_enc->parent, &qsync_min_fps, 0); if (!qsync_min_fps || !default_fps || !yres) { SDE_ERROR_CMDENC(cmd_enc, diff --git a/msm/sde/sde_encoder_phys_vid.c b/msm/sde/sde_encoder_phys_vid.c index a10939ec..7708cf8f 100644 --- a/msm/sde/sde_encoder_phys_vid.c +++ b/msm/sde/sde_encoder_phys_vid.c @@ -461,7 +461,7 @@ static void sde_encoder_phys_vid_setup_timing_engine( exit: if (phys_enc->parent_ops.get_qsync_fps) phys_enc->parent_ops.get_qsync_fps( - phys_enc->parent, &qsync_min_fps); + phys_enc->parent, &qsync_min_fps, mode.vrefresh); /* only panels which support qsync will have a non-zero min fps */ if (qsync_min_fps) { diff --git a/msm/sde/sde_kms.c b/msm/sde/sde_kms.c index 050ba34e..25a869fb 100644 --- a/msm/sde/sde_kms.c +++ b/msm/sde/sde_kms.c @@ -1430,6 +1430,7 @@ static int _sde_kms_setup_displays(struct drm_device *dev, .cont_splash_config = dsi_display_cont_splash_config, .get_panel_vfp = dsi_display_get_panel_vfp, .get_default_lms = dsi_display_get_default_lms, + .get_qsync_min_fps = dsi_display_get_qsync_min_fps, }; static const struct sde_connector_ops wb_ops = { .post_init = sde_wb_connector_post_init, |