[Intel-gfx] [PATCH 12/16] drm/i915: Disable LP1+ watermarks while changing the number of active pipes

2014-05-22 Thread ville . syrjala
From: Ville Syrjälä 

When we switch between one active pipe and multiple active pipes, the
display FIFO gets repartitioned. Disable the LP1+ waterwarks while that
is happening to make sure we don't get any glitches on other active
pipes while doing a modeset on another other pipe.

Signed-off-by: Ville Syrjälä 
---
 drivers/gpu/drm/i915/intel_display.c | 45 ++
 drivers/gpu/drm/i915/intel_drv.h |  2 ++
 drivers/gpu/drm/i915/intel_pm.c  | 47 
 3 files changed, 89 insertions(+), 5 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index bccf414..311c0f0 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -3985,6 +3985,27 @@ static struct intel_crtc *get_other_active_crtc(struct 
intel_crtc *crtc)
return other_active_crtc;
 }
 
+static void ilk_prepare_for_num_pipes_change(struct intel_crtc *crtc)
+{
+   struct drm_device *dev = crtc->base.dev;
+   struct intel_crtc *other_active_crtc = get_other_active_crtc(crtc);
+
+   /*
+* If we change between one pipe and multiple pipes,
+* make sure the other active pipe is prepared
+* for having its FIFO resized. We do that by making
+* sure the pipe isn't using LP1+ watermarks when
+* the second pipe gets enabled or disabled.
+*/
+   if (!other_active_crtc)
+   return;
+
+   ilk_wm_synchronize(other_active_crtc);
+
+   if (ilk_disable_lp_wm(dev))
+   intel_wait_for_vblank(dev, other_active_crtc->pipe);
+}
+
 static void ironlake_crtc_enable(struct drm_crtc *crtc)
 {
struct drm_device *dev = crtc->dev;
@@ -4023,6 +4044,9 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
 
intel_crtc->active = true;
 
+   /* Make sure other pipes are prepared for FIFO resizing */
+   ilk_prepare_for_num_pipes_change(intel_crtc);
+
intel_set_cpu_fifo_underrun_reporting(dev, pipe, true);
intel_set_pch_fifo_underrun_reporting(dev, pipe, true);
 
@@ -4123,6 +4147,9 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
 
intel_crtc->active = true;
 
+   /* Make sure other pipes are prepared for FIFO resizing */
+   ilk_prepare_for_num_pipes_change(intel_crtc);
+
intel_set_cpu_fifo_underrun_reporting(dev, pipe, true);
if (intel_crtc->config.has_pch_encoder)
intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A, true);
@@ -4192,6 +4219,9 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
 
intel_crtc_disable_planes(crtc);
 
+   /* Make sure other pipes are prepared for FIFO resizing */
+   ilk_prepare_for_num_pipes_change(intel_crtc);
+
for_each_encoder_on_crtc(dev, crtc, encoder)
encoder->disable(encoder);
 
@@ -4235,6 +4265,12 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
 
intel_crtc->active = false;
 
+   /*
+* Potentially let some other pipe use the
+* full FIFO, and re-enable LP1+ watermarks.
+*/
+   ilk_wm_pipe_post_disable(intel_crtc);
+
mutex_lock(&dev->struct_mutex);
intel_update_fbc(dev);
intel_edp_psr_update(dev);
@@ -4255,6 +4291,9 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
 
intel_crtc_disable_planes(crtc);
 
+   /* Make sure other pipes are prepared for FIFO resizing */
+   ilk_prepare_for_num_pipes_change(intel_crtc);
+
for_each_encoder_on_crtc(dev, crtc, encoder) {
intel_opregion_notify_encoder(encoder, false);
encoder->disable(encoder);
@@ -4282,6 +4321,12 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
 
intel_crtc->active = false;
 
+   /*
+* Potentially let some other pipe use the
+* full FIFO, and re-enable LP1+ watermarks.
+*/
+   ilk_wm_pipe_post_disable(intel_crtc);
+
mutex_lock(&dev->struct_mutex);
intel_update_fbc(dev);
intel_edp_psr_update(dev);
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 5ad7ad5..98f878f 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -1022,6 +1022,8 @@ void intel_program_watermarks_pre(struct intel_crtc *crtc,
 void intel_program_watermarks_post(struct intel_crtc *crtc,
   const struct intel_crtc_wm_config *config);
 void ilk_wm_synchronize(struct intel_crtc *crtc);
+void ilk_wm_pipe_post_disable(struct intel_crtc *crtc);
+bool ilk_disable_lp_wm(struct drm_device *dev);
 
 
 /* intel_sdvo.c */
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index 1c072cd..18ea8b1 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -2765,7 +2765,7 @@ static void ilk_write_wm_values(struct drm_i915_private 
*dev_priv,
}
 }
 
-static bool il

Re: [Intel-gfx] [PATCH 12/16] drm/i915: Disable LP1+ watermarks while changing the number of active pipes

2014-06-04 Thread Paulo Zanoni
2014-05-22 11:48 GMT-03:00  :
> From: Ville Syrjälä 
>
> When we switch between one active pipe and multiple active pipes, the
> display FIFO gets repartitioned. Disable the LP1+ waterwarks while that
> is happening to make sure we don't get any glitches on other active
> pipes while doing a modeset on another other pipe.
>
> Signed-off-by: Ville Syrjälä 
> ---
>  drivers/gpu/drm/i915/intel_display.c | 45 ++
>  drivers/gpu/drm/i915/intel_drv.h |  2 ++
>  drivers/gpu/drm/i915/intel_pm.c  | 47 
> 
>  3 files changed, 89 insertions(+), 5 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/intel_display.c 
> b/drivers/gpu/drm/i915/intel_display.c
> index bccf414..311c0f0 100644
> --- a/drivers/gpu/drm/i915/intel_display.c
> +++ b/drivers/gpu/drm/i915/intel_display.c
> @@ -3985,6 +3985,27 @@ static struct intel_crtc *get_other_active_crtc(struct 
> intel_crtc *crtc)
> return other_active_crtc;
>  }
>
> +static void ilk_prepare_for_num_pipes_change(struct intel_crtc *crtc)
> +{
> +   struct drm_device *dev = crtc->base.dev;
> +   struct intel_crtc *other_active_crtc = get_other_active_crtc(crtc);
> +
> +   /*
> +* If we change between one pipe and multiple pipes,
> +* make sure the other active pipe is prepared
> +* for having its FIFO resized. We do that by making
> +* sure the pipe isn't using LP1+ watermarks when
> +* the second pipe gets enabled or disabled.
> +*/
> +   if (!other_active_crtc)
> +   return;

But get_other_active_crtc() returns NULL in case 2 other CRTCs are
already active. If we're the third pipe being enabled, we may still
get an underrun.

> +
> +   ilk_wm_synchronize(other_active_crtc);
> +
> +   if (ilk_disable_lp_wm(dev))
> +   intel_wait_for_vblank(dev, other_active_crtc->pipe);
> +}
> +
>  static void ironlake_crtc_enable(struct drm_crtc *crtc)
>  {
> struct drm_device *dev = crtc->dev;
> @@ -4023,6 +4044,9 @@ static void ironlake_crtc_enable(struct drm_crtc *crtc)
>
> intel_crtc->active = true;
>
> +   /* Make sure other pipes are prepared for FIFO resizing */
> +   ilk_prepare_for_num_pipes_change(intel_crtc);
> +
> intel_set_cpu_fifo_underrun_reporting(dev, pipe, true);
> intel_set_pch_fifo_underrun_reporting(dev, pipe, true);
>
> @@ -4123,6 +4147,9 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
>
> intel_crtc->active = true;
>
> +   /* Make sure other pipes are prepared for FIFO resizing */
> +   ilk_prepare_for_num_pipes_change(intel_crtc);
> +
> intel_set_cpu_fifo_underrun_reporting(dev, pipe, true);
> if (intel_crtc->config.has_pch_encoder)
> intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A, 
> true);
> @@ -4192,6 +4219,9 @@ static void ironlake_crtc_disable(struct drm_crtc *crtc)
>
> intel_crtc_disable_planes(crtc);
>
> +   /* Make sure other pipes are prepared for FIFO resizing */
> +   ilk_prepare_for_num_pipes_change(intel_crtc);
> +
> for_each_encoder_on_crtc(dev, crtc, encoder)
> encoder->disable(encoder);
>
> @@ -4235,6 +4265,12 @@ static void ironlake_crtc_disable(struct drm_crtc 
> *crtc)
>
> intel_crtc->active = false;
>
> +   /*
> +* Potentially let some other pipe use the
> +* full FIFO, and re-enable LP1+ watermarks.
> +*/
> +   ilk_wm_pipe_post_disable(intel_crtc);
> +
> mutex_lock(&dev->struct_mutex);
> intel_update_fbc(dev);
> intel_edp_psr_update(dev);
> @@ -4255,6 +4291,9 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
>
> intel_crtc_disable_planes(crtc);
>
> +   /* Make sure other pipes are prepared for FIFO resizing */
> +   ilk_prepare_for_num_pipes_change(intel_crtc);
> +
> for_each_encoder_on_crtc(dev, crtc, encoder) {
> intel_opregion_notify_encoder(encoder, false);
> encoder->disable(encoder);
> @@ -4282,6 +4321,12 @@ static void haswell_crtc_disable(struct drm_crtc *crtc)
>
> intel_crtc->active = false;
>
> +   /*
> +* Potentially let some other pipe use the
> +* full FIFO, and re-enable LP1+ watermarks.
> +*/
> +   ilk_wm_pipe_post_disable(intel_crtc);
> +
> mutex_lock(&dev->struct_mutex);
> intel_update_fbc(dev);
> intel_edp_psr_update(dev);
> diff --git a/drivers/gpu/drm/i915/intel_drv.h 
> b/drivers/gpu/drm/i915/intel_drv.h
> index 5ad7ad5..98f878f 100644
> --- a/drivers/gpu/drm/i915/intel_drv.h
> +++ b/drivers/gpu/drm/i915/intel_drv.h
> @@ -1022,6 +1022,8 @@ void intel_program_watermarks_pre(struct intel_crtc 
> *crtc,
>  void intel_program_watermarks_post(struct intel_crtc *crtc,
>const struct intel_crtc_wm_config *config);
>  void ilk_wm_synchronize(struct intel_crtc *crtc);
> +void ilk_wm_pipe_post_

Re: [Intel-gfx] [PATCH 12/16] drm/i915: Disable LP1+ watermarks while changing the number of active pipes

2014-06-09 Thread Ville Syrjälä
On Wed, Jun 04, 2014 at 03:24:13PM -0300, Paulo Zanoni wrote:
> 2014-05-22 11:48 GMT-03:00  :
> > From: Ville Syrjälä 
> >
> > When we switch between one active pipe and multiple active pipes, the
> > display FIFO gets repartitioned. Disable the LP1+ waterwarks while that
> > is happening to make sure we don't get any glitches on other active
> > pipes while doing a modeset on another other pipe.
> >
> > Signed-off-by: Ville Syrjälä 
> > ---
> >  drivers/gpu/drm/i915/intel_display.c | 45 
> > ++
> >  drivers/gpu/drm/i915/intel_drv.h |  2 ++
> >  drivers/gpu/drm/i915/intel_pm.c  | 47 
> > 
> >  3 files changed, 89 insertions(+), 5 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/i915/intel_display.c 
> > b/drivers/gpu/drm/i915/intel_display.c
> > index bccf414..311c0f0 100644
> > --- a/drivers/gpu/drm/i915/intel_display.c
> > +++ b/drivers/gpu/drm/i915/intel_display.c
> > @@ -3985,6 +3985,27 @@ static struct intel_crtc 
> > *get_other_active_crtc(struct intel_crtc *crtc)
> > return other_active_crtc;
> >  }
> >
> > +static void ilk_prepare_for_num_pipes_change(struct intel_crtc *crtc)
> > +{
> > +   struct drm_device *dev = crtc->base.dev;
> > +   struct intel_crtc *other_active_crtc = get_other_active_crtc(crtc);
> > +
> > +   /*
> > +* If we change between one pipe and multiple pipes,
> > +* make sure the other active pipe is prepared
> > +* for having its FIFO resized. We do that by making
> > +* sure the pipe isn't using LP1+ watermarks when
> > +* the second pipe gets enabled or disabled.
> > +*/
> > +   if (!other_active_crtc)
> > +   return;
> 
> But get_other_active_crtc() returns NULL in case 2 other CRTCs are
> already active. If we're the third pipe being enabled, we may still
> get an underrun.

The FIFO repartitioning happens only when going 1<->2 pipes, so the
2<->3 cases don't matter here.

> 
> > +
> > +   ilk_wm_synchronize(other_active_crtc);
> > +
> > +   if (ilk_disable_lp_wm(dev))
> > +   intel_wait_for_vblank(dev, other_active_crtc->pipe);
> > +}
> > +
> >  static void ironlake_crtc_enable(struct drm_crtc *crtc)
> >  {
> > struct drm_device *dev = crtc->dev;
> > @@ -4023,6 +4044,9 @@ static void ironlake_crtc_enable(struct drm_crtc 
> > *crtc)
> >
> > intel_crtc->active = true;
> >
> > +   /* Make sure other pipes are prepared for FIFO resizing */
> > +   ilk_prepare_for_num_pipes_change(intel_crtc);
> > +
> > intel_set_cpu_fifo_underrun_reporting(dev, pipe, true);
> > intel_set_pch_fifo_underrun_reporting(dev, pipe, true);
> >
> > @@ -4123,6 +4147,9 @@ static void haswell_crtc_enable(struct drm_crtc *crtc)
> >
> > intel_crtc->active = true;
> >
> > +   /* Make sure other pipes are prepared for FIFO resizing */
> > +   ilk_prepare_for_num_pipes_change(intel_crtc);
> > +
> > intel_set_cpu_fifo_underrun_reporting(dev, pipe, true);
> > if (intel_crtc->config.has_pch_encoder)
> > intel_set_pch_fifo_underrun_reporting(dev, TRANSCODER_A, 
> > true);
> > @@ -4192,6 +4219,9 @@ static void ironlake_crtc_disable(struct drm_crtc 
> > *crtc)
> >
> > intel_crtc_disable_planes(crtc);
> >
> > +   /* Make sure other pipes are prepared for FIFO resizing */
> > +   ilk_prepare_for_num_pipes_change(intel_crtc);
> > +
> > for_each_encoder_on_crtc(dev, crtc, encoder)
> > encoder->disable(encoder);
> >
> > @@ -4235,6 +4265,12 @@ static void ironlake_crtc_disable(struct drm_crtc 
> > *crtc)
> >
> > intel_crtc->active = false;
> >
> > +   /*
> > +* Potentially let some other pipe use the
> > +* full FIFO, and re-enable LP1+ watermarks.
> > +*/
> > +   ilk_wm_pipe_post_disable(intel_crtc);
> > +
> > mutex_lock(&dev->struct_mutex);
> > intel_update_fbc(dev);
> > intel_edp_psr_update(dev);
> > @@ -4255,6 +4291,9 @@ static void haswell_crtc_disable(struct drm_crtc 
> > *crtc)
> >
> > intel_crtc_disable_planes(crtc);
> >
> > +   /* Make sure other pipes are prepared for FIFO resizing */
> > +   ilk_prepare_for_num_pipes_change(intel_crtc);
> > +
> > for_each_encoder_on_crtc(dev, crtc, encoder) {
> > intel_opregion_notify_encoder(encoder, false);
> > encoder->disable(encoder);
> > @@ -4282,6 +4321,12 @@ static void haswell_crtc_disable(struct drm_crtc 
> > *crtc)
> >
> > intel_crtc->active = false;
> >
> > +   /*
> > +* Potentially let some other pipe use the
> > +* full FIFO, and re-enable LP1+ watermarks.
> > +*/
> > +   ilk_wm_pipe_post_disable(intel_crtc);
> > +
> > mutex_lock(&dev->struct_mutex);
> > intel_update_fbc(dev);
> > intel_edp_psr_update(dev);
> > diff --git a/drivers/gpu/drm/i915/intel_drv.h 
> > b/drivers/gpu/drm/i