disp: msm: sde: add support for AVR_STEP feature
Add AVR step support so SW can trigger a late frame and instead of immediately triggering, HW will perform the update at the start of the next step interval. This allows for a fixed SW vsync timeline to be maintained in userland, eliminating the usual drift from the actual HW vsync caused by a late frame. This change adds AVR_STEP support via a DRM property. Change-Id: I4cf8a296989805f134c2165a3bed0b050bb09c96 Signed-off-by: Steve Cohen <cohens@codeaurora.org>
This commit is contained in:
@@ -223,6 +223,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,
|
||||||
|
|
||||||
/* total # of properties */
|
/* total # of properties */
|
||||||
CONNECTOR_PROP_COUNT
|
CONNECTOR_PROP_COUNT
|
||||||
|
@@ -697,7 +697,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;
|
u32 qsync_propval = 0, step_val = 0;
|
||||||
bool prop_dirty;
|
bool prop_dirty;
|
||||||
|
|
||||||
if (!connector)
|
if (!connector)
|
||||||
@@ -720,6 +720,17 @@ void sde_connector_set_qsync_params(struct drm_connector *connector)
|
|||||||
c_conn->qsync_mode = qsync_propval;
|
c_conn->qsync_mode = qsync_propval;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
prop_dirty = msm_property_is_dirty(&c_conn->property_info, &c_state->property_state,
|
||||||
|
CONNECTOR_PROP_AVR_STEP);
|
||||||
|
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->avr_step = step_val;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void sde_connector_complete_qsync_commit(struct drm_connector *conn,
|
void sde_connector_complete_qsync_commit(struct drm_connector *conn,
|
||||||
@@ -2870,11 +2881,16 @@ 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 && display_info->qsync_min_fps) {
|
||||||
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,
|
||||||
CONNECTOR_PROP_QSYNC_MODE);
|
CONNECTOR_PROP_QSYNC_MODE);
|
||||||
|
if (sde_kms->catalog->has_avr_step)
|
||||||
|
msm_property_install_range(&c_conn->property_info,
|
||||||
|
"avr_step", 0x0, 0, U32_MAX, 0,
|
||||||
|
CONNECTOR_PROP_AVR_STEP);
|
||||||
|
}
|
||||||
|
|
||||||
if (display_info->capabilities & MSM_DISPLAY_CAP_CMD_MODE)
|
if (display_info->capabilities & MSM_DISPLAY_CAP_CMD_MODE)
|
||||||
msm_property_install_enum(&c_conn->property_info,
|
msm_property_install_enum(&c_conn->property_info,
|
||||||
|
@@ -484,6 +484,7 @@ struct sde_connector_dyn_hdr_metadata {
|
|||||||
* @allow_bl_update: Flag to indicate if BL update is allowed currently or not
|
* @allow_bl_update: Flag to indicate if BL update is allowed currently 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
|
||||||
@@ -553,6 +554,7 @@ 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;
|
||||||
|
|
||||||
@@ -604,6 +606,13 @@ 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
|
||||||
|
@@ -995,6 +995,101 @@ static int _sde_encoder_atomic_check_reserve(struct drm_encoder *drm_enc,
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void _sde_encoder_get_qsync_fps_callback(
|
||||||
|
struct drm_encoder *drm_enc, 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;
|
||||||
|
|
||||||
|
*qsync_fps = 0;
|
||||||
|
if (!drm_enc) {
|
||||||
|
SDE_ERROR("invalid drm encoder\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
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);
|
||||||
|
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);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _sde_encoder_avr_step_check(struct sde_connector *sde_conn,
|
||||||
|
struct sde_connector_state *sde_conn_state, u32 step)
|
||||||
|
{
|
||||||
|
u32 nom_fps = drm_mode_vrefresh(sde_conn_state->msm_mode.base);
|
||||||
|
u32 min_fps;
|
||||||
|
u32 vtotal = sde_conn_state->msm_mode.base->vtotal;
|
||||||
|
|
||||||
|
if (!step)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
_sde_encoder_get_qsync_fps_callback(sde_conn_state->base.best_encoder, &min_fps, nom_fps);
|
||||||
|
if (!min_fps || !nom_fps || step % nom_fps || step % min_fps || step < nom_fps ||
|
||||||
|
(vtotal * nom_fps) % step) {
|
||||||
|
SDE_ERROR("invalid avr_step rate! nom:%u min:%u step:%u vtotal:%u\n", nom_fps,
|
||||||
|
min_fps, step, vtotal);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _sde_encoder_atomic_check_qsync(struct sde_connector *sde_conn,
|
||||||
|
struct sde_connector_state *sde_conn_state)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
u32 avr_step;
|
||||||
|
bool qsync_dirty, has_modeset;
|
||||||
|
struct drm_connector_state *conn_state = &sde_conn_state->base;
|
||||||
|
u32 qsync_mode = sde_connector_get_property(&sde_conn_state->base,
|
||||||
|
CONNECTOR_PROP_QSYNC_MODE);
|
||||||
|
|
||||||
|
has_modeset = sde_crtc_atomic_check_has_modeset(conn_state->state, conn_state->crtc);
|
||||||
|
qsync_dirty = msm_property_is_dirty(&sde_conn->property_info,
|
||||||
|
&sde_conn_state->property_state, CONNECTOR_PROP_QSYNC_MODE);
|
||||||
|
|
||||||
|
if (has_modeset && qsync_dirty &&
|
||||||
|
(msm_is_mode_seamless_poms(&sde_conn_state->msm_mode) ||
|
||||||
|
msm_is_mode_seamless_dms(&sde_conn_state->msm_mode) ||
|
||||||
|
msm_is_mode_seamless_dyn_clk(&sde_conn_state->msm_mode))) {
|
||||||
|
SDE_ERROR("invalid qsync update during modeset priv flag:%x\n",
|
||||||
|
sde_conn_state->msm_mode.private_flags);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
avr_step = sde_connector_get_property(conn_state, CONNECTOR_PROP_AVR_STEP);
|
||||||
|
if (qsync_dirty || (avr_step != sde_conn->avr_step) || (qsync_mode && has_modeset))
|
||||||
|
rc = _sde_encoder_avr_step_check(sde_conn, sde_conn_state, avr_step);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
static int sde_encoder_virt_atomic_check(
|
static int sde_encoder_virt_atomic_check(
|
||||||
struct drm_encoder *drm_enc, struct drm_crtc_state *crtc_state,
|
struct drm_encoder *drm_enc, struct drm_crtc_state *crtc_state,
|
||||||
struct drm_connector_state *conn_state)
|
struct drm_connector_state *conn_state)
|
||||||
@@ -1010,7 +1105,6 @@ static int sde_encoder_virt_atomic_check(
|
|||||||
enum sde_rm_topology_name top_name;
|
enum sde_rm_topology_name top_name;
|
||||||
struct msm_display_info *disp_info;
|
struct msm_display_info *disp_info;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
bool qsync_dirty = false, has_modeset = false;
|
|
||||||
|
|
||||||
if (!drm_enc || !crtc_state || !conn_state) {
|
if (!drm_enc || !crtc_state || !conn_state) {
|
||||||
SDE_ERROR("invalid arg(s), drm_enc %d, crtc/conn state %d/%d\n",
|
SDE_ERROR("invalid arg(s), drm_enc %d, crtc/conn state %d/%d\n",
|
||||||
@@ -1083,25 +1177,12 @@ static int sde_encoder_virt_atomic_check(
|
|||||||
|
|
||||||
drm_mode_set_crtcinfo(adj_mode, 0);
|
drm_mode_set_crtcinfo(adj_mode, 0);
|
||||||
|
|
||||||
has_modeset = sde_crtc_atomic_check_has_modeset(conn_state->state,
|
ret = _sde_encoder_atomic_check_qsync(sde_conn, sde_conn_state);
|
||||||
conn_state->crtc);
|
|
||||||
qsync_dirty = msm_property_is_dirty(&sde_conn->property_info,
|
|
||||||
&sde_conn_state->property_state,
|
|
||||||
CONNECTOR_PROP_QSYNC_MODE);
|
|
||||||
|
|
||||||
if (has_modeset && qsync_dirty &&
|
|
||||||
(msm_is_mode_seamless_poms(&sde_conn_state->msm_mode) ||
|
|
||||||
msm_is_mode_seamless_dms(&sde_conn_state->msm_mode) ||
|
|
||||||
msm_is_mode_seamless_dyn_clk(&sde_conn_state->msm_mode))) {
|
|
||||||
SDE_ERROR("invalid qsync update during modeset priv flag:%x\n",
|
|
||||||
sde_conn_state->msm_mode.private_flags);
|
|
||||||
return -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
SDE_EVT32(DRMID(drm_enc), adj_mode->flags,
|
SDE_EVT32(DRMID(drm_enc), adj_mode->flags,
|
||||||
sde_conn_state->msm_mode.private_flags,
|
sde_conn_state->msm_mode.private_flags,
|
||||||
old_top, drm_mode_vrefresh(adj_mode), adj_mode->hdisplay,
|
old_top, drm_mode_vrefresh(adj_mode), adj_mode->hdisplay,
|
||||||
adj_mode->vdisplay, adj_mode->htotal, adj_mode->vtotal);
|
adj_mode->vdisplay, adj_mode->htotal, adj_mode->vtotal, ret);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -3342,54 +3423,6 @@ static void sde_encoder_frame_done_callback(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sde_encoder_get_qsync_fps_callback(
|
|
||||||
struct drm_encoder *drm_enc,
|
|
||||||
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;
|
|
||||||
|
|
||||||
*qsync_fps = 0;
|
|
||||||
if (!drm_enc) {
|
|
||||||
SDE_ERROR("invalid drm encoder\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 %d\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)
|
||||||
{
|
{
|
||||||
struct sde_encoder_virt *sde_enc;
|
struct sde_encoder_virt *sde_enc;
|
||||||
@@ -4905,7 +4938,7 @@ static int sde_encoder_setup_display(struct sde_encoder_virt *sde_enc,
|
|||||||
sde_encoder_vblank_callback,
|
sde_encoder_vblank_callback,
|
||||||
sde_encoder_underrun_callback,
|
sde_encoder_underrun_callback,
|
||||||
sde_encoder_frame_done_callback,
|
sde_encoder_frame_done_callback,
|
||||||
sde_encoder_get_qsync_fps_callback,
|
_sde_encoder_get_qsync_fps_callback,
|
||||||
};
|
};
|
||||||
struct sde_enc_phys_init_params phys_params;
|
struct sde_enc_phys_init_params phys_params;
|
||||||
|
|
||||||
|
@@ -367,21 +367,20 @@ static void _sde_encoder_phys_vid_setup_avr(
|
|||||||
static void _sde_encoder_phys_vid_avr_ctrl(struct sde_encoder_phys *phys_enc)
|
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 =
|
struct sde_encoder_phys_vid *vid_enc = to_sde_encoder_phys_vid(phys_enc);
|
||||||
to_sde_encoder_phys_vid(phys_enc);
|
u32 avr_step_fps = sde_connector_get_avr_step(phys_enc->connector);
|
||||||
|
|
||||||
avr_params.avr_mode = sde_connector_get_qsync_mode(
|
memset(&avr_params, 0, sizeof(avr_params));
|
||||||
phys_enc->connector);
|
avr_params.avr_mode = sde_connector_get_qsync_mode(phys_enc->connector);
|
||||||
|
if (avr_step_fps)
|
||||||
|
avr_params.avr_step_lines = mult_frac(phys_enc->cached_mode.vtotal,
|
||||||
|
vid_enc->timing_params.vrefresh, 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->ops.avr_ctrl(vid_enc->base.hw_intf, &avr_params);
|
||||||
vid_enc->base.hw_intf,
|
|
||||||
&avr_params);
|
|
||||||
}
|
|
||||||
|
|
||||||
SDE_EVT32(DRMID(phys_enc->parent),
|
SDE_EVT32(DRMID(phys_enc->parent), phys_enc->hw_intf->idx - INTF_0,
|
||||||
phys_enc->hw_intf->idx - INTF_0,
|
avr_params.avr_mode, avr_params.avr_step_lines, avr_step_fps);
|
||||||
avr_params.avr_mode);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sde_encoder_phys_vid_setup_timing_engine(
|
static void sde_encoder_phys_vid_setup_timing_engine(
|
||||||
|
@@ -5070,6 +5070,7 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev)
|
|||||||
sde_cfg->has_fp16 = true;
|
sde_cfg->has_fp16 = true;
|
||||||
set_bit(SDE_MDP_PERIPH_TOP_0_REMOVED, &sde_cfg->mdp[0].features);
|
set_bit(SDE_MDP_PERIPH_TOP_0_REMOVED, &sde_cfg->mdp[0].features);
|
||||||
sde_cfg->has_precise_vsync_ts = true;
|
sde_cfg->has_precise_vsync_ts = true;
|
||||||
|
sde_cfg->has_avr_step = true;
|
||||||
sde_cfg->has_trusted_vm_support = true;
|
sde_cfg->has_trusted_vm_support = true;
|
||||||
} else if (IS_YUPIK_TARGET(hw_rev)) {
|
} else if (IS_YUPIK_TARGET(hw_rev)) {
|
||||||
sde_cfg->has_cwb_support = true;
|
sde_cfg->has_cwb_support = true;
|
||||||
|
@@ -1517,6 +1517,7 @@ struct sde_perf_cfg {
|
|||||||
* @has_3d_merge_reset Supports 3D merge reset
|
* @has_3d_merge_reset Supports 3D merge reset
|
||||||
* @has_decimation Supports decimation
|
* @has_decimation Supports decimation
|
||||||
* @has_trusted_vm_support Supported HW sharing with trusted VM
|
* @has_trusted_vm_support Supported HW sharing with trusted VM
|
||||||
|
* @has_avr_step Supports AVR with vsync alignment to a set step rate
|
||||||
* @rc_lm_flush_override Support Rounded Corner using layer mixer flush
|
* @rc_lm_flush_override Support Rounded Corner using layer mixer flush
|
||||||
* @has_mixer_combined_alpha Mixer has single register for FG & BG alpha
|
* @has_mixer_combined_alpha Mixer has single register for FG & BG alpha
|
||||||
* @vbif_disable_inner_outer_shareable VBIF requires disabling shareables
|
* @vbif_disable_inner_outer_shareable VBIF requires disabling shareables
|
||||||
@@ -1604,6 +1605,7 @@ struct sde_mdss_cfg {
|
|||||||
bool has_base_layer;
|
bool has_base_layer;
|
||||||
bool has_demura;
|
bool has_demura;
|
||||||
bool has_trusted_vm_support;
|
bool has_trusted_vm_support;
|
||||||
|
bool has_avr_step;
|
||||||
bool rc_lm_flush_override;
|
bool rc_lm_flush_override;
|
||||||
u32 demura_supported[SSPP_MAX][2];
|
u32 demura_supported[SSPP_MAX][2];
|
||||||
u32 qseed_sw_lib_rev;
|
u32 qseed_sw_lib_rev;
|
||||||
|
@@ -175,9 +175,10 @@ static void sde_hw_intf_avr_ctrl(struct sde_hw_intf *ctx,
|
|||||||
c = &ctx->hw;
|
c = &ctx->hw;
|
||||||
if (avr_params->avr_mode) {
|
if (avr_params->avr_mode) {
|
||||||
avr_ctrl = BIT(0);
|
avr_ctrl = BIT(0);
|
||||||
avr_mode =
|
avr_mode = (avr_params->avr_mode == SDE_RM_QSYNC_ONE_SHOT_MODE) ?
|
||||||
(avr_params->avr_mode == SDE_RM_QSYNC_ONE_SHOT_MODE) ?
|
(BIT(0) | BIT(8)) : 0x0;
|
||||||
(BIT(0) | BIT(8)) : 0x0;
|
if (avr_params->avr_step_lines)
|
||||||
|
avr_mode |= avr_params->avr_step_lines << 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDE_REG_WRITE(c, INTF_AVR_CONTROL, avr_ctrl);
|
SDE_REG_WRITE(c, INTF_AVR_CONTROL, avr_ctrl);
|
||||||
|
@@ -63,7 +63,8 @@ struct intf_tear_status {
|
|||||||
struct intf_avr_params {
|
struct intf_avr_params {
|
||||||
u32 default_fps;
|
u32 default_fps;
|
||||||
u32 min_fps;
|
u32 min_fps;
|
||||||
u32 avr_mode; /* 0 - disable, 1 - continuous, 2 - one-shot */
|
u32 avr_mode; /* one of enum @sde_rm_qsync_modes */
|
||||||
|
u32 avr_step_lines; /* 0 or 1 means disabled */
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user