Merge "disp: msm: sde: compute timeouts based on refresh rate"
This commit is contained in:

committed by
Gerrit - the friendly Code Review server

commit
4ec64c1672
@@ -2681,6 +2681,25 @@ u32 sde_crtc_get_dfps_maxfps(struct drm_crtc *crtc)
|
|||||||
return 0;
|
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)
|
static void sde_crtc_vblank_cb(void *data, ktime_t ts)
|
||||||
{
|
{
|
||||||
struct drm_crtc *crtc = (struct drm_crtc *)data;
|
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);
|
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_ */
|
#endif /* _SDE_CRTC_H_ */
|
||||||
|
@@ -61,7 +61,7 @@
|
|||||||
(p) ? ((p)->hw_pp ? (p)->hw_pp->idx - PINGPONG_0 : -1) : -1, \
|
(p) ? ((p)->hw_pp ? (p)->hw_pp->idx - PINGPONG_0 : -1) : -1, \
|
||||||
##__VA_ARGS__)
|
##__VA_ARGS__)
|
||||||
|
|
||||||
|
#define SEC_TO_MILLI_SEC 1000
|
||||||
|
|
||||||
#define MISR_BUFF_SIZE 256
|
#define MISR_BUFF_SIZE 256
|
||||||
|
|
||||||
@@ -4482,6 +4482,32 @@ void sde_encoder_get_transfer_time(struct drm_encoder *drm_enc,
|
|||||||
*transfer_time_us = info->mdp_transfer_time_us;
|
*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)
|
int sde_encoder_get_avr_status(struct drm_encoder *drm_enc)
|
||||||
{
|
{
|
||||||
struct sde_encoder_virt *sde_enc;
|
struct sde_encoder_virt *sde_enc;
|
||||||
|
@@ -51,6 +51,9 @@
|
|||||||
#define IDLE_POWERCOLLAPSE_DURATION (66 - 16/2)
|
#define IDLE_POWERCOLLAPSE_DURATION (66 - 16/2)
|
||||||
#define IDLE_POWERCOLLAPSE_IN_EARLY_WAKEUP (200 - 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
|
* Encoder functions and data types
|
||||||
* @intfs: Interfaces this encoder is using, INTF_MODE_NONE if unused
|
* @intfs: Interfaces this encoder is using, INTF_MODE_NONE if unused
|
||||||
|
@@ -22,8 +22,7 @@
|
|||||||
#define SDE_ENCODER_NAME_MAX 16
|
#define SDE_ENCODER_NAME_MAX 16
|
||||||
|
|
||||||
/* wait for at most 2 vsync for lowest refresh rate (24hz) */
|
/* wait for at most 2 vsync for lowest refresh rate (24hz) */
|
||||||
#define KICKOFF_TIMEOUT_MS 84
|
#define DEFAULT_KICKOFF_TIMEOUT_MS 84
|
||||||
#define KICKOFF_TIMEOUT_JIFFIES msecs_to_jiffies(KICKOFF_TIMEOUT_MS)
|
|
||||||
|
|
||||||
#define MAX_TE_PROFILE_COUNT 5
|
#define MAX_TE_PROFILE_COUNT 5
|
||||||
/**
|
/**
|
||||||
@@ -286,6 +285,7 @@ struct sde_encoder_irq {
|
|||||||
* @pending_retire_fence_cnt: Atomic counter tracking the pending retire
|
* @pending_retire_fence_cnt: Atomic counter tracking the pending retire
|
||||||
* fences that have to be signalled.
|
* fences that have to be signalled.
|
||||||
* @pending_kickoff_wq: Wait queue for blocking until kickoff completes
|
* @pending_kickoff_wq: Wait queue for blocking until kickoff completes
|
||||||
|
* @kickoff_timeout_ms: kickoff timeout in mill seconds
|
||||||
* @irq: IRQ tracking structures
|
* @irq: IRQ tracking structures
|
||||||
* @has_intf_te: Interface TE configuration support
|
* @has_intf_te: Interface TE configuration support
|
||||||
* @cont_splash_enabled: Variable to store continuous splash settings.
|
* @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_kickoff_cnt;
|
||||||
atomic_t pending_retire_fence_cnt;
|
atomic_t pending_retire_fence_cnt;
|
||||||
wait_queue_head_t pending_kickoff_wq;
|
wait_queue_head_t pending_kickoff_wq;
|
||||||
|
u32 kickoff_timeout_ms;
|
||||||
struct sde_encoder_irq irq[INTR_IDX_MAX];
|
struct sde_encoder_irq irq[INTR_IDX_MAX];
|
||||||
bool has_intf_te;
|
bool has_intf_te;
|
||||||
bool cont_splash_enabled;
|
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,
|
void sde_encoder_helper_get_pp_line_count(struct drm_encoder *drm_enc,
|
||||||
struct sde_hw_pp_vsync_info *info);
|
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
|
* sde_encoder_helper_trigger_flush - control flush helper function
|
||||||
* This helper function may be optionally specified by physical
|
* This helper function may be optionally specified by physical
|
||||||
|
@@ -37,11 +37,13 @@
|
|||||||
#define AUTOREFRESH_SEQ2_POLL_TIMEOUT 1000000
|
#define AUTOREFRESH_SEQ2_POLL_TIMEOUT 1000000
|
||||||
|
|
||||||
static inline int _sde_encoder_phys_cmd_get_idle_timeout(
|
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 ?
|
return cmd_enc->autorefresh.cfg.frame_count ?
|
||||||
cmd_enc->autorefresh.cfg.frame_count *
|
cmd_enc->autorefresh.cfg.frame_count * timeout : timeout;
|
||||||
KICKOFF_TIMEOUT_MS : KICKOFF_TIMEOUT_MS;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool sde_encoder_phys_cmd_is_master(
|
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);
|
_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(
|
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.wq = &phys_enc->pending_kickoff_wq;
|
||||||
wait_info.atomic_cnt = &phys_enc->pending_kickoff_cnt;
|
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 */
|
/* slave encoder doesn't enable for ppsplit */
|
||||||
if (_sde_encoder_phys_is_ppsplit_slave(phys_enc))
|
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.wq = &cmd_enc->autorefresh.kickoff_wq;
|
||||||
wait_info.atomic_cnt = &cmd_enc->autorefresh.kickoff_cnt;
|
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 */
|
/* wait for autorefresh kickoff to start */
|
||||||
ret = sde_encoder_helper_wait_for_irq(phys_enc,
|
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;
|
ctl = phys_enc->hw_ctl;
|
||||||
c_conn = to_sde_connector(phys_enc->connector);
|
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 ||
|
if (c_conn->lp_mode == SDE_MODE_DPMS_LP1 ||
|
||||||
c_conn->lp_mode == SDE_MODE_DPMS_LP2)
|
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.wq = &phys_enc->pending_kickoff_wq;
|
||||||
wait_info.atomic_cnt = &phys_enc->pending_retire_fence_cnt;
|
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.wq = &cmd_enc->pending_vblank_wq;
|
||||||
wait_info.atomic_cnt = &cmd_enc->pending_vblank_cnt;
|
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);
|
atomic_inc(&cmd_enc->pending_vblank_cnt);
|
||||||
|
|
||||||
@@ -1696,6 +1701,7 @@ static void _sde_encoder_autorefresh_disable_seq1(
|
|||||||
struct sde_encoder_phys *phys_enc)
|
struct sde_encoder_phys *phys_enc)
|
||||||
{
|
{
|
||||||
int trial = 0;
|
int trial = 0;
|
||||||
|
u32 timeout_ms = phys_enc->kickoff_timeout_ms;
|
||||||
struct sde_encoder_phys_cmd *cmd_enc =
|
struct sde_encoder_phys_cmd *cmd_enc =
|
||||||
to_sde_encoder_phys_cmd(phys_enc);
|
to_sde_encoder_phys_cmd(phys_enc);
|
||||||
|
|
||||||
@@ -1712,7 +1718,7 @@ static void _sde_encoder_autorefresh_disable_seq1(
|
|||||||
do {
|
do {
|
||||||
udelay(AUTOREFRESH_SEQ1_POLL_TIME);
|
udelay(AUTOREFRESH_SEQ1_POLL_TIME);
|
||||||
if ((trial * 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,
|
SDE_ERROR_CMDENC(cmd_enc,
|
||||||
"disable autorefresh failed\n");
|
"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;
|
phys_enc->vblank_ctl_lock = p->vblank_ctl_lock;
|
||||||
cmd_enc->stream_sel = 0;
|
cmd_enc->stream_sel = 0;
|
||||||
phys_enc->enable_state = SDE_ENC_DISABLED;
|
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);
|
sde_encoder_phys_cmd_init_ops(&phys_enc->ops);
|
||||||
phys_enc->comp_type = p->comp_type;
|
phys_enc->comp_type = p->comp_type;
|
||||||
|
|
||||||
|
@@ -656,6 +656,9 @@ static void sde_encoder_phys_vid_mode_set(
|
|||||||
}
|
}
|
||||||
|
|
||||||
_sde_encoder_phys_vid_setup_irq_hw_idx(phys_enc);
|
_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(
|
static int sde_encoder_phys_vid_control_vblank_irq(
|
||||||
@@ -888,7 +891,7 @@ static int _sde_encoder_phys_vid_wait_for_vblank(
|
|||||||
|
|
||||||
wait_info.wq = &phys_enc->pending_kickoff_wq;
|
wait_info.wq = &phys_enc->pending_kickoff_wq;
|
||||||
wait_info.atomic_cnt = &phys_enc->pending_kickoff_cnt;
|
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 */
|
/* Wait for kickoff to complete */
|
||||||
ret = sde_encoder_helper_wait_for_irq(phys_enc, INTR_IDX_VSYNC,
|
ret = sde_encoder_helper_wait_for_irq(phys_enc, INTR_IDX_VSYNC,
|
||||||
@@ -1360,6 +1363,7 @@ struct sde_encoder_phys *sde_encoder_phys_vid_init(
|
|||||||
phys_enc->enc_spinlock = p->enc_spinlock;
|
phys_enc->enc_spinlock = p->enc_spinlock;
|
||||||
phys_enc->vblank_ctl_lock = p->vblank_ctl_lock;
|
phys_enc->vblank_ctl_lock = p->vblank_ctl_lock;
|
||||||
phys_enc->comp_type = p->comp_type;
|
phys_enc->comp_type = p->comp_type;
|
||||||
|
phys_enc->kickoff_timeout_ms = DEFAULT_KICKOFF_TIMEOUT_MS;
|
||||||
for (i = 0; i < INTR_IDX_MAX; i++) {
|
for (i = 0; i < INTR_IDX_MAX; i++) {
|
||||||
irq = &phys_enc->irq[i];
|
irq = &phys_enc->irq[i];
|
||||||
INIT_LIST_HEAD(&irq->cb.list);
|
INIT_LIST_HEAD(&irq->cb.list);
|
||||||
|
@@ -1402,6 +1402,9 @@ static void sde_encoder_phys_wb_mode_set(
|
|||||||
PTR_ERR(phys_enc->hw_cdm));
|
PTR_ERR(phys_enc->hw_cdm));
|
||||||
phys_enc->hw_cdm = NULL;
|
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)
|
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.wq = &phys_enc->pending_kickoff_wq;
|
||||||
wait_info.atomic_cnt = &phys_enc->pending_retire_fence_cnt;
|
wait_info.atomic_cnt = &phys_enc->pending_retire_fence_cnt;
|
||||||
wait_info.timeout_ms = max_t(u32, wb_enc->wbdone_timeout,
|
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,
|
rc = sde_encoder_helper_wait_for_irq(phys_enc, INTR_IDX_WB_DONE,
|
||||||
&wait_info);
|
&wait_info);
|
||||||
if (rc == -ETIMEDOUT && _sde_encoder_phys_wb_is_idle(phys_enc)) {
|
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;
|
ret = -ENOMEM;
|
||||||
goto fail_alloc;
|
goto fail_alloc;
|
||||||
}
|
}
|
||||||
wb_enc->wbdone_timeout = KICKOFF_TIMEOUT_MS;
|
|
||||||
|
|
||||||
phys_enc = &wb_enc->base;
|
phys_enc = &wb_enc->base;
|
||||||
|
phys_enc->kickoff_timeout_ms = DEFAULT_KICKOFF_TIMEOUT_MS;
|
||||||
|
|
||||||
if (p->sde_kms->vbif[VBIF_NRT]) {
|
if (p->sde_kms->vbif[VBIF_NRT]) {
|
||||||
wb_enc->aspace[SDE_IOMMU_DOMAIN_UNSECURE] =
|
wb_enc->aspace[SDE_IOMMU_DOMAIN_UNSECURE] =
|
||||||
|
Reference in New Issue
Block a user