Merge "disp: msm: sde: add support for qsync min fps list"
This commit is contained in:

committed by
Gerrit - the friendly Code Review server

commit
68f4129cc6
@@ -6472,7 +6472,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;
|
||||
info->poms_align_vsync = display->panel->poms_align_vsync;
|
||||
|
||||
switch (display->panel->panel_mode) {
|
||||
@@ -6934,6 +6937,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)
|
||||
@@ -7781,7 +7803,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;
|
||||
}
|
||||
@@ -7809,7 +7831,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;
|
||||
}
|
||||
|
@@ -407,6 +407,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.
|
||||
|
@@ -628,14 +628,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);
|
||||
|
@@ -1219,8 +1219,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);
|
||||
@@ -1228,8 +1235,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;
|
||||
}
|
||||
|
||||
@@ -3396,11 +3470,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);
|
||||
|
@@ -86,6 +86,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;
|
||||
@@ -231,7 +238,7 @@ struct dsi_panel {
|
||||
|
||||
bool panel_initialized;
|
||||
bool te_using_watchdog_timer;
|
||||
u32 qsync_min_fps;
|
||||
struct dsi_qsync_capabilities qsync_caps;
|
||||
|
||||
char dce_pps_cmd[DSI_CMD_PPS_SIZE];
|
||||
enum dsi_dms_mode dms_mode;
|
||||
|
@@ -739,6 +739,7 @@ struct msm_resource_caps_info {
|
||||
* @poms_align_vsync: poms with vsync aligned
|
||||
* @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
|
||||
* @dsc_count: max dsc hw blocks used by display (only available
|
||||
* for dsi display)
|
||||
@@ -767,6 +768,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;
|
||||
|
||||
uint32_t dsc_count;
|
||||
|
@@ -374,6 +374,14 @@ struct sde_connector_ops {
|
||||
*/
|
||||
void (*set_allowed_mode_switch)(struct drm_connector *connector,
|
||||
void *display);
|
||||
|
||||
/**
|
||||
* 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);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@@ -3218,10 +3218,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;
|
||||
@@ -3235,6 +3237,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)
|
||||
|
@@ -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);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@@ -962,7 +962,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,
|
||||
|
@@ -470,7 +470,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) {
|
||||
|
@@ -1731,6 +1731,7 @@ static int _sde_kms_setup_displays(struct drm_device *dev,
|
||||
.cmd_receive = dsi_display_cmd_receive,
|
||||
.install_properties = NULL,
|
||||
.set_allowed_mode_switch = dsi_conn_set_allowed_mode_switch,
|
||||
.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,
|
||||
|
Reference in New Issue
Block a user