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_width = 1920;
|
||||||
info->max_height = 1080;
|
info->max_height = 1080;
|
||||||
info->qsync_min_fps =
|
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;
|
info->poms_align_vsync = display->panel->poms_align_vsync;
|
||||||
|
|
||||||
switch (display->panel->panel_mode) {
|
switch (display->panel->panel_mode) {
|
||||||
@@ -6934,6 +6937,25 @@ 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_find_mode(struct dsi_display *display,
|
int dsi_display_find_mode(struct dsi_display *display,
|
||||||
const struct dsi_display_mode *cmp,
|
const struct dsi_display_mode *cmp,
|
||||||
struct dsi_display_mode **out_mode)
|
struct dsi_display_mode **out_mode)
|
||||||
@@ -7781,7 +7803,7 @@ 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_min_fps) {
|
if (!display->panel->qsync_caps.qsync_min_fps) {
|
||||||
DSI_ERR("%s:ERROR: qsync set, but no fps\n", __func__);
|
DSI_ERR("%s:ERROR: qsync set, but no fps\n", __func__);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -7809,7 +7831,7 @@ static int dsi_display_qsync(struct dsi_display *display, bool enable)
|
|||||||
}
|
}
|
||||||
|
|
||||||
exit:
|
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);
|
mutex_unlock(&display->display_lock);
|
||||||
return rc;
|
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);
|
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
|
* dsi_display_find_mode() - retrieve cached DSI mode given relevant params
|
||||||
* @display: Handle to display.
|
* @display: Handle to display.
|
||||||
|
@@ -628,14 +628,16 @@ int dsi_conn_set_info_blob(struct drm_connector *connector,
|
|||||||
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");
|
||||||
sde_kms_info_add_keystr(info, "qsync support",
|
sde_kms_info_add_keystr(info, "qsync support",
|
||||||
panel->qsync_min_fps ? "true" : "false");
|
panel->qsync_caps.qsync_min_fps ?
|
||||||
|
"true" : "false");
|
||||||
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");
|
||||||
sde_kms_info_add_keyint(info, "mdp_transfer_time_us",
|
sde_kms_info_add_keyint(info, "mdp_transfer_time_us",
|
||||||
mode_info->mdp_transfer_time_us);
|
mode_info->mdp_transfer_time_us);
|
||||||
sde_kms_info_add_keystr(info, "qsync support",
|
sde_kms_info_add_keystr(info, "qsync support",
|
||||||
panel->qsync_min_fps ? "true" : "false");
|
panel->qsync_caps.qsync_min_fps ?
|
||||||
|
"true" : "false");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
DSI_DEBUG("invalid panel type:%d\n", panel->panel_mode);
|
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)
|
struct device_node *of_node)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
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,
|
rc = of_property_read_u32(of_node,
|
||||||
"qcom,mdss-dsi-qsync-min-refresh-rate",
|
"qcom,mdss-dsi-qsync-min-refresh-rate",
|
||||||
&val);
|
&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",
|
DSI_DEBUG("[%s] qsync min fps not defined rc:%d\n",
|
||||||
panel->name, rc);
|
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;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3396,11 +3470,6 @@ struct dsi_panel *dsi_panel_get(struct device *parent,
|
|||||||
if (rc)
|
if (rc)
|
||||||
DSI_DEBUG("failed to parse qsync features, rc=%d\n", 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);
|
rc = dsi_panel_parse_dyn_clk_caps(panel);
|
||||||
if (rc)
|
if (rc)
|
||||||
DSI_ERR("failed to parse dynamic clk config, rc=%d\n", rc);
|
DSI_ERR("failed to parse dynamic clk config, rc=%d\n", rc);
|
||||||
|
@@ -86,6 +86,13 @@ struct dsi_dfps_capabilities {
|
|||||||
bool dfps_support;
|
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 {
|
struct dsi_dyn_clk_caps {
|
||||||
bool dyn_clk_support;
|
bool dyn_clk_support;
|
||||||
u32 *bit_clk_list;
|
u32 *bit_clk_list;
|
||||||
@@ -231,7 +238,7 @@ struct dsi_panel {
|
|||||||
|
|
||||||
bool panel_initialized;
|
bool panel_initialized;
|
||||||
bool te_using_watchdog_timer;
|
bool te_using_watchdog_timer;
|
||||||
u32 qsync_min_fps;
|
struct dsi_qsync_capabilities qsync_caps;
|
||||||
|
|
||||||
char dce_pps_cmd[DSI_CMD_PPS_SIZE];
|
char dce_pps_cmd[DSI_CMD_PPS_SIZE];
|
||||||
enum dsi_dms_mode dms_mode;
|
enum dsi_dms_mode dms_mode;
|
||||||
|
@@ -739,6 +739,7 @@ struct msm_resource_caps_info {
|
|||||||
* @poms_align_vsync: poms with vsync aligned
|
* @poms_align_vsync: poms with vsync aligned
|
||||||
* @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
|
||||||
* @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)
|
||||||
@@ -767,6 +768,8 @@ struct msm_display_info {
|
|||||||
struct msm_roi_caps roi_caps;
|
struct msm_roi_caps roi_caps;
|
||||||
|
|
||||||
uint32_t qsync_min_fps;
|
uint32_t qsync_min_fps;
|
||||||
|
bool has_qsync_min_fps_list;
|
||||||
|
|
||||||
uint32_t te_source;
|
uint32_t te_source;
|
||||||
|
|
||||||
uint32_t dsc_count;
|
uint32_t dsc_count;
|
||||||
|
@@ -374,6 +374,14 @@ struct sde_connector_ops {
|
|||||||
*/
|
*/
|
||||||
void (*set_allowed_mode_switch)(struct drm_connector *connector,
|
void (*set_allowed_mode_switch)(struct drm_connector *connector,
|
||||||
void *display);
|
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(
|
static void sde_encoder_get_qsync_fps_callback(
|
||||||
struct drm_encoder *drm_enc,
|
struct drm_encoder *drm_enc,
|
||||||
u32 *qsync_fps)
|
u32 *qsync_fps, u32 vrr_fps)
|
||||||
{
|
{
|
||||||
struct msm_display_info *disp_info;
|
struct msm_display_info *disp_info;
|
||||||
struct sde_encoder_virt *sde_enc;
|
struct sde_encoder_virt *sde_enc;
|
||||||
|
int rc = 0;
|
||||||
|
struct sde_connector *sde_conn;
|
||||||
|
|
||||||
if (!qsync_fps)
|
if (!qsync_fps)
|
||||||
return;
|
return;
|
||||||
@@ -3235,6 +3237,31 @@ 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;
|
disp_info = &sde_enc->disp_info;
|
||||||
*qsync_fps = disp_info->qsync_min_fps;
|
*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)
|
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,
|
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 *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)
|
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, 0);
|
||||||
|
|
||||||
if (!qsync_min_fps || !default_fps || !yres) {
|
if (!qsync_min_fps || !default_fps || !yres) {
|
||||||
SDE_ERROR_CMDENC(cmd_enc,
|
SDE_ERROR_CMDENC(cmd_enc,
|
||||||
|
@@ -470,7 +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, mode.vrefresh);
|
||||||
|
|
||||||
/* 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) {
|
||||||
|
@@ -1731,6 +1731,7 @@ static int _sde_kms_setup_displays(struct drm_device *dev,
|
|||||||
.cmd_receive = dsi_display_cmd_receive,
|
.cmd_receive = dsi_display_cmd_receive,
|
||||||
.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,
|
||||||
|
.get_qsync_min_fps = dsi_display_get_qsync_min_fps,
|
||||||
};
|
};
|
||||||
static const struct sde_connector_ops wb_ops = {
|
static const struct sde_connector_ops wb_ops = {
|
||||||
.post_init = sde_wb_connector_post_init,
|
.post_init = sde_wb_connector_post_init,
|
||||||
|
Reference in New Issue
Block a user