disp: msm: sde: allow qsync support along with VRR
Allow Qsync and VRR features to be supported independently by display driver. Restrict the feature availability in same composition cycle. Change-Id: I696eb72a2b4f9451e142ffdc5acccc8987c36b6d Signed-off-by: Kalyan Thota <kalyant@codeaurora.org> Signed-off-by: Jayaprakash <jmadiset@codeaurora.org>
This commit is contained in:
@@ -3257,13 +3257,14 @@ struct dsi_panel *dsi_panel_get(struct device *parent,
|
|||||||
if (rc)
|
if (rc)
|
||||||
DSI_ERR("failed to parse dfps configuration, rc=%d\n", rc);
|
DSI_ERR("failed to parse dfps configuration, rc=%d\n", rc);
|
||||||
|
|
||||||
if (!(panel->dfps_caps.dfps_support)) {
|
rc = dsi_panel_parse_qsync_caps(panel, of_node);
|
||||||
/* qsync and dfps are mutually exclusive features */
|
if (rc)
|
||||||
rc = dsi_panel_parse_qsync_caps(panel, of_node);
|
DSI_DEBUG("failed to parse qsync features, rc=%d\n", rc);
|
||||||
if (rc)
|
|
||||||
DSI_DEBUG("failed to parse qsync features, rc=%d\n",
|
/* allow qsync support only if DFPS is with VFP approach */
|
||||||
rc);
|
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)
|
||||||
|
@@ -621,17 +621,24 @@ void sde_connector_set_colorspace(struct sde_connector *c_conn)
|
|||||||
|
|
||||||
void sde_connector_set_qsync_params(struct drm_connector *connector)
|
void sde_connector_set_qsync_params(struct drm_connector *connector)
|
||||||
{
|
{
|
||||||
struct sde_connector *c_conn = to_sde_connector(connector);
|
struct sde_connector *c_conn;
|
||||||
u32 qsync_propval;
|
struct sde_connector_state *c_state;
|
||||||
|
u32 qsync_propval = 0;
|
||||||
|
bool prop_dirty;
|
||||||
|
|
||||||
if (!connector)
|
if (!connector)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
c_conn = to_sde_connector(connector);
|
||||||
|
c_state = to_sde_connector_state(connector->state);
|
||||||
c_conn->qsync_updated = false;
|
c_conn->qsync_updated = false;
|
||||||
qsync_propval = sde_connector_get_property(c_conn->base.state,
|
|
||||||
CONNECTOR_PROP_QSYNC_MODE);
|
|
||||||
|
|
||||||
if (qsync_propval != c_conn->qsync_mode) {
|
prop_dirty = msm_property_is_dirty(&c_conn->property_info,
|
||||||
|
&c_state->property_state,
|
||||||
|
CONNECTOR_PROP_QSYNC_MODE);
|
||||||
|
if (prop_dirty) {
|
||||||
|
qsync_propval = sde_connector_get_property(c_conn->base.state,
|
||||||
|
CONNECTOR_PROP_QSYNC_MODE);
|
||||||
SDE_DEBUG("updated qsync mode %d -> %d\n", c_conn->qsync_mode,
|
SDE_DEBUG("updated qsync mode %d -> %d\n", c_conn->qsync_mode,
|
||||||
qsync_propval);
|
qsync_propval);
|
||||||
c_conn->qsync_updated = true;
|
c_conn->qsync_updated = true;
|
||||||
@@ -1376,6 +1383,10 @@ static int sde_connector_atomic_set_property(struct drm_connector *connector,
|
|||||||
if (rc)
|
if (rc)
|
||||||
SDE_ERROR_CONN(c_conn, "cannot set hdr info %d\n", rc);
|
SDE_ERROR_CONN(c_conn, "cannot set hdr info %d\n", rc);
|
||||||
break;
|
break;
|
||||||
|
case CONNECTOR_PROP_QSYNC_MODE:
|
||||||
|
msm_property_set_dirty(&c_conn->property_info,
|
||||||
|
&c_state->property_state, idx);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -2027,13 +2038,33 @@ static int sde_connector_atomic_check(struct drm_connector *connector,
|
|||||||
struct drm_connector_state *new_conn_state)
|
struct drm_connector_state *new_conn_state)
|
||||||
{
|
{
|
||||||
struct sde_connector *c_conn;
|
struct sde_connector *c_conn;
|
||||||
|
struct sde_connector_state *c_state;
|
||||||
|
bool qsync_dirty = false, has_modeset = false;
|
||||||
|
|
||||||
if (!connector) {
|
if (!connector) {
|
||||||
SDE_ERROR("invalid connector\n");
|
SDE_ERROR("invalid connector\n");
|
||||||
return 0;
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!new_conn_state) {
|
||||||
|
SDE_ERROR("invalid connector state\n");
|
||||||
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
c_conn = to_sde_connector(connector);
|
c_conn = to_sde_connector(connector);
|
||||||
|
c_state = to_sde_connector_state(new_conn_state);
|
||||||
|
|
||||||
|
has_modeset = sde_crtc_atomic_check_has_modeset(new_conn_state->state,
|
||||||
|
new_conn_state->crtc);
|
||||||
|
qsync_dirty = msm_property_is_dirty(&c_conn->property_info,
|
||||||
|
&c_state->property_state,
|
||||||
|
CONNECTOR_PROP_QSYNC_MODE);
|
||||||
|
|
||||||
|
SDE_DEBUG("has_modeset %d qsync_dirty %d\n", has_modeset, qsync_dirty);
|
||||||
|
if (has_modeset && qsync_dirty) {
|
||||||
|
SDE_ERROR("invalid qsync update during modeset\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
if (c_conn->ops.atomic_check)
|
if (c_conn->ops.atomic_check)
|
||||||
return c_conn->ops.atomic_check(connector,
|
return c_conn->ops.atomic_check(connector,
|
||||||
|
@@ -714,6 +714,25 @@ static inline int sde_crtc_get_secure_level(struct drm_crtc *crtc,
|
|||||||
CRTC_PROP_SECURITY_LEVEL);
|
CRTC_PROP_SECURITY_LEVEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** sde_crtc_atomic_check_has_modeset - checks if the new_crtc_state in the
|
||||||
|
* drm_atomic_state has a modeset
|
||||||
|
* @state : pointer to drm_atomic_state
|
||||||
|
* @crtc : Pointer to drm crtc structure
|
||||||
|
* Returns true if crtc has modeset
|
||||||
|
*/
|
||||||
|
static inline bool sde_crtc_atomic_check_has_modeset(
|
||||||
|
struct drm_atomic_state *state, struct drm_crtc *crtc)
|
||||||
|
{
|
||||||
|
struct drm_crtc_state *crtc_state;
|
||||||
|
|
||||||
|
if (!state || !crtc)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
crtc_state = drm_atomic_get_new_crtc_state(state,
|
||||||
|
crtc);
|
||||||
|
return (crtc_state && drm_atomic_crtc_needs_modeset(crtc_state));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sde_crtc_get_secure_transition - determines the operations to be
|
* sde_crtc_get_secure_transition - determines the operations to be
|
||||||
* performed before transitioning to secure state
|
* performed before transitioning to secure state
|
||||||
|
@@ -332,7 +332,7 @@ static void _sde_encoder_phys_vid_setup_avr(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (qsync_min_fps >= default_fps) {
|
if (qsync_min_fps > default_fps) {
|
||||||
SDE_ERROR_VIDENC(vid_enc,
|
SDE_ERROR_VIDENC(vid_enc,
|
||||||
"qsync fps %d must be less than default %d\n",
|
"qsync fps %d must be less than default %d\n",
|
||||||
qsync_min_fps, default_fps);
|
qsync_min_fps, default_fps);
|
||||||
|
@@ -129,7 +129,7 @@ static int sde_hw_intf_avr_setup(struct sde_hw_intf *ctx,
|
|||||||
u32 min_fps, default_fps, diff_fps;
|
u32 min_fps, default_fps, diff_fps;
|
||||||
u32 vsync_period_slow;
|
u32 vsync_period_slow;
|
||||||
u32 avr_vtotal;
|
u32 avr_vtotal;
|
||||||
u32 add_porches;
|
u32 add_porches = 0;
|
||||||
|
|
||||||
if (!ctx || !params || !avr_params) {
|
if (!ctx || !params || !avr_params) {
|
||||||
SDE_ERROR("invalid input parameter(s)\n");
|
SDE_ERROR("invalid input parameter(s)\n");
|
||||||
@@ -146,7 +146,10 @@ static int sde_hw_intf_avr_setup(struct sde_hw_intf *ctx,
|
|||||||
vsync_period = params->vsync_pulse_width +
|
vsync_period = params->vsync_pulse_width +
|
||||||
params->v_back_porch + params->height +
|
params->v_back_porch + params->height +
|
||||||
params->v_front_porch;
|
params->v_front_porch;
|
||||||
add_porches = mult_frac(vsync_period, diff_fps, min_fps);
|
|
||||||
|
if (diff_fps)
|
||||||
|
add_porches = mult_frac(vsync_period, diff_fps, min_fps);
|
||||||
|
|
||||||
vsync_period_slow = vsync_period + add_porches;
|
vsync_period_slow = vsync_period + add_porches;
|
||||||
avr_vtotal = vsync_period_slow * hsync_period;
|
avr_vtotal = vsync_period_slow * hsync_period;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user