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 <quic_veeras@quicinc.com>
This commit is contained in:
Veera Sundaram Sankaran
2023-01-20 15:20:10 -08:00
parent 95e583e413
commit 2e3ba9430c
13 changed files with 155 additions and 141 deletions

View File

@@ -419,6 +419,7 @@ struct dsi_panel_cmd_set {
* @pclk_scale: pclk scale factor, target bpp to source bpp * @pclk_scale: pclk scale factor, target bpp to source bpp
* @roi_caps: Panel ROI capabilities. * @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 { struct dsi_mode_info {
u32 h_active; u32 h_active;
@@ -446,6 +447,7 @@ struct dsi_mode_info {
struct msm_ratio pclk_scale; struct msm_ratio pclk_scale;
struct msm_roi_caps roi_caps; struct msm_roi_caps roi_caps;
u32 qsync_min_fps; u32 qsync_min_fps;
u32 avr_step_fps;
}; };
/** /**
@@ -625,6 +627,7 @@ struct dsi_host_config {
* for command mode panels in microseconds. * for command mode panels in microseconds.
* @dsi_transfer_time_us: Specifies the dsi transfer time for cmd panels. * @dsi_transfer_time_us: Specifies the dsi transfer time for cmd panels.
* @qsync_min_fps: Qsync min fps value for the mode * @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. * @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. * @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. * @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 mdp_transfer_time_us_max;
u32 dsi_transfer_time_us; u32 dsi_transfer_time_us;
u32 qsync_min_fps; u32 qsync_min_fps;
u32 avr_step_fps;
u64 clk_rate_hz; u64 clk_rate_hz;
u64 min_dsi_clk_hz; u64 min_dsi_clk_hz;
struct msm_dyn_clk_list bit_clk_list; struct msm_dyn_clk_list bit_clk_list;

View File

@@ -6754,7 +6754,7 @@ int dsi_display_get_info(struct drm_connector *connector,
info->max_height = 1080; info->max_height = 1080;
info->qsync_min_fps = display->panel->qsync_caps.qsync_min_fps; 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_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; info->poms_align_vsync = display->panel->poms_align_vsync;
switch (display->panel->panel_mode) { 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, int dsi_display_get_modes_helper(struct dsi_display *display,
struct dsi_display_ctrl *ctrl, u32 timing_mode_count, struct dsi_display_ctrl *ctrl, u32 timing_mode_count,
struct dsi_dfps_capabilities dfps_caps, struct dsi_qsync_capabilities *qsync_caps, 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; int dsc_modes = 0, nondsc_modes = 0, rc = 0, i, start, end;
u32 num_dfps_rates, mode_idx, sublinks_count, array_idx = 0; 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) if (!sub_mode->timing.qsync_min_fps && qsync_caps->qsync_min_fps)
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 * Qsync min fps for the mode will be populated in the timing info
* in dsi_panel_get_mode function. * 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; 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, dsi_display_get_dfps_timing(display, sub_mode,
curr_refresh_rate); curr_refresh_rate);
sub_mode->panel_mode_caps = DSI_OP_VIDEO_MODE; 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; struct dsi_dyn_clk_caps *dyn_clk_caps;
int rc = -EINVAL; int rc = -EINVAL;
struct dsi_qsync_capabilities *qsync_caps; struct dsi_qsync_capabilities *qsync_caps;
struct dsi_avr_capabilities *avr_caps;
if (!display || !out_modes) { if (!display || !out_modes) {
DSI_ERR("Invalid params\n"); DSI_ERR("Invalid params\n");
@@ -7247,6 +7258,7 @@ int dsi_display_get_modes(struct dsi_display *display,
qsync_caps = &(display->panel->qsync_caps); qsync_caps = &(display->panel->qsync_caps);
dyn_clk_caps = &(display->panel->dyn_clk_caps); dyn_clk_caps = &(display->panel->dyn_clk_caps);
avr_caps = &(display->panel->avr_caps);
timing_mode_count = display->panel->num_timing_nodes; 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; display->cmdline_timing = NO_OVERRIDE;
rc = dsi_display_get_modes_helper(display, ctrl, timing_mode_count, 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) if (rc)
goto error; goto error;
@@ -7353,31 +7365,6 @@ int dsi_display_get_default_lms(void *dsi_display, u32 *num_lm)
return rc; 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) int dsi_display_update_transfer_time(void *display, u32 transfer_time)
{ {
struct dsi_display *disp = (struct dsi_display *)display; struct dsi_display *disp = (struct dsi_display *)display;

View File

@@ -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); 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 * dsi_conn_get_lm_from_mode() - retrieves LM count from dsi mode priv info
* @display: Handle to display. * @display: Handle to display.

View File

@@ -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->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->disable_rsc_solver = dsi_mode->priv_info->disable_rsc_solver;
mode_info->qsync_min_fps = dsi_mode->timing.qsync_min_fps; 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->wd_jitter = dsi_mode->priv_info->wd_jitter;
mode_info->vpadding = dsi_display->panel->host_config.vpadding; 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, .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) 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); 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; 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, int dsi_conn_set_info_blob(struct drm_connector *connector,
void *info, void *display, struct msm_mode_info *mode_info) 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) { switch (panel->panel_mode) {
case DSI_OP_VIDEO_MODE: case DSI_OP_VIDEO_MODE:
sde_kms_info_add_keystr(info, "panel mode", "video"); 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; break;
case DSI_OP_CMD_MODE: case DSI_OP_CMD_MODE:
sde_kms_info_add_keystr(info, "panel mode", "command"); sde_kms_info_add_keystr(info, "panel mode", "command");

View File

@@ -1,5 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* 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. * 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. * Return: Qsync min fps rate or -ve error code.
*/ */
int dsi_conn_get_qsync_min_fps(struct drm_connector_state *conn_state); 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_ */ #endif /* _DSI_DRM_H_ */

View File

@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only // 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. * 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 = 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", 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_active, mode->v_front_porch, mode->v_back_porch,
mode->v_sync_width); 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; struct dsi_parser_utils *utils = &panel->utils;
int val, rc = 0; 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"); val = utils->count_u32_elems(utils->data, "qcom,dsi-qsync-avr-step-list");
if (val <= 0) { if (val <= 0) {
DSI_DEBUG("[%s] optional avr step list not defined, val:%d\n", panel->name, val); 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) { } 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", DSI_ERR("[%s] avr step list size %d not same as dfps list %d\n",
panel->name, val, panel->dfps_caps.dfps_list_len); panel->name, val, panel->dfps_caps.dfps_list_len);
return -EINVAL; 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); avr_caps->avr_step_fps_list = kcalloc(val, sizeof(u32), GFP_KERNEL);

