Re: [Freedreno] [PATCH 2/2] drm/msm: dpu: Make legacy cursor updates asynchronous

2018-10-03 Thread Sean Paul
On Tue, Oct 02, 2018 at 06:19:52PM -0700, Jeykumar Sankaran wrote:
> On 2018-10-01 13:30, Sean Paul wrote:
> > On Wed, Sep 26, 2018 at 11:56:47AM -0700, Jeykumar Sankaran wrote:
> > > On 2018-09-19 11:56, Sean Paul wrote:
> > > > From: Sean Paul 
> > > >
> > > > This patch sprinkles a few async/legacy_cursor_update checks
> > > > through commit to ensure that cursor updates aren't blocked on vsync.
> > > > There are 2 main components to this, the first is that we don't want
> > to
> > > > wait_for_commit_done in msm_atomic  before returning from
> > > > atomic_complete.
> > > > The second is that in dpu we don't want to wait for frame_done events
> > > > when
> > > > updating the cursor.
> > > >
> > > > Signed-off-by: Sean Paul 
> > > > ---

/snip

> > > > diff --git a/drivers/gpu/drm/msm/msm_atomic.c
> > > > b/drivers/gpu/drm/msm/msm_atomic.c
> > > > index c1f1779c980f..7912130ce5ce 100644
> > > > --- a/drivers/gpu/drm/msm/msm_atomic.c
> > > > +++ b/drivers/gpu/drm/msm/msm_atomic.c
> > > > @@ -76,7 +76,8 @@ void msm_atomic_commit_tail(struct drm_atomic_state
> > > > *state)
> > > > kms->funcs->commit(kms, state);
> > > > }
> > > >
> > > > -   msm_atomic_wait_for_commit_done(dev, state);
> > > > +   if (!state->legacy_cursor_update)
> > > I see state->async_update is updated after validation checks on the
> > async
> > > capabilities. Shouldn't we use
> > > that var instead of state->legacy_cursor_update?
> > > > +   msm_atomic_wait_for_commit_done(dev, state);
> > > >
> > > > kms->funcs->complete_commit(kms, state);
> > > 
> > > Do we need to introduce plane helpers atomic_async_update and
> > > atomic_async_check in DPU before supporting
> > > these wait skips? or are they irrelevant for this legacy async path?
> > 
> > I was trying to limit the scope of this to just cursor updates. I think
> > once/if
> > support is added for generic async it makes sense to change over to that
> > verbage.
> > 
> Since SDM845 doesnt support dedicated CURSOR stages, 

Well, it has CURSOR type planes, which unlocks the cursor ioctls, so it kind of
does :)

> I think the right
> way to add the cursor support should be to introduce the atomic async
> support
> in the driver and let the cursor frame update like regulary async commit.
> 
> I need to explore on the right way to fit that in.

It's as easy as implementing the async atomic hooks. If they're present, the
cursor path goes through them. Upgrading from legacy cursor to generic async is
pretty trivial in light of the other issues we're facing here.

Sean

> 
> Thanks,
> Jeykumar S.
> > Sean
> > 
> > > 
> > > --
> > > Jeykumar S
> 
> -- 
> Jeykumar S

-- 
Sean Paul, Software Engineer, Google / Chromium OS
___
Freedreno mailing list
Freedreno@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/freedreno


Re: [Freedreno] [PATCH 2/2] drm/msm: dpu: Make legacy cursor updates asynchronous

2018-10-02 Thread Jeykumar Sankaran

On 2018-10-01 13:30, Sean Paul wrote:

On Wed, Sep 26, 2018 at 11:56:47AM -0700, Jeykumar Sankaran wrote:

On 2018-09-19 11:56, Sean Paul wrote:
> From: Sean Paul 
>
> This patch sprinkles a few async/legacy_cursor_update checks
> through commit to ensure that cursor updates aren't blocked on vsync.
> There are 2 main components to this, the first is that we don't want

to

