disp: msm: sde: wait for specific pp_done instead of zero
2 Frames transfer pending is possible with posted start. One ongoing frame and another triggered frame. Current SW waits for pp_done interrupt if pending frame count is greater than 1. It is possible that interrupt may be missed for ongoing frame. In that case, SW should run pp_done wait for one by one frame instead of two frames together. It allows encoder to check the ctl scheduler status and trigger the frame done event on time. Change-Id: I4817842292d96747890ee70da8a5bdf9b56816ed Signed-off-by: Dhaval Patel <pdhaval@codeaurora.org>
This commit is contained in:
@@ -408,13 +408,16 @@ static int _sde_encoder_wait_timeout(int32_t drm_id, int32_t hw_id,
|
|||||||
|
|
||||||
do {
|
do {
|
||||||
rc = wait_event_timeout(*(info->wq),
|
rc = wait_event_timeout(*(info->wq),
|
||||||
atomic_read(info->atomic_cnt) == 0, wait_time_jiffies);
|
atomic_read(info->atomic_cnt) == info->count_check,
|
||||||
|
wait_time_jiffies);
|
||||||
cur_ktime = ktime_get();
|
cur_ktime = ktime_get();
|
||||||
|
|
||||||
SDE_EVT32(drm_id, hw_id, rc, ktime_to_ms(cur_ktime),
|
SDE_EVT32(drm_id, hw_id, rc, ktime_to_ms(cur_ktime),
|
||||||
timeout_ms, atomic_read(info->atomic_cnt));
|
timeout_ms, atomic_read(info->atomic_cnt),
|
||||||
|
info->count_check);
|
||||||
/* If we timed out, counter is valid and time is less, wait again */
|
/* If we timed out, counter is valid and time is less, wait again */
|
||||||
} while (atomic_read(info->atomic_cnt) && (rc == 0) &&
|
} while ((atomic_read(info->atomic_cnt) != info->count_check) &&
|
||||||
|
(rc == 0) &&
|
||||||
(ktime_compare_safe(exp_ktime, cur_ktime) > 0));
|
(ktime_compare_safe(exp_ktime, cur_ktime) > 0));
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
|
@@ -458,11 +458,13 @@ struct sde_enc_phys_init_params {
|
|||||||
* sde_encoder_wait_info - container for passing arguments to irq wait functions
|
* sde_encoder_wait_info - container for passing arguments to irq wait functions
|
||||||
* @wq: wait queue structure
|
* @wq: wait queue structure
|
||||||
* @atomic_cnt: wait until atomic_cnt equals zero
|
* @atomic_cnt: wait until atomic_cnt equals zero
|
||||||
|
* @count_check: wait for specific atomic_cnt instead of zero.
|
||||||
* @timeout_ms: timeout value in milliseconds
|
* @timeout_ms: timeout value in milliseconds
|
||||||
*/
|
*/
|
||||||
struct sde_encoder_wait_info {
|
struct sde_encoder_wait_info {
|
||||||
wait_queue_head_t *wq;
|
wait_queue_head_t *wq;
|
||||||
atomic_t *atomic_cnt;
|
atomic_t *atomic_cnt;
|
||||||
|
u32 count_check;
|
||||||
s64 timeout_ms;
|
s64 timeout_ms;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -647,10 +647,11 @@ static int _sde_encoder_phys_cmd_wait_for_idle(
|
|||||||
{
|
{
|
||||||
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);
|
||||||
struct sde_encoder_wait_info wait_info;
|
struct sde_encoder_wait_info wait_info = {0};
|
||||||
bool recovery_events;
|
bool recovery_events;
|
||||||
int ret;
|
int ret;
|
||||||
struct sde_hw_ctl *ctl;
|
struct sde_hw_ctl *ctl;
|
||||||
|
bool wr_ptr_wait_success = true;
|
||||||
|
|
||||||
if (!phys_enc) {
|
if (!phys_enc) {
|
||||||
SDE_ERROR("invalid encoder\n");
|
SDE_ERROR("invalid encoder\n");
|
||||||
@@ -658,7 +659,11 @@ static int _sde_encoder_phys_cmd_wait_for_idle(
|
|||||||
}
|
}
|
||||||
|
|
||||||
ctl = phys_enc->hw_ctl;
|
ctl = phys_enc->hw_ctl;
|
||||||
if (cmd_enc->wr_ptr_wait_success &&
|
|
||||||
|
if (sde_encoder_phys_cmd_is_master(phys_enc))
|
||||||
|
wr_ptr_wait_success = cmd_enc->wr_ptr_wait_success;
|
||||||
|
|
||||||
|
if (wr_ptr_wait_success &&
|
||||||
(phys_enc->frame_trigger_mode == FRAME_DONE_WAIT_POSTED_START) &&
|
(phys_enc->frame_trigger_mode == FRAME_DONE_WAIT_POSTED_START) &&
|
||||||
ctl->ops.get_scheduler_status &&
|
ctl->ops.get_scheduler_status &&
|
||||||
(ctl->ops.get_scheduler_status(ctl) & BIT(0)) &&
|
(ctl->ops.get_scheduler_status(ctl) & BIT(0)) &&
|
||||||
@@ -672,6 +677,9 @@ static int _sde_encoder_phys_cmd_wait_for_idle(
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (atomic_read(&phys_enc->pending_kickoff_cnt) > 1)
|
||||||
|
wait_info.count_check = 1;
|
||||||
|
|
||||||
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 = KICKOFF_TIMEOUT_MS;
|
||||||
@@ -707,7 +715,7 @@ static int _sde_encoder_phys_cmd_wait_for_autorefresh_done(
|
|||||||
{
|
{
|
||||||
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);
|
||||||
struct sde_encoder_wait_info wait_info;
|
struct sde_encoder_wait_info wait_info = {0};
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (!phys_enc) {
|
if (!phys_enc) {
|
||||||
@@ -1334,7 +1342,7 @@ static int _sde_encoder_phys_cmd_wait_for_wr_ptr(
|
|||||||
{
|
{
|
||||||
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);
|
||||||
struct sde_encoder_wait_info wait_info;
|
struct sde_encoder_wait_info wait_info = {0};
|
||||||
int ret;
|
int ret;
|
||||||
bool frame_pending = true;
|
bool frame_pending = true;
|
||||||
struct sde_hw_ctl *ctl;
|
struct sde_hw_ctl *ctl;
|
||||||
@@ -1383,6 +1391,7 @@ static int _sde_encoder_phys_cmd_wait_for_wr_ptr(
|
|||||||
}
|
}
|
||||||
|
|
||||||
cmd_enc->wr_ptr_wait_success = (ret == 0) ? true : false;
|
cmd_enc->wr_ptr_wait_success = (ret == 0) ? true : false;
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1461,7 +1470,7 @@ static int sde_encoder_phys_cmd_wait_for_vblank(
|
|||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
struct sde_encoder_phys_cmd *cmd_enc;
|
struct sde_encoder_phys_cmd *cmd_enc;
|
||||||
struct sde_encoder_wait_info wait_info;
|
struct sde_encoder_wait_info wait_info = {0};
|
||||||
|
|
||||||
if (!phys_enc)
|
if (!phys_enc)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@@ -864,7 +864,7 @@ static void sde_encoder_phys_vid_get_hw_resources(
|
|||||||
static int _sde_encoder_phys_vid_wait_for_vblank(
|
static int _sde_encoder_phys_vid_wait_for_vblank(
|
||||||
struct sde_encoder_phys *phys_enc, bool notify)
|
struct sde_encoder_phys *phys_enc, bool notify)
|
||||||
{
|
{
|
||||||
struct sde_encoder_wait_info wait_info;
|
struct sde_encoder_wait_info wait_info = {0};
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
u32 event = SDE_ENCODER_FRAME_EVENT_ERROR |
|
u32 event = SDE_ENCODER_FRAME_EVENT_ERROR |
|
||||||
SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE |
|
SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE |
|
||||||
|
@@ -1218,7 +1218,7 @@ static int _sde_encoder_phys_wb_wait_for_commit_done(
|
|||||||
u32 event = 0;
|
u32 event = 0;
|
||||||
u64 wb_time = 0;
|
u64 wb_time = 0;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
struct sde_encoder_wait_info wait_info;
|
struct sde_encoder_wait_info wait_info = {0};
|
||||||
|
|
||||||
/* Return EWOULDBLOCK since we know the wait isn't necessary */
|
/* Return EWOULDBLOCK since we know the wait isn't necessary */
|
||||||
if (phys_enc->enable_state == SDE_ENC_DISABLED) {
|
if (phys_enc->enable_state == SDE_ENC_DISABLED) {
|
||||||
|
Reference in New Issue
Block a user