View File

@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */ /* 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. * Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
*/ */
@@ -99,6 +99,7 @@ struct dsi_qsync_capabilities {
}; };
struct dsi_avr_capabilities { struct dsi_avr_capabilities {
u32 avr_step_fps;
u32 *avr_step_fps_list; u32 *avr_step_fps_list;
u32 avr_step_fps_list_len; u32 avr_step_fps_list_len;
}; };

View File

@@ -246,7 +246,7 @@ enum msm_mdp_conn_property {
CONNECTOR_PROP_QSYNC_MODE, CONNECTOR_PROP_QSYNC_MODE,
CONNECTOR_PROP_CMD_FRAME_TRIGGER_MODE, CONNECTOR_PROP_CMD_FRAME_TRIGGER_MODE,
CONNECTOR_PROP_SET_PANEL_MODE, CONNECTOR_PROP_SET_PANEL_MODE,
CONNECTOR_PROP_AVR_STEP, CONNECTOR_PROP_AVR_STEP_STATE,
CONNECTOR_PROP_EPT, CONNECTOR_PROP_EPT,
CONNECTOR_PROP_CACHE_STATE, CONNECTOR_PROP_CACHE_STATE,
CONNECTOR_PROP_DSC_MODE, 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. * @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. * @dyn_clk_list: List of dynamic clock rates for RFI.
* @qsync_min_fps: qsync min fps rate * @qsync_min_fps: qsync min fps rate
* @avr_step_fps: AVR step fps rate
* @wd_jitter: Info for WD jitter. * @wd_jitter: Info for WD jitter.
* @vpadding: panel stacking height * @vpadding: panel stacking height
*/ */
@@ -837,6 +838,7 @@ struct msm_mode_info {
bool disable_rsc_solver; bool disable_rsc_solver;
struct msm_dyn_clk_list dyn_clk_list; struct msm_dyn_clk_list dyn_clk_list;
u32 qsync_min_fps; u32 qsync_min_fps;
u32 avr_step_fps;
struct msm_display_wd_jitter_config wd_jitter; struct msm_display_wd_jitter_config wd_jitter;
u32 vpadding; u32 vpadding;
}; };
@@ -885,7 +887,7 @@ struct msm_resource_caps_info {
* @roi_caps: Region of interest capability info * @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_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 * @te_source vsync source pin information
* @dsc_count: max dsc hw blocks used by display (only available * @dsc_count: max dsc hw blocks used by display (only available
* for dsi display) * for dsi display)
@@ -915,7 +917,7 @@ struct msm_display_info {
uint32_t qsync_min_fps; uint32_t qsync_min_fps;
bool has_qsync_min_fps_list; bool has_qsync_min_fps_list;
bool has_avr_step_req; uint32_t avr_step_fps;
uint32_t te_source; uint32_t te_source;

View File

@@ -854,7 +854,7 @@ void sde_connector_set_qsync_params(struct drm_connector *connector)
{ {
struct sde_connector *c_conn; struct sde_connector *c_conn;
struct sde_connector_state *c_state; struct sde_connector_state *c_state;
u32 qsync_propval = 0, step_val = 0; u32 qsync_propval = 0;
bool prop_dirty; bool prop_dirty;
if (!connector) 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, prop_dirty = msm_property_is_dirty(&c_conn->property_info, &c_state->property_state,
CONNECTOR_PROP_AVR_STEP); CONNECTOR_PROP_AVR_STEP_STATE);
if (prop_dirty) { 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->qsync_updated = true;
c_conn->avr_step = step_val;
}
}
} }
void sde_connector_complete_qsync_commit(struct drm_connector *conn, 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, "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_info_add_keyint(info, "has_cwb_crop", test_bit(SDE_FEATURE_CWB_CROP,
sde_kms->catalog->features)); sde_kms->catalog->features));
sde_kms_info_add_keyint(info, "has_dedicated_cwb_support", sde_kms_info_add_keyint(info, "has_dedicated_cwb_support",
@@ -3058,6 +3053,33 @@ exit:
return rc; 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, static int _sde_connector_install_properties(struct drm_device *dev,
struct sde_kms *sde_kms, struct sde_connector *c_conn, struct sde_kms *sde_kms, struct sde_connector *c_conn,
int connector_type, void *display, int connector_type, void *display,
@@ -3169,21 +3191,7 @@ static int _sde_connector_install_properties(struct drm_device *dev,
CONNECTOR_PROP_AUTOREFRESH); CONNECTOR_PROP_AUTOREFRESH);
if (connector_type == DRM_MODE_CONNECTOR_DSI) { if (connector_type == DRM_MODE_CONNECTOR_DSI) {
if (test_bit(SDE_FEATURE_QSYNC, sde_kms->catalog->features) && dsi_display && _sde_connector_install_qsync_properties(sde_kms, c_conn, dsi_display, display_info);
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);
}
msm_property_install_enum(&c_conn->property_info, "dsc_mode", 0, 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); 0, e_dsc_mode, ARRAY_SIZE(e_dsc_mode), 0, CONNECTOR_PROP_DSC_MODE);

View File

@@ -408,12 +408,11 @@ struct sde_connector_ops {
int (*get_qsync_min_fps)(struct drm_connector_state *conn_state); int (*get_qsync_min_fps)(struct drm_connector_state *conn_state);
/** /**
* get_avr_step_req - Get the required avr_step for given fps rate * get_avr_step_fps - Get the required avr_step for given fps rate
* @display: Pointer to private display structure * @conn_state: Pointer to drm_connector_state structure
* @mode_fps: Fps value in dfps list
* Returns: AVR step fps value on success * 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 * 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 * 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 * @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_mode: Cached Qsync mode, 0=disabled, 1=continuous mode
* @qsync_updated: Qsync settings were updated * @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 * @colorspace_updated: Colorspace property was updated
* @last_cmd_tx_sts: status of the last command transfer * @last_cmd_tx_sts: status of the last command transfer
* @hdr_capable: external hdr support present * @hdr_capable: external hdr support present
@@ -631,7 +641,6 @@ struct sde_connector {
u8 hdr_plus_app_ver; u8 hdr_plus_app_ver;
u32 qsync_mode; u32 qsync_mode;
bool qsync_updated; bool qsync_updated;
u32 avr_step;
bool colorspace_updated; bool colorspace_updated;
@@ -687,13 +696,6 @@ struct sde_connector {
#define sde_connector_get_qsync_mode(C) \ #define sde_connector_get_qsync_mode(C) \
((C) ? to_sde_connector((C))->qsync_mode : 0) ((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 * sde_connector_get_propinfo - get sde connector's property info pointer
* @C: Pointer to drm connector structure * @C: Pointer to drm connector structure

View File

@@ -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, 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 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; 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, u32 qsync_mode = sde_connector_get_property(&sde_conn_state->base,
CONNECTOR_PROP_QSYNC_MODE); 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 ((avr_step_state == AVR_STEP_NONE) || !sde_conn->ops.get_avr_step_fps)
if (!sde_conn->ops.get_avr_step_req) {
SDE_ERROR("unable to retrieve required step rate\n");
return -EINVAL;
}
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 (!step)
return 0; return 0;
if (!qsync_mode && avr_step_state) {
SDE_ERROR("invalid config: avr-step enabled without qsync\n");
return -EINVAL;
}
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_encoder_get_qsync_fps_callback(sde_conn_state->base.best_encoder, &min_fps,
&sde_conn_state->base); &sde_conn_state->base);
if (!min_fps || !nom_fps || step % nom_fps || step % min_fps || step < nom_fps || if (!min_fps || !nom_fps || step_fps % nom_fps || step_fps % min_fps
(vtotal * nom_fps) % step) { || 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, 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; 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) struct sde_connector_state *sde_conn_state)
{ {
int rc = 0; int rc = 0;
u32 avr_step;
bool qsync_dirty, has_modeset, ept; bool qsync_dirty, has_modeset, ept;
struct drm_connector_state *conn_state = &sde_conn_state->base; struct drm_connector_state *conn_state = &sde_conn_state->base;
u32 qsync_mode = sde_connector_get_property(&sde_conn_state->base, u32 qsync_mode;
CONNECTOR_PROP_QSYNC_MODE);
has_modeset = sde_crtc_atomic_check_has_modeset(conn_state->state, conn_state->crtc); has_modeset = sde_crtc_atomic_check_has_modeset(conn_state->state, conn_state->crtc);
qsync_dirty = msm_property_is_dirty(&sde_conn->property_info, 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; return -EINVAL;
} }
avr_step = sde_connector_get_property(conn_state, CONNECTOR_PROP_AVR_STEP); qsync_mode = sde_connector_get_property(conn_state, CONNECTOR_PROP_QSYNC_MODE);
if (qsync_dirty || (avr_step != sde_conn->avr_step) || (qsync_mode && has_modeset)) if (qsync_dirty || (qsync_mode && has_modeset))
rc = _sde_encoder_avr_step_check(sde_conn, sde_conn_state, avr_step); rc = _sde_encoder_avr_step_check(sde_conn, sde_conn_state);
return rc; 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; u32 avr_step_fps, min_fps = 0, qsync_mode;
u64 timeout_us = 0, ept; u64 timeout_us = 0, ept;
struct drm_connector *drm_conn; struct drm_connector *drm_conn;
struct msm_mode_info *info = &sde_enc->mode_info;
if (!sde_enc->cur_master || !sde_enc->cur_master->connector) if (!sde_enc->cur_master || !sde_enc->cur_master->connector)
return; return;
@@ -4679,13 +4670,13 @@ void _sde_encoder_delay_kickoff_processing(struct sde_encoder_virt *sde_enc)
if (!ept) if (!ept)
return; return;
avr_step_fps = sde_connector_get_avr_step(drm_conn);
qsync_mode = sde_connector_get_property(drm_conn->state, CONNECTOR_PROP_QSYNC_MODE); qsync_mode = sde_connector_get_property(drm_conn->state, CONNECTOR_PROP_QSYNC_MODE);
if (qsync_mode) if (qsync_mode)
_sde_encoder_get_qsync_fps_callback(&sde_enc->base, &min_fps, drm_conn->state); _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 */ /* use min qsync fps, if feature is enabled; otherwise min default fps */
min_fps = min_fps ? min_fps : DEFAULT_MIN_FPS; min_fps = min_fps ? min_fps : DEFAULT_MIN_FPS;
avr_step_fps = info->avr_step_fps;
current_ts = ktime_get_ns(); current_ts = ktime_get_ns();
/* ept is in ns and avr_step is mulitple of refresh rate */ /* 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 ept_ts = avr_step_fps ? ept - DIV_ROUND_UP(NSEC_PER_SEC, avr_step_fps) + NSEC_PER_MSEC

View File

@@ -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 intf_avr_params avr_params;
struct sde_encoder_phys_vid *vid_enc = to_sde_encoder_phys_vid(phys_enc); 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)); memset(&avr_params, 0, sizeof(avr_params));
avr_params.avr_mode = sde_connector_get_qsync_mode(phys_enc->connector); 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, 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) if (vid_enc->base.hw_intf->ops.avr_ctrl)
vid_enc->base.hw_intf->ops.avr_ctrl(vid_enc->base.hw_intf, &avr_params); 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, SDE_EVT32(DRMID(phys_enc->parent), phys_enc->hw_intf->idx - INTF_0, avr_params.avr_mode,
avr_params.avr_mode, avr_params.avr_step_lines, avr_step_fps); avr_params.avr_step_lines, info->avr_step_fps, avr_step_state);
} }
static void sde_encoder_phys_vid_setup_timing_engine( static void sde_encoder_phys_vid_setup_timing_engine(

View File

@@ -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_allowed_mode_switch = dsi_conn_set_allowed_mode_switch,
.set_dyn_bit_clk = dsi_conn_set_dyn_bit_clk, .set_dyn_bit_clk = dsi_conn_set_dyn_bit_clk,
.get_qsync_min_fps = dsi_conn_get_qsync_min_fps, .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, .prepare_commit = dsi_conn_prepare_commit,
.set_submode_info = dsi_conn_set_submode_blob_info, .set_submode_info = dsi_conn_set_submode_blob_info,
.get_num_lm_from_mode = dsi_conn_get_lm_from_mode, .get_num_lm_from_mode = dsi_conn_get_lm_from_mode,