> wait_for_commit_done in msm_atomic  before returning from
> atomic_complete.
> The second is that in dpu we don't want to wait for frame_done events
> when
> updating the cursor.
>
> Signed-off-by: Sean Paul 
> ---
>  drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c| 44

+++--

>  drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h|  3 +-
>  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 21 ++
>  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h |  6 ++-
>  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c |  5 ++-
>  drivers/gpu/drm/msm/msm_atomic.c|  3 +-
>  6 files changed, 48 insertions(+), 34 deletions(-)
>
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> index a8f2dd7a37c7..b23f00a2554b 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> @@ -816,7 +816,7 @@ static int _dpu_crtc_wait_for_frame_done(struct
> drm_crtc *crtc)
>return rc;
>  }
>
> -void dpu_crtc_commit_kickoff(struct drm_crtc *crtc)
> +void dpu_crtc_commit_kickoff(struct drm_crtc *crtc, bool async)
>  {
>struct drm_encoder *encoder;
>struct drm_device *dev;
> @@ -862,27 +862,30 @@ void dpu_crtc_commit_kickoff(struct drm_crtc
> *crtc)
> * Encoder will flush/start now, unless it has a tx
> pending.
> * If so, it may delay and flush at an irq event (e.g.
> ppdone)
> */
> -  dpu_encoder_prepare_for_kickoff(encoder, );
> +  dpu_encoder_prepare_for_kickoff(encoder, , async);
>}
>
> -  /* wait for frame_event_done completion */
> -  DPU_ATRACE_BEGIN("wait_for_frame_done_event");
> -  ret = _dpu_crtc_wait_for_frame_done(crtc);
> -  DPU_ATRACE_END("wait_for_frame_done_event");
> -  if (ret) {
> -  DPU_ERROR("crtc%d wait for frame done
> failed;frame_pending%d\n",
> -  crtc->base.id,
> -  atomic_read(_crtc->frame_pending));
> -  goto end;
> -  }
>
> -  if (atomic_inc_return(_crtc->frame_pending) == 1) {
> -  /* acquire bandwidth and other resources */
> -  DPU_DEBUG("crtc%d first commit\n", crtc->base.id);
> -  } else
> -  DPU_DEBUG("crtc%d commit\n", crtc->base.id);
> +  if (!async) {
> +  /* wait for frame_event_done completion */
> +  DPU_ATRACE_BEGIN("wait_for_frame_done_event");
> +  ret = _dpu_crtc_wait_for_frame_done(crtc);
> +  DPU_ATRACE_END("wait_for_frame_done_event");
> +  if (ret) {
> +  DPU_ERROR("crtc%d wait for frame done
> failed;frame_pending%d\n",
> +  crtc->base.id,
> +
> atomic_read(_crtc->frame_pending));
> +  goto end;
> +  }
> +
> +  if (atomic_inc_return(_crtc->frame_pending) == 1) {
> +  /* acquire bandwidth and other resources */
> +  DPU_DEBUG("crtc%d first commit\n", crtc->base.id);
> +  } else
> +  DPU_DEBUG("crtc%d commit\n", crtc->base.id);
>
> -  dpu_crtc->play_count++;
> +  dpu_crtc->play_count++;
> +  }
>
>dpu_vbif_clear_errors(dpu_kms);
>
> @@ -890,11 +893,12 @@ void dpu_crtc_commit_kickoff(struct drm_crtc
> *crtc)
>if (encoder->crtc != crtc)
>continue;
>
> -  dpu_encoder_kickoff(encoder);
> +  dpu_encoder_kickoff(encoder, async);
>}
>
>  end:
> -  reinit_completion(_crtc->frame_done_comp);
> +  if (!async)
> +  reinit_completion(_crtc->frame_done_comp);
>DPU_ATRACE_END("crtc_commit");
>  }
>
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
> b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
> index 3723b4830335..67c9f59997cf 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
> @@ -285,8 +285,9 @@ int dpu_crtc_vblank(struct drm_crtc *crtc, bool

en);

>  /**
>   * dpu_crtc_commit_kickoff - trigger kickoff of the commit for this
> crtc
>   * @crtc: Pointer to drm crtc object
> + * @async: true if the commit is asynchronous, false otherwise
>   */
> -void dpu_crtc_commit_kickoff(struct drm_crtc *crtc);
> +void dpu_crtc_commit_kickoff(struct drm_crtc *crtc, bool async);
>
>  /**
>   * dpu_crtc_complete_commit - callback signalling completion of

current

> commit
> diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> index c2e8985b4c54..fc729fc8dd8c 100644
> --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
> @@ -1410,7 +1410,7 @@ static void 

Re: [Freedreno] [PATCH 2/2] drm/msm: dpu: Make legacy cursor updates asynchronous

2018-10-01 Thread Sean Paul
On Wed, Sep 26, 2018 at 11:56:47AM -0700, Jeykumar Sankaran wrote:
> On 2018-09-19 11:56, Sean Paul wrote:
> > From: Sean Paul 
> > 
> > This patch sprinkles a few async/legacy_cursor_update checks
> > through commit to ensure that cursor updates aren't blocked on vsync.
> > There are 2 main components to this, the first is that we don't want to
> > wait_for_commit_done in msm_atomic  before returning from
> > atomic_complete.
> > The second is that in dpu we don't want to wait for frame_done events
> > when
> > updating the cursor.
> > 
> > Signed-off-by: Sean Paul 
> > ---
> >  drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c| 44 +++--
> >  drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h|  3 +-
> >  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 21 ++
> >  drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h |  6 ++-
> >  drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c |  5 ++-
> >  drivers/gpu/drm/msm/msm_atomic.c|  3 +-
> >  6 files changed, 48 insertions(+), 34 deletions(-)
> > 
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > index a8f2dd7a37c7..b23f00a2554b 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
> > @@ -816,7 +816,7 @@ static int _dpu_crtc_wait_for_frame_done(struct
> > drm_crtc *crtc)
> > return rc;
> >  }
> > 
> > -void dpu_crtc_commit_kickoff(struct drm_crtc *crtc)
> > +void dpu_crtc_commit_kickoff(struct drm_crtc *crtc, bool async)
> >  {
> > struct drm_encoder *encoder;
> > struct drm_device *dev;
> > @@ -862,27 +862,30 @@ void dpu_crtc_commit_kickoff(struct drm_crtc
> > *crtc)
> >  * Encoder will flush/start now, unless it has a tx
> > pending.
> >  * If so, it may delay and flush at an irq event (e.g.
> > ppdone)
> >  */
> > -   dpu_encoder_prepare_for_kickoff(encoder, );
> > +   dpu_encoder_prepare_for_kickoff(encoder, , async);
> > }
> > 
> > -   /* wait for frame_event_done completion */
> > -   DPU_ATRACE_BEGIN("wait_for_frame_done_event");
> > -   ret = _dpu_crtc_wait_for_frame_done(crtc);
> > -   DPU_ATRACE_END("wait_for_frame_done_event");
> > -   if (ret) {
> > -   DPU_ERROR("crtc%d wait for frame done
> > failed;frame_pending%d\n",
> > -   crtc->base.id,
> > -   atomic_read(_crtc->frame_pending));
> > -   goto end;
> > -   }
> > 
> > -   if (atomic_inc_return(_crtc->frame_pending) == 1) {
> > -   /* acquire bandwidth and other resources */
> > -   DPU_DEBUG("crtc%d first commit\n", crtc->base.id);
> > -   } else
> > -   DPU_DEBUG("crtc%d commit\n", crtc->base.id);
> > +   if (!async) {
> > +   /* wait for frame_event_done completion */
> > +   DPU_ATRACE_BEGIN("wait_for_frame_done_event");
> > +   ret = _dpu_crtc_wait_for_frame_done(crtc);
> > +   DPU_ATRACE_END("wait_for_frame_done_event");
> > +   if (ret) {
> > +   DPU_ERROR("crtc%d wait for frame done
> > failed;frame_pending%d\n",
> > +   crtc->base.id,
> > +
> > atomic_read(_crtc->frame_pending));
> > +   goto end;
> > +   }
> > +
> > +   if (atomic_inc_return(_crtc->frame_pending) == 1) {
> > +   /* acquire bandwidth and other resources */
> > +   DPU_DEBUG("crtc%d first commit\n", crtc->base.id);
> > +   } else
> > +   DPU_DEBUG("crtc%d commit\n", crtc->base.id);
> > 
> > -   dpu_crtc->play_count++;
> > +   dpu_crtc->play_count++;
> > +   }
> > 
> > dpu_vbif_clear_errors(dpu_kms);
> > 
> > @@ -890,11 +893,12 @@ void dpu_crtc_commit_kickoff(struct drm_crtc
> > *crtc)
> > if (encoder->crtc != crtc)
> > continue;
> > 
> > -   dpu_encoder_kickoff(encoder);
> > +   dpu_encoder_kickoff(encoder, async);
> > }
> > 
> >  end:
> > -   reinit_completion(_crtc->frame_done_comp);
> > +   if (!async)
> > +   reinit_completion(_crtc->frame_done_comp);
> > DPU_ATRACE_END("crtc_commit");
> >  }
> > 
> > diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
> > b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
> > index 3723b4830335..67c9f59997cf 100644
> > --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
> > +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
> > @@ -285,8 +285,9 @@ int dpu_crtc_vblank(struct drm_crtc *crtc, bool en);
> >  /**
> >   * dpu_crtc_commit_kickoff - trigger kickoff of the commit for this
> > crtc
> >   * @crtc: Pointer to drm crtc object
> > + * @async: true if the commit is asynchronous, false otherwise
> >   */
> > -void dpu_crtc_commit_kickoff(struct drm_crtc *crtc);
> > +void dpu_crtc_commit_kickoff(struct drm_crtc *crtc, bool async);
> > 
> >  /**
> >   * dpu_crtc_complete_commit - callback signalling completion of current
> > commit
> > diff --git 

Re: [Freedreno] [PATCH 2/2] drm/msm: dpu: Make legacy cursor updates asynchronous

2018-09-26 Thread Jeykumar Sankaran

On 2018-09-19 11:56, Sean Paul wrote:

From: Sean Paul 

This patch sprinkles a few async/legacy_cursor_update checks
through commit to ensure that cursor updates aren't blocked on vsync.
There are 2 main components to this, the first is that we don't want to
wait_for_commit_done in msm_atomic  before returning from 
atomic_complete.
The second is that in dpu we don't want to wait for frame_done events 
when

updating the cursor.

Signed-off-by: Sean Paul 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c| 44 +++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h|  3 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 21 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h |  6 ++-
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c |  5 ++-
 drivers/gpu/drm/msm/msm_atomic.c|  3 +-
 6 files changed, 48 insertions(+), 34 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index a8f2dd7a37c7..b23f00a2554b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -816,7 +816,7 @@ static int _dpu_crtc_wait_for_frame_done(struct
drm_crtc *crtc)
return rc;
 }

-void dpu_crtc_commit_kickoff(struct drm_crtc *crtc)
+void dpu_crtc_commit_kickoff(struct drm_crtc *crtc, bool async)
 {
struct drm_encoder *encoder;
struct drm_device *dev;
@@ -862,27 +862,30 @@ void dpu_crtc_commit_kickoff(struct drm_crtc 
*crtc)

 * Encoder will flush/start now, unless it has a tx
pending.
 * If so, it may delay and flush at an irq event (e.g.
ppdone)
 */
-   dpu_encoder_prepare_for_kickoff(encoder, );
+   dpu_encoder_prepare_for_kickoff(encoder, , async);
}

-   /* wait for frame_event_done completion */
-   DPU_ATRACE_BEGIN("wait_for_frame_done_event");
-   ret = _dpu_crtc_wait_for_frame_done(crtc);
-   DPU_ATRACE_END("wait_for_frame_done_event");
-   if (ret) {
-   DPU_ERROR("crtc%d wait for frame done
failed;frame_pending%d\n",
-   crtc->base.id,
-   atomic_read(_crtc->frame_pending));
-   goto end;
-   }

-   if (atomic_inc_return(_crtc->frame_pending) == 1) {
-   /* acquire bandwidth and other resources */
-   DPU_DEBUG("crtc%d first commit\n", crtc->base.id);
-   } else
-   DPU_DEBUG("crtc%d commit\n", crtc->base.id);
+   if (!async) {
+   /* wait for frame_event_done completion */
+   DPU_ATRACE_BEGIN("wait_for_frame_done_event");
+   ret = _dpu_crtc_wait_for_frame_done(crtc);
+   DPU_ATRACE_END("wait_for_frame_done_event");
+   if (ret) {
+   DPU_ERROR("crtc%d wait for frame done
failed;frame_pending%d\n",
+   crtc->base.id,
+
atomic_read(_crtc->frame_pending));
+   goto end;
+   }
+
+   if (atomic_inc_return(_crtc->frame_pending) == 1) {
+   /* acquire bandwidth and other resources */
+   DPU_DEBUG("crtc%d first commit\n", crtc->base.id);
+   } else
+   DPU_DEBUG("crtc%d commit\n", crtc->base.id);

-   dpu_crtc->play_count++;
+   dpu_crtc->play_count++;
+   }

dpu_vbif_clear_errors(dpu_kms);

@@ -890,11 +893,12 @@ void dpu_crtc_commit_kickoff(struct drm_crtc 
*crtc)

if (encoder->crtc != crtc)
continue;

-   dpu_encoder_kickoff(encoder);
+   dpu_encoder_kickoff(encoder, async);
}

 end:
-   reinit_completion(_crtc->frame_done_comp);
+   if (!async)
+   reinit_completion(_crtc->frame_done_comp);
DPU_ATRACE_END("crtc_commit");
 }

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
index 3723b4830335..67c9f59997cf 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
@@ -285,8 +285,9 @@ int dpu_crtc_vblank(struct drm_crtc *crtc, bool 
en);

 /**
  * dpu_crtc_commit_kickoff - trigger kickoff of the commit for this 
crtc

  * @crtc: Pointer to drm crtc object
+ * @async: true if the commit is asynchronous, false otherwise
  */
-void dpu_crtc_commit_kickoff(struct drm_crtc *crtc);
+void dpu_crtc_commit_kickoff(struct drm_crtc *crtc, bool async);

 /**
  * dpu_crtc_complete_commit - callback signalling completion of 
current

commit
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index c2e8985b4c54..fc729fc8dd8c 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -1410,7 +1410,7 @@ static void dpu_encoder_off_work(struct 
kthread_work

*work)
  * extra_flush_bits: Additional bit mask to include in flush 

[Freedreno] [PATCH 2/2] drm/msm: dpu: Make legacy cursor updates asynchronous

2018-09-19 Thread Sean Paul
From: Sean Paul 

This patch sprinkles a few async/legacy_cursor_update checks
through commit to ensure that cursor updates aren't blocked on vsync.
There are 2 main components to this, the first is that we don't want to
wait_for_commit_done in msm_atomic  before returning from atomic_complete.
The second is that in dpu we don't want to wait for frame_done events when
updating the cursor.

Signed-off-by: Sean Paul 
---
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c| 44 +++--
 drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h|  3 +-
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c | 21 ++
 drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.h |  6 ++-
 drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c |  5 ++-
 drivers/gpu/drm/msm/msm_atomic.c|  3 +-
 6 files changed, 48 insertions(+), 34 deletions(-)

diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
index a8f2dd7a37c7..b23f00a2554b 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.c
@@ -816,7 +816,7 @@ static int _dpu_crtc_wait_for_frame_done(struct drm_crtc 
*crtc)
return rc;
 }
 
-void dpu_crtc_commit_kickoff(struct drm_crtc *crtc)
+void dpu_crtc_commit_kickoff(struct drm_crtc *crtc, bool async)
 {
struct drm_encoder *encoder;
struct drm_device *dev;
@@ -862,27 +862,30 @@ void dpu_crtc_commit_kickoff(struct drm_crtc *crtc)
 * Encoder will flush/start now, unless it has a tx pending.
 * If so, it may delay and flush at an irq event (e.g. ppdone)
 */
-   dpu_encoder_prepare_for_kickoff(encoder, );
+   dpu_encoder_prepare_for_kickoff(encoder, , async);
}
 
-   /* wait for frame_event_done completion */
-   DPU_ATRACE_BEGIN("wait_for_frame_done_event");
-   ret = _dpu_crtc_wait_for_frame_done(crtc);
-   DPU_ATRACE_END("wait_for_frame_done_event");
-   if (ret) {
-   DPU_ERROR("crtc%d wait for frame done failed;frame_pending%d\n",
-   crtc->base.id,
-   atomic_read(_crtc->frame_pending));
-   goto end;
-   }
 
-   if (atomic_inc_return(_crtc->frame_pending) == 1) {
-   /* acquire bandwidth and other resources */
-   DPU_DEBUG("crtc%d first commit\n", crtc->base.id);
-   } else
-   DPU_DEBUG("crtc%d commit\n", crtc->base.id);
+   if (!async) {
+   /* wait for frame_event_done completion */
+   DPU_ATRACE_BEGIN("wait_for_frame_done_event");
+   ret = _dpu_crtc_wait_for_frame_done(crtc);
+   DPU_ATRACE_END("wait_for_frame_done_event");
+   if (ret) {
+   DPU_ERROR("crtc%d wait for frame done 
failed;frame_pending%d\n",
+   crtc->base.id,
+   atomic_read(_crtc->frame_pending));
+   goto end;
+   }
+
+   if (atomic_inc_return(_crtc->frame_pending) == 1) {
+   /* acquire bandwidth and other resources */
+   DPU_DEBUG("crtc%d first commit\n", crtc->base.id);
+   } else
+   DPU_DEBUG("crtc%d commit\n", crtc->base.id);
 
-   dpu_crtc->play_count++;
+   dpu_crtc->play_count++;
+   }
 
dpu_vbif_clear_errors(dpu_kms);
 
@@ -890,11 +893,12 @@ void dpu_crtc_commit_kickoff(struct drm_crtc *crtc)
if (encoder->crtc != crtc)
continue;
 
-   dpu_encoder_kickoff(encoder);
+   dpu_encoder_kickoff(encoder, async);
}
 
 end:
-   reinit_completion(_crtc->frame_done_comp);
+   if (!async)
+   reinit_completion(_crtc->frame_done_comp);
DPU_ATRACE_END("crtc_commit");
 }
 
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
index 3723b4830335..67c9f59997cf 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_crtc.h
@@ -285,8 +285,9 @@ int dpu_crtc_vblank(struct drm_crtc *crtc, bool en);
 /**
  * dpu_crtc_commit_kickoff - trigger kickoff of the commit for this crtc
  * @crtc: Pointer to drm crtc object
+ * @async: true if the commit is asynchronous, false otherwise
  */
-void dpu_crtc_commit_kickoff(struct drm_crtc *crtc);
+void dpu_crtc_commit_kickoff(struct drm_crtc *crtc, bool async);
 
 /**
  * dpu_crtc_complete_commit - callback signalling completion of current commit
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c 
b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
index c2e8985b4c54..fc729fc8dd8c 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
@@ -1410,7 +1410,7 @@ static void dpu_encoder_off_work(struct kthread_work 
*work)
  * extra_flush_bits: Additional bit mask to include in flush