summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKrishna Manikandan <mkrishn@codeaurora.org>2020-11-18 13:14:24 +0530
committerKrishna Manikandan <mkrishn@codeaurora.org>2020-11-19 11:26:39 +0530
commit72944c5100849d76c554d1ebb33d2ca6e49772ce (patch)
tree4ba66fab57bac31d439359fa89190f8e89a0f3be
parent213d04499e661bed3b36a5294271706088a4964f (diff)
downloaddisplay-drivers-72944c5100849d76c554d1ebb33d2ca6e49772ce.tar.gz
disp: msm: sde: add support to handle qsync-min-fps list property
Qsync min fps is same for all the fps in the dfps list in the current implementation. Added support to parse qcom,dsi-supported-qsync-min-fps-list where each value is the qsync min fps corresponding to the mode in the dfps list with same index. Change-Id: I68b179f6eacbf9cc14c1bd90d71d5661c2255750 Signed-off-by: Krishna Manikandan <mkrishn@codeaurora.org>
-rw-r--r--msm/dsi/dsi_display.c28
-rw-r--r--msm/dsi/dsi_display.h10
-rw-r--r--msm/dsi/dsi_drm.c6
-rw-r--r--msm/dsi/dsi_panel.c83
-rw-r--r--msm/dsi/dsi_panel.h9
-rw-r--r--msm/msm_drv.h3
-rw-r--r--msm/sde/sde_connector.h10
-rw-r--r--msm/sde/sde_encoder.c29
-rw-r--r--msm/sde/sde_encoder_phys.h2
-rw-r--r--msm/sde/sde_encoder_phys_cmd.c2
-rw-r--r--msm/sde/sde_encoder_phys_vid.c2
-rw-r--r--msm/sde/sde_kms.c1
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 32c983ba..17243a5c 100644
--- a/msm/sde/sde_encoder.c
+++ b/msm/sde/sde_encoder.c
@@ -3865,10 +3865,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;
@@ -3882,6 +3884,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 54faa7cb..0744553d 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,