disp: msm: sde: compute timeouts based on refresh rate
Current timeout values in sde driver for vblank, kickoff and frame complete timeouts are fixed and can be much lower than a vsync incase of low refresh rate display. Compute timeouts based on refresh rate for low refresh rate displays. Change-Id: I9dda41feb15446de7451824e185321de421ad575 Signed-off-by: Prabhanjan Kandula <pkandula@codeaurora.org>
This commit is contained in:
@@ -2681,6 +2681,25 @@ u32 sde_crtc_get_dfps_maxfps(struct drm_crtc *crtc)
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct drm_encoder *sde_crtc_get_src_encoder_of_clone(struct drm_crtc *crtc)
|
||||
{
|
||||
struct drm_encoder *enc;
|
||||
struct sde_crtc *sde_crtc;
|
||||
|
||||
if (!crtc || !crtc->dev)
|
||||
return NULL;
|
||||
|
||||
sde_crtc = to_sde_crtc(crtc);
|
||||
drm_for_each_encoder_mask(enc, crtc->dev, sde_crtc->cached_encoder_mask) {
|
||||
if (sde_encoder_in_clone_mode(enc))
|
||||
continue;
|
||||
|
||||
return enc;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void sde_crtc_vblank_cb(void *data, ktime_t ts)
|
||||
{
|
||||
struct drm_crtc *crtc = (struct drm_crtc *)data;
|
||||
|
@@ -1057,4 +1057,10 @@ void _sde_crtc_clear_dim_layers_v1(struct drm_crtc_state *state);
|
||||
*/
|
||||
void sde_crtc_cancel_delayed_work(struct drm_crtc *crtc);
|
||||
|
||||
/*
|
||||
* sde_crtc_get_src_encoder_of_clone- find source encoder of a clone mode encoder
|
||||
* @cstate: Pointer to DRM crtc object
|
||||
*/
|
||||
struct drm_encoder *sde_crtc_get_src_encoder_of_clone(struct drm_crtc *crtc);
|
||||
|
||||
#endif /* _SDE_CRTC_H_ */
|
||||
|
@@ -61,7 +61,7 @@
|
||||
(p) ? ((p)->hw_pp ? (p)->hw_pp->idx - PINGPONG_0 : -1) : -1, \
|
||||
##__VA_ARGS__)
|
||||
|
||||
|
||||
#define SEC_TO_MILLI_SEC 1000
|
||||
|
||||
#define MISR_BUFF_SIZE 256
|
||||
|
||||
@@ -4488,6 +4488,32 @@ void sde_encoder_get_transfer_time(struct drm_encoder *drm_enc,
|
||||
*transfer_time_us = info->mdp_transfer_time_us;
|
||||
}
|
||||
|
||||
u32 sde_encoder_helper_get_kickoff_timeout_ms(struct drm_encoder *drm_enc)
|
||||
{
|
||||
struct drm_encoder *src_enc = drm_enc;
|
||||
struct sde_encoder_virt *sde_enc;
|
||||
u32 fps;
|
||||
|
||||
if (!drm_enc) {
|
||||
SDE_ERROR("invalid encoder\n");
|
||||
return DEFAULT_KICKOFF_TIMEOUT_MS;
|
||||
}
|
||||
|
||||
if (sde_encoder_in_clone_mode(drm_enc))
|
||||
src_enc = sde_crtc_get_src_encoder_of_clone(drm_enc->crtc);
|
||||
|
||||
if (!src_enc)
|
||||
return DEFAULT_KICKOFF_TIMEOUT_MS;
|
||||
|
||||
sde_enc = to_sde_encoder_virt(src_enc);
|
||||
fps = sde_enc->mode_info.frame_rate;
|
||||
|
||||
if (!fps || fps >= DEFAULT_TIMEOUT_FPS_THRESHOLD)
|
||||
return DEFAULT_KICKOFF_TIMEOUT_MS;
|
||||
else
|
||||
return (SEC_TO_MILLI_SEC / fps) * 2;
|
||||
}
|
||||
|
||||
int sde_encoder_get_avr_status(struct drm_encoder *drm_enc)
|
||||
{
|
||||
struct sde_encoder_virt *sde_enc;
|
||||
|
@@ -51,6 +51,9 @@
|
||||
#define IDLE_POWERCOLLAPSE_DURATION (66 - 16/2)
|
||||
#define IDLE_POWERCOLLAPSE_IN_EARLY_WAKEUP (200 - 16/2)
|
||||
|
||||
/* below this fps limit, timeouts are adjusted based on fps */
|
||||
#define DEFAULT_TIMEOUT_FPS_THRESHOLD 24
|
||||
|
||||
/**
|
||||
* Encoder functions and data types
|
||||
* @intfs: Interfaces this encoder is using, INTF_MODE_NONE if unused
|
||||
|
@@ -22,8 +22,7 @@
|
||||
#define SDE_ENCODER_NAME_MAX 16
|
||||
|
||||
/* wait for at most 2 vsync for lowest refresh rate (24hz) */
|
||||
#define KICKOFF_TIMEOUT_MS 84
|
||||
#define KICKOFF_TIMEOUT_JIFFIES msecs_to_jiffies(KICKOFF_TIMEOUT_MS)
|
||||
#define DEFAULT_KICKOFF_TIMEOUT_MS 84
|
||||
|
||||
#define MAX_TE_PROFILE_COUNT 5
|
||||
/**
|
||||
@@ -286,6 +285,7 @@ struct sde_encoder_irq {
|
||||
* @pending_retire_fence_cnt: Atomic counter tracking the pending retire
|
||||
* fences that have to be signalled.
|
||||
* @pending_kickoff_wq: Wait queue for blocking until kickoff completes
|
||||
* @kickoff_timeout_ms: kickoff timeout in mill seconds
|
||||
* @irq: IRQ tracking structures
|
||||
* @has_intf_te: Interface TE configuration support
|
||||
* @cont_splash_enabled: Variable to store continuous splash settings.
|
||||
@@ -332,6 +332,7 @@ struct sde_encoder_phys {
|
||||
atomic_t pending_kickoff_cnt;
|
||||
atomic_t pending_retire_fence_cnt;
|
||||
wait_queue_head_t pending_kickoff_wq;
|
||||
u32 kickoff_timeout_ms;
|
||||
struct sde_encoder_irq irq[INTR_IDX_MAX];
|
||||
bool has_intf_te;
|
||||
bool cont_splash_enabled;
|
||||
@@ -539,6 +540,13 @@ void sde_encoder_phys_setup_cdm(struct sde_encoder_phys *phys_enc,
|
||||
void sde_encoder_helper_get_pp_line_count(struct drm_encoder *drm_enc,
|
||||
struct sde_hw_pp_vsync_info *info);
|
||||
|
||||
/**
|
||||
* sde_encoder_helper_get_kickoff_timeout_ms- get the kickoff timeout value based on fps
|
||||
* @drm_enc: Pointer to drm encoder structure
|
||||
* Returns: Kickoff timeout in milli seconds
|
||||
*/
|
||||
u32 sde_encoder_helper_get_kickoff_timeout_ms(struct drm_encoder *drm_enc);
|
||||
|
||||
/**
|
||||
* sde_encoder_helper_trigger_flush - control flush helper function
|
||||
* This helper function may be optionally specified by physical
|
||||
|
@@ -37,11 +37,13 @@
|
||||
#define AUTOREFRESH_SEQ2_POLL_TIMEOUT 1000000
|
||||
|
||||
static inline int _sde_encoder_phys_cmd_get_idle_timeout(
|
||||
struct sde_encoder_phys_cmd *cmd_enc)
|
||||
struct sde_encoder_phys *phys_enc)
|
||||
{
|
||||
u32 timeout = phys_enc->kickoff_timeout_ms;
|
||||
struct sde_encoder_phys_cmd *cmd_enc = to_sde_encoder_phys_cmd(phys_enc);
|
||||
|
||||
return cmd_enc->autorefresh.cfg.frame_count ?
|
||||
cmd_enc->autorefresh.cfg.frame_count *
|
||||
KICKOFF_TIMEOUT_MS : KICKOFF_TIMEOUT_MS;
|
||||
cmd_enc->autorefresh.cfg.frame_count * timeout : timeout;
|
||||
}
|
||||
|
||||
static inline bool sde_encoder_phys_cmd_is_master(
|
||||
@@ -450,6 +452,9 @@ static void sde_encoder_phys_cmd_mode_set(
|
||||
}
|
||||
|
||||
_sde_encoder_phys_cmd_setup_irq_hw_idx(phys_enc);
|
||||
|
||||
phys_enc->kickoff_timeout_ms =
|
||||
sde_encoder_helper_get_kickoff_timeout_ms(phys_enc->parent);
|
||||
}
|
||||
|
||||
static int _sde_encoder_phys_cmd_handle_ppdone_timeout(
|
||||
@@ -708,7 +713,7 @@ static int _sde_encoder_phys_cmd_wait_for_idle(
|
||||
|
||||
wait_info.wq = &phys_enc->pending_kickoff_wq;
|
||||
wait_info.atomic_cnt = &phys_enc->pending_kickoff_cnt;
|
||||
wait_info.timeout_ms = KICKOFF_TIMEOUT_MS;
|
||||
wait_info.timeout_ms = phys_enc->kickoff_timeout_ms;
|
||||
|
||||
/* slave encoder doesn't enable for ppsplit */
|
||||
if (_sde_encoder_phys_is_ppsplit_slave(phys_enc))
|
||||
@@ -748,7 +753,7 @@ static int _sde_encoder_phys_cmd_wait_for_autorefresh_done(
|
||||
|
||||
wait_info.wq = &cmd_enc->autorefresh.kickoff_wq;
|
||||
wait_info.atomic_cnt = &cmd_enc->autorefresh.kickoff_cnt;
|
||||
wait_info.timeout_ms = _sde_encoder_phys_cmd_get_idle_timeout(cmd_enc);
|
||||
wait_info.timeout_ms = _sde_encoder_phys_cmd_get_idle_timeout(phys_enc);
|
||||
|
||||
/* wait for autorefresh kickoff to start */
|
||||
ret = sde_encoder_helper_wait_for_irq(phys_enc,
|
||||
@@ -1427,11 +1432,11 @@ static int _sde_encoder_phys_cmd_wait_for_wr_ptr(
|
||||
}
|
||||
ctl = phys_enc->hw_ctl;
|
||||
c_conn = to_sde_connector(phys_enc->connector);
|
||||
timeout_ms = KICKOFF_TIMEOUT_MS;
|
||||
timeout_ms = phys_enc->kickoff_timeout_ms;
|
||||
|
||||
if (c_conn->lp_mode == SDE_MODE_DPMS_LP1 ||
|
||||
c_conn->lp_mode == SDE_MODE_DPMS_LP2)
|
||||
timeout_ms = (KICKOFF_TIMEOUT_MS) * 2;
|
||||
timeout_ms = timeout_ms * 2;
|
||||
|
||||
wait_info.wq = &phys_enc->pending_kickoff_wq;
|
||||
wait_info.atomic_cnt = &phys_enc->pending_retire_fence_cnt;
|
||||
@@ -1649,7 +1654,7 @@ static int sde_encoder_phys_cmd_wait_for_vblank(
|
||||
|
||||
wait_info.wq = &cmd_enc->pending_vblank_wq;
|
||||
wait_info.atomic_cnt = &cmd_enc->pending_vblank_cnt;
|
||||
wait_info.timeout_ms = _sde_encoder_phys_cmd_get_idle_timeout(cmd_enc);
|
||||
wait_info.timeout_ms = _sde_encoder_phys_cmd_get_idle_timeout(phys_enc);
|
||||
|
||||
atomic_inc(&cmd_enc->pending_vblank_cnt);
|
||||
|
||||
@@ -1696,6 +1701,7 @@ static void _sde_encoder_autorefresh_disable_seq1(
|
||||
struct sde_encoder_phys *phys_enc)
|
||||
{
|
||||
int trial = 0;
|
||||
u32 timeout_ms = phys_enc->kickoff_timeout_ms;
|
||||
struct sde_encoder_phys_cmd *cmd_enc =
|
||||
to_sde_encoder_phys_cmd(phys_enc);
|
||||
|
||||
@@ -1712,7 +1718,7 @@ static void _sde_encoder_autorefresh_disable_seq1(
|
||||
do {
|
||||
udelay(AUTOREFRESH_SEQ1_POLL_TIME);
|
||||
if ((trial * AUTOREFRESH_SEQ1_POLL_TIME)
|
||||
> (KICKOFF_TIMEOUT_MS * USEC_PER_MSEC)) {
|
||||
> (timeout_ms * USEC_PER_MSEC)) {
|
||||
SDE_ERROR_CMDENC(cmd_enc,
|
||||
"disable autorefresh failed\n");
|
||||
|
||||
@@ -1954,6 +1960,7 @@ struct sde_encoder_phys *sde_encoder_phys_cmd_init(
|
||||
phys_enc->vblank_ctl_lock = p->vblank_ctl_lock;
|
||||
cmd_enc->stream_sel = 0;
|
||||
phys_enc->enable_state = SDE_ENC_DISABLED;
|
||||
phys_enc->kickoff_timeout_ms = DEFAULT_KICKOFF_TIMEOUT_MS;
|
||||
sde_encoder_phys_cmd_init_ops(&phys_enc->ops);
|
||||
phys_enc->comp_type = p->comp_type;
|
||||
|
||||
|
@@ -657,6 +657,9 @@ static void sde_encoder_phys_vid_mode_set(
|
||||
}
|
||||
|
||||
_sde_encoder_phys_vid_setup_irq_hw_idx(phys_enc);
|
||||
|
||||
phys_enc->kickoff_timeout_ms =
|
||||
sde_encoder_helper_get_kickoff_timeout_ms(phys_enc->parent);
|
||||
}
|
||||
|
||||
static int sde_encoder_phys_vid_control_vblank_irq(
|
||||
@@ -889,7 +892,7 @@ static int _sde_encoder_phys_vid_wait_for_vblank(
|
||||
|
||||
wait_info.wq = &phys_enc->pending_kickoff_wq;
|
||||
wait_info.atomic_cnt = &phys_enc->pending_kickoff_cnt;
|
||||
wait_info.timeout_ms = KICKOFF_TIMEOUT_MS;
|
||||
wait_info.timeout_ms = phys_enc->kickoff_timeout_ms;
|
||||
|
||||
/* Wait for kickoff to complete */
|
||||
ret = sde_encoder_helper_wait_for_irq(phys_enc, INTR_IDX_VSYNC,
|
||||
@@ -1361,6 +1364,7 @@ struct sde_encoder_phys *sde_encoder_phys_vid_init(
|
||||
phys_enc->enc_spinlock = p->enc_spinlock;
|
||||
phys_enc->vblank_ctl_lock = p->vblank_ctl_lock;
|
||||
phys_enc->comp_type = p->comp_type;
|
||||
phys_enc->kickoff_timeout_ms = DEFAULT_KICKOFF_TIMEOUT_MS;
|
||||
for (i = 0; i < INTR_IDX_MAX; i++) {
|
||||
irq = &phys_enc->irq[i];
|
||||
INIT_LIST_HEAD(&irq->cb.list);
|
||||
|
@@ -1402,6 +1402,9 @@ static void sde_encoder_phys_wb_mode_set(
|
||||
PTR_ERR(phys_enc->hw_cdm));
|
||||
phys_enc->hw_cdm = NULL;
|
||||
}
|
||||
|
||||
phys_enc->kickoff_timeout_ms =
|
||||
sde_encoder_helper_get_kickoff_timeout_ms(phys_enc->parent);
|
||||
}
|
||||
|
||||
static int sde_encoder_phys_wb_frame_timeout(struct sde_encoder_phys *phys_enc)
|
||||
@@ -1508,7 +1511,7 @@ static int _sde_encoder_phys_wb_wait_for_commit_done(
|
||||
wait_info.wq = &phys_enc->pending_kickoff_wq;
|
||||
wait_info.atomic_cnt = &phys_enc->pending_retire_fence_cnt;
|
||||
wait_info.timeout_ms = max_t(u32, wb_enc->wbdone_timeout,
|
||||
KICKOFF_TIMEOUT_MS);
|
||||
phys_enc->kickoff_timeout_ms);
|
||||
rc = sde_encoder_helper_wait_for_irq(phys_enc, INTR_IDX_WB_DONE,
|
||||
&wait_info);
|
||||
if (rc == -ETIMEDOUT && _sde_encoder_phys_wb_is_idle(phys_enc)) {
|
||||
@@ -2037,9 +2040,9 @@ struct sde_encoder_phys *sde_encoder_phys_wb_init(
|
||||
ret = -ENOMEM;
|
||||
goto fail_alloc;
|
||||
}
|
||||
wb_enc->wbdone_timeout = KICKOFF_TIMEOUT_MS;
|
||||
|
||||
phys_enc = &wb_enc->base;
|
||||
phys_enc->kickoff_timeout_ms = DEFAULT_KICKOFF_TIMEOUT_MS;
|
||||
|
||||
if (p->sde_kms->vbif[VBIF_NRT]) {
|
||||
wb_enc->aspace[SDE_IOMMU_DOMAIN_UNSECURE] =
|
||||
|
Reference in New Issue
Block a user