Merge "disp: msm: add qsync refresh rate support per mode"

This commit is contained in:
qctecmdr
2021-08-12 14:10:43 -07:00
committed by Gerrit - the friendly Code Review server
15 changed files with 89 additions and 61 deletions

View File

@@ -413,6 +413,7 @@ struct dsi_panel_cmd_set {
* @vdc: VDC compression configuration. * @vdc: VDC compression configuration.
* @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
*/ */
struct dsi_mode_info { struct dsi_mode_info {
u32 h_active; u32 h_active;
@@ -439,6 +440,7 @@ struct dsi_mode_info {
struct msm_display_vdc_info *vdc; struct msm_display_vdc_info *vdc;
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;
}; };
/** /**

View File

@@ -6838,6 +6838,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 i, start, end, rc = -EINVAL; int i, start, end, rc = -EINVAL;
int dsc_modes = 0, nondsc_modes = 0; int dsc_modes = 0, nondsc_modes = 0;
struct dsi_qsync_capabilities *qsync_caps;
if (!display || !out_modes) { if (!display || !out_modes) {
DSI_ERR("Invalid params\n"); DSI_ERR("Invalid params\n");
@@ -6868,6 +6869,7 @@ int dsi_display_get_modes(struct dsi_display *display,
goto error; goto error;
} }
qsync_caps = &(display->panel->qsync_caps);
dyn_clk_caps = &(display->panel->dyn_clk_caps); dyn_clk_caps = &(display->panel->dyn_clk_caps);
timing_mode_count = display->panel->num_timing_nodes; timing_mode_count = display->panel->num_timing_nodes;
@@ -6963,6 +6965,14 @@ int dsi_display_get_modes(struct dsi_display *display,
memcpy(sub_mode, &display_mode, sizeof(display_mode)); memcpy(sub_mode, &display_mode, sizeof(display_mode));
array_idx++; array_idx++;
/*
* Populate mode qsync min fps from panel min qsync fps dt property
* in video mode & in command mode where per mode qsync min fps is
* not defined.
*/
if (!sub_mode->timing.qsync_min_fps && qsync_caps->qsync_min_fps)
sub_mode->timing.qsync_min_fps = qsync_caps->qsync_min_fps;
if (!dfps_caps.dfps_support || !support_video_mode) if (!dfps_caps.dfps_support || !support_video_mode)
continue; continue;
@@ -6970,6 +6980,10 @@ int dsi_display_get_modes(struct dsi_display *display,
curr_refresh_rate = sub_mode->timing.refresh_rate; curr_refresh_rate = sub_mode->timing.refresh_rate;
sub_mode->timing.refresh_rate = dfps_caps.dfps_list[i]; sub_mode->timing.refresh_rate = dfps_caps.dfps_list[i];
/* Override with qsync min fps list in dfps usecases */
if (qsync_caps->qsync_min_fps && qsync_caps->qsync_min_fps_list_len)
sub_mode->timing.qsync_min_fps = qsync_caps->qsync_min_fps_list[i];
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;
@@ -7080,25 +7094,6 @@ int dsi_display_get_default_lms(void *dsi_display, u32 *num_lm)
return rc; 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_get_avr_step_req_fps(void *display_dsi, u32 mode_fps) 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_display *display = (struct dsi_display *)display_dsi;
@@ -8061,11 +8056,6 @@ static int dsi_display_qsync(struct dsi_display *display, bool enable)
int i; int i;
int rc = 0; int rc = 0;
if (!display->panel->qsync_caps.qsync_min_fps) {
DSI_ERR("%s:ERROR: qsync set, but no fps\n", __func__);
return 0;
}
mutex_lock(&display->display_lock); mutex_lock(&display->display_lock);
display_for_each_ctrl(i, display) { display_for_each_ctrl(i, display) {

View File

@@ -419,15 +419,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_qsync_min_fps() - get qsync min fps for given fps
* @display: Handle to display.
* @mode_fps: Fps value of current mode
*
* Return: Qsync min fps rate or -ve error code.
*/
int dsi_display_get_qsync_min_fps(void *dsi_display, u32 mode_fps);
/** /**
* dsi_display_get_avr_step_req_fps() - get avr step rate for given fps * dsi_display_get_avr_step_req_fps() - get avr step rate for given fps
* @display: Handle to display. * @display: Handle to display.

View File

@@ -614,6 +614,7 @@ int dsi_conn_get_mode_info(struct drm_connector *connector,
mode_info->mdp_transfer_time_us = mode_info->mdp_transfer_time_us =
dsi_mode->priv_info->mdp_transfer_time_us; dsi_mode->priv_info->mdp_transfer_time_us;
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;
memcpy(&mode_info->topology, &dsi_mode->priv_info->topology, memcpy(&mode_info->topology, &dsi_mode->priv_info->topology,
sizeof(struct msm_display_topology)); sizeof(struct msm_display_topology));
@@ -699,6 +700,32 @@ int dsi_conn_set_avr_step_info(struct dsi_panel *panel, void *info)
return 0; return 0;
} }
int dsi_conn_get_qsync_min_fps(void *display_dsi, struct drm_connector_state *conn_state)
{
struct dsi_display *display = (struct dsi_display *)display_dsi;
int rc = 0;
struct dsi_display_mode partial_dsi_mode, *dsi_mode;
struct msm_sub_mode new_sub_mode;
struct sde_connector_state *sde_conn_state;
struct drm_display_mode *drm_mode;
if (!display || !display->drm_conn || !conn_state)
return -EINVAL;
sde_conn_state = to_sde_connector_state(conn_state);
drm_mode = sde_conn_state->msm_mode.base;
convert_to_dsi_mode(drm_mode, &partial_dsi_mode);
new_sub_mode.dsc_mode = sde_connector_get_property(conn_state, CONNECTOR_PROP_DSC_MODE);
rc = dsi_display_find_mode(display, &partial_dsi_mode, &new_sub_mode, &dsi_mode);
if (rc) {
DSI_ERR("invalid mode\n");
return rc;
}
return dsi_mode->timing.qsync_min_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)
{ {
@@ -761,7 +788,7 @@ int dsi_conn_set_info_blob(struct drm_connector *connector,
} }
sde_kms_info_add_keystr(info, "qsync support", sde_kms_info_add_keystr(info, "qsync support",
panel->qsync_caps.qsync_min_fps ? panel->qsync_caps.qsync_support ?
"true" : "false"); "true" : "false");
if (panel->qsync_caps.qsync_min_fps) if (panel->qsync_caps.qsync_min_fps)
sde_kms_info_add_keyint(info, "qsync_fps", sde_kms_info_add_keyint(info, "qsync_fps",

View File

@@ -172,4 +172,12 @@ int dsi_conn_set_dyn_bit_clk(struct drm_connector *connector,
void dsi_conn_set_submode_blob_info(struct drm_connector *conn, void dsi_conn_set_submode_blob_info(struct drm_connector *conn,
void *info, void *display, struct drm_display_mode *drm_mode); void *info, void *display, struct drm_display_mode *drm_mode);
/**
* dsi_conn_get_qsync_min_fps() - get qsync min fps for given fps
* @display: Handle to display.
* @conn_state: Pointer to drm_connector_state structure
*
* Return: Qsync min fps rate or -ve error code.
*/
int dsi_conn_get_qsync_min_fps(void *dsi_display, struct drm_connector_state *conn_state);
#endif /* _DSI_DRM_H_ */ #endif /* _DSI_DRM_H_ */

View File

@@ -904,6 +904,13 @@ static int dsi_panel_parse_timing(struct dsi_mode_info *mode,
rc); rc);
goto error; goto error;
} }
rc = utils->read_u32(utils->data, "qcom,qsync-mode-min-refresh-rate", &mode->qsync_min_fps);
if (rc) {
DSI_DEBUG("qsync min 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);
@@ -1301,6 +1308,12 @@ static int dsi_panel_parse_qsync_caps(struct dsi_panel *panel,
struct dsi_parser_utils *utils = &panel->utils; struct dsi_parser_utils *utils = &panel->utils;
const char *name = panel->name; const char *name = panel->name;
qsync_caps->qsync_support = utils->read_bool(utils->data, "qcom,qsync-enable");
if (!qsync_caps->qsync_support) {
DSI_DEBUG("qsync feature not enabled\n");
goto error;
}
/** /**
* "mdss-dsi-qsync-min-refresh-rate" is defined in cmd mode and * "mdss-dsi-qsync-min-refresh-rate" is defined in cmd mode and
* video mode when there is only one qsync min fps present. * video mode when there is only one qsync min fps present.
@@ -1373,8 +1386,10 @@ static int dsi_panel_parse_qsync_caps(struct dsi_panel *panel,
qsync_support: qsync_support:
/* allow qsync support only if DFPS is with VFP approach */ /* allow qsync support only if DFPS is with VFP approach */
if ((panel->dfps_caps.dfps_support) && if ((panel->dfps_caps.dfps_support) &&
!(panel->dfps_caps.type == DSI_DFPS_IMMEDIATE_VFP)) !(panel->dfps_caps.type == DSI_DFPS_IMMEDIATE_VFP)) {
panel->qsync_caps.qsync_min_fps = 0; qsync_caps->qsync_support = false;
qsync_caps->qsync_min_fps = 0;
}
error: error:
if (rc < 0) { if (rc < 0) {

View File

@@ -89,7 +89,7 @@ struct dsi_dfps_capabilities {
}; };
struct dsi_qsync_capabilities { struct dsi_qsync_capabilities {
/* qsync disabled if qsync_min_fps = 0 */ bool qsync_support;
u32 qsync_min_fps; u32 qsync_min_fps;
u32 *qsync_min_fps_list; u32 *qsync_min_fps_list;
int qsync_min_fps_list_len; int qsync_min_fps_list_len;

View File

@@ -747,6 +747,7 @@ struct msm_dyn_clk_list {
* @allowed_mode_switches: bit mask to indicate supported mode switch. * @allowed_mode_switches: bit mask to indicate supported mode switch.
* @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
*/ */
struct msm_mode_info { struct msm_mode_info {
uint32_t frame_rate; uint32_t frame_rate;
@@ -765,6 +766,7 @@ struct msm_mode_info {
u32 allowed_mode_switches; u32 allowed_mode_switches;
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;
}; };
/** /**

View File

@@ -2769,6 +2769,7 @@ static int sde_connector_populate_mode_info(struct drm_connector *conn,
sde_kms_info_add_keystr(info, "topology", topo_name); sde_kms_info_add_keystr(info, "topology", topo_name);
} }
sde_kms_info_add_keyint(info, "qsync_min_fps", mode_info.qsync_min_fps);
sde_kms_info_add_keyint(info, "has_cwb_crop", sde_kms->catalog->has_cwb_crop); sde_kms_info_add_keyint(info, "has_cwb_crop", sde_kms->catalog->has_cwb_crop);
sde_kms_info_add_keyint(info, "has_dedicated_cwb_support", sde_kms_info_add_keyint(info, "has_dedicated_cwb_support",
sde_kms->catalog->has_dedicated_cwb_support); sde_kms->catalog->has_dedicated_cwb_support);
@@ -2986,7 +2987,8 @@ 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 (sde_kms->catalog->has_qsync && display_info->qsync_min_fps) { if (sde_kms->catalog->has_qsync && dsi_display && dsi_display->panel &&
dsi_display->panel->qsync_caps.qsync_support) {
msm_property_install_enum(&c_conn->property_info, msm_property_install_enum(&c_conn->property_info,
"qsync_mode", 0, 0, e_qsync_mode, "qsync_mode", 0, 0, e_qsync_mode,
ARRAY_SIZE(e_qsync_mode), 0, ARRAY_SIZE(e_qsync_mode), 0,

View File

@@ -400,10 +400,10 @@ struct sde_connector_ops {
/** /**
* get_qsync_min_fps - Get qsync min fps from qsync-min-fps-list * get_qsync_min_fps - Get qsync min fps from qsync-min-fps-list
* @display: Pointer to private display structure * @display: Pointer to private display structure
* @mode_fps: Fps value in dfps list * @conn_state: Pointer to drm_connector_state structure
* Returns: Qsync min fps value on success * Returns: Qsync min fps value on success
*/ */
int (*get_qsync_min_fps)(void *display, u32 mode_fps); int (*get_qsync_min_fps)(void *display, struct drm_connector_state *conn_state);
/** /**
* get_avr_step_req - Get the required avr_step for given fps rate * get_avr_step_req - Get the required avr_step for given fps rate

View File

@@ -1028,10 +1028,9 @@ static int _sde_encoder_atomic_check_reserve(struct drm_encoder *drm_enc,
return ret; return ret;
} }
static void _sde_encoder_get_qsync_fps_callback( static void _sde_encoder_get_qsync_fps_callback(struct drm_encoder *drm_enc,
struct drm_encoder *drm_enc, u32 *qsync_fps, u32 vrr_fps) u32 *qsync_fps, struct drm_connector_state *conn_state)
{ {
struct msm_display_info *disp_info;
struct sde_encoder_virt *sde_enc; struct sde_encoder_virt *sde_enc;
int rc = 0; int rc = 0;
struct sde_connector *sde_conn; struct sde_connector *sde_conn;
@@ -1046,25 +1045,17 @@ static void _sde_encoder_get_qsync_fps_callback(
} }
sde_enc = to_sde_encoder_virt(drm_enc); sde_enc = to_sde_encoder_virt(drm_enc);
disp_info = &sde_enc->disp_info;
*qsync_fps = disp_info->qsync_min_fps;
if (!disp_info->has_qsync_min_fps_list) { if (!sde_enc->cur_master) {
return;
} else if (!sde_enc->cur_master || !(disp_info->capabilities & MSM_DISPLAY_CAP_VID_MODE)) {
SDE_ERROR("invalid qsync settings %d\n", !sde_enc->cur_master); SDE_ERROR("invalid qsync settings %d\n", !sde_enc->cur_master);
return; return;
} }
/*
* If "dsi-supported-qsync-min-fps-list" is defined, get
* the qsync min fps corresponding to the fps in dfps list
*/
sde_conn = to_sde_connector(sde_enc->cur_master->connector); sde_conn = to_sde_connector(sde_enc->cur_master->connector);
if (sde_conn->ops.get_qsync_min_fps) if (sde_conn->ops.get_qsync_min_fps)
rc = sde_conn->ops.get_qsync_min_fps(sde_conn->display, vrr_fps); rc = sde_conn->ops.get_qsync_min_fps(sde_conn->display, conn_state);
if (rc <= 0) { if (rc < 0) {
SDE_ERROR("invalid qsync min fps %d\n", rc); SDE_ERROR("invalid qsync min fps %d\n", rc);
return; return;
} }
@@ -1101,7 +1092,8 @@ static int _sde_encoder_avr_step_check(struct sde_connector *sde_conn,
if (!step) if (!step)
return 0; return 0;
_sde_encoder_get_qsync_fps_callback(sde_conn_state->base.best_encoder, &min_fps, nom_fps); _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 || if (!min_fps || !nom_fps || step % nom_fps || step % min_fps || step < nom_fps ||
(vtotal * nom_fps) % step) { (vtotal * nom_fps) % step) {
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,

View File

@@ -82,7 +82,7 @@ struct sde_encoder_virt_ops {
void (*handle_frame_done)(struct drm_encoder *parent, void (*handle_frame_done)(struct drm_encoder *parent,
struct sde_encoder_phys *phys, u32 event); struct sde_encoder_phys *phys, u32 event);
void (*get_qsync_fps)(struct drm_encoder *parent, void (*get_qsync_fps)(struct drm_encoder *parent,
u32 *qsync_fps, u32 vrr_fps); u32 *qsync_fps, struct drm_connector_state *conn_state);
}; };
/** /**

View File

@@ -896,7 +896,7 @@ static int _get_tearcheck_threshold(struct sde_encoder_phys *phys_enc)
if (phys_enc->parent_ops.get_qsync_fps) if (phys_enc->parent_ops.get_qsync_fps)
phys_enc->parent_ops.get_qsync_fps( phys_enc->parent_ops.get_qsync_fps(
phys_enc->parent, &qsync_min_fps, 0); phys_enc->parent, &qsync_min_fps, conn->state);
if (!qsync_min_fps || !default_fps || !yres) { if (!qsync_min_fps || !default_fps || !yres) {
SDE_ERROR_CMDENC(cmd_enc, SDE_ERROR_CMDENC(cmd_enc,

View File

@@ -397,7 +397,7 @@ static void sde_encoder_phys_vid_setup_timing_engine(
bool is_split_link = false; bool is_split_link = false;
if (!phys_enc || !phys_enc->sde_kms || !phys_enc->hw_ctl || if (!phys_enc || !phys_enc->sde_kms || !phys_enc->hw_ctl ||
!phys_enc->hw_intf) { !phys_enc->hw_intf || !phys_enc->connector) {
SDE_ERROR("invalid encoder %d\n", !phys_enc); SDE_ERROR("invalid encoder %d\n", !phys_enc);
return; return;
} }
@@ -470,8 +470,7 @@ static void sde_encoder_phys_vid_setup_timing_engine(
exit: exit:
if (phys_enc->parent_ops.get_qsync_fps) if (phys_enc->parent_ops.get_qsync_fps)
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, phys_enc->connector->state);
drm_mode_vrefresh(&phys_enc->cached_mode));
/* only panels which support qsync will have a non-zero min fps */ /* only panels which support qsync will have a non-zero min fps */
if (qsync_min_fps) { if (qsync_min_fps) {

View File

@@ -1768,7 +1768,7 @@ static int _sde_kms_setup_displays(struct drm_device *dev,
.install_properties = NULL, .install_properties = NULL,
.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_display_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_req = dsi_display_get_avr_step_req_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,