diff mbox

[2/3] drm/rockchip: Don't key off vblank for psr

Message ID 1471563251-28754-3-git-send-email-seanpaul@chromium.org (mailing list archive)
State New, archived
Headers show

Commit Message

Sean Paul Aug. 18, 2016, 11:34 p.m. UTC
Instead of keying off vblank for psr, just flush every time
we get an atomic update. This ensures that cursor updates
will properly disable psr (without turning vblank on/off),
and unifies the paths between fb_dirty and atomic psr
enable/disable.

Signed-off-by: Sean Paul <seanpaul@chromium.org>
---
 drivers/gpu/drm/rockchip/rockchip_drm_fb.c  |  2 +-
 drivers/gpu/drm/rockchip/rockchip_drm_psr.c | 72 ++++++++++++++++++++---------
 drivers/gpu/drm/rockchip/rockchip_drm_psr.h |  8 ++--
 drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 10 ++--
 4 files changed, 62 insertions(+), 30 deletions(-)

Comments

Yakir Yang Aug. 26, 2016, 2:30 a.m. UTC | #1
Sean,

Thanks for this good fix.

On 08/19/2016 07:34 AM, Sean Paul wrote:
> Instead of keying off vblank for psr, just flush every time
> we get an atomic update. This ensures that cursor updates
> will properly disable psr (without turning vblank on/off),
> and unifies the paths between fb_dirty and atomic psr
> enable/disable.
>
> Signed-off-by: Sean Paul <seanpaul@chromium.org>

Reviewed-by: Yakir Yang <ykk@rock-chips.com>

Also I have verified this patch on RK3399 Kevin, eDP PSR works rightly, so

Tested-by: Yakir Yang <ykk@rock-chips.com>

- Yakir

> ---
>   drivers/gpu/drm/rockchip/rockchip_drm_fb.c  |  2 +-
>   drivers/gpu/drm/rockchip/rockchip_drm_psr.c | 72 ++++++++++++++++++++---------
>   drivers/gpu/drm/rockchip/rockchip_drm_psr.h |  8 ++--
>   drivers/gpu/drm/rockchip/rockchip_drm_vop.c | 10 ++--
>   4 files changed, 62 insertions(+), 30 deletions(-)
>
> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
> index ba45d9d..10cafbc 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
> @@ -70,7 +70,7 @@ static int rockchip_drm_fb_dirty(struct drm_framebuffer *fb,
>   				 struct drm_clip_rect *clips,
>   				 unsigned int num_clips)
>   {
> -	rockchip_drm_psr_flush(fb->dev);
> +	rockchip_drm_psr_flush_all(fb->dev);
>   	return 0;
>   }
>   
> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_psr.c b/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
> index c6ac5d0..de6252f 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
> @@ -31,6 +31,7 @@ struct psr_drv {
>   	struct drm_encoder	*encoder;
>   
>   	spinlock_t		lock;
> +	bool			active;
>   	enum psr_state		state;
>   
>   	struct timer_list	flush_timer;
> @@ -67,11 +68,7 @@ static void psr_set_state_locked(struct psr_drv *psr, enum psr_state state)
>   	 *       v |                        |
>   	 *   PSR_DISABLE < - - - - - - - - -
>   	 */
> -	if (state == psr->state)
> -		return;
> -
> -	/* Requesting a flush when disabled is a noop */
> -	if (state == PSR_FLUSH && psr->state == PSR_DISABLE)
> +	if (state == psr->state || !psr->active)
>   		return;
>   
>   	psr->state = state;
> @@ -115,45 +112,79 @@ static void psr_flush_handler(unsigned long data)
>   }
>   
>   /**
> - * rockchip_drm_psr_enable - enable the encoder PSR which bind to given CRTC
> + * rockchip_drm_psr_activate - activate PSR on the given pipe
>    * @crtc: CRTC to obtain the PSR encoder
>    *
>    * Returns:
>    * Zero on success, negative errno on failure.
>    */
> -int rockchip_drm_psr_enable(struct drm_crtc *crtc)
> +int rockchip_drm_psr_activate(struct drm_crtc *crtc)
>   {
>   	struct psr_drv *psr = find_psr_by_crtc(crtc);
> +	unsigned long flags;
>   
>   	if (IS_ERR(psr))
>   		return PTR_ERR(psr);
>   
> -	psr_set_state(psr, PSR_ENABLE);
> +	spin_lock_irqsave(&psr->lock, flags);
> +	psr->active = true;
> +	spin_unlock_irqrestore(&psr->lock, flags);
> +
>   	return 0;
>   }
> -EXPORT_SYMBOL(rockchip_drm_psr_enable);
> +EXPORT_SYMBOL(rockchip_drm_psr_activate);
>   
>   /**
> - * rockchip_drm_psr_disable - disable the encoder PSR which bind to given CRTC
> + * rockchip_drm_psr_deactivate - deactivate PSR on the given pipe
>    * @crtc: CRTC to obtain the PSR encoder
>    *
>    * Returns:
>    * Zero on success, negative errno on failure.
>    */
> -int rockchip_drm_psr_disable(struct drm_crtc *crtc)
> +int rockchip_drm_psr_deactivate(struct drm_crtc *crtc)
>   {
>   	struct psr_drv *psr = find_psr_by_crtc(crtc);
> +	unsigned long flags;
> +
> +	if (IS_ERR(psr))
> +		return PTR_ERR(psr);
> +
> +	spin_lock_irqsave(&psr->lock, flags);
> +	psr->active = false;
> +	spin_unlock_irqrestore(&psr->lock, flags);
> +	del_timer_sync(&psr->flush_timer);
> +
> +	return 0;
> +}
> +EXPORT_SYMBOL(rockchip_drm_psr_deactivate);
> +
> +static void rockchip_drm_do_flush(struct psr_drv *psr)
> +{
> +	mod_timer(&psr->flush_timer,
> +		  round_jiffies_up(jiffies + PSR_FLUSH_TIMEOUT));
> +	psr_set_state(psr, PSR_FLUSH);
> +}
>   
> +/**
> + * rockchip_drm_psr_flush - flush a single pipe
> + * @crtc: CRTC of the pipe to flush
> + *
> + * Returns:
> + * 0 on success, -errno on fail
> + */
> +int rockchip_drm_psr_flush(struct drm_crtc *crtc)
> +{
> +	struct psr_drv *psr = find_psr_by_crtc(crtc);
>   	if (IS_ERR(psr))
>   		return PTR_ERR(psr);
>   
> -	psr_set_state(psr, PSR_DISABLE);
> +	rockchip_drm_do_flush(psr);
>   	return 0;
>   }
> -EXPORT_SYMBOL(rockchip_drm_psr_disable);
> +EXPORT_SYMBOL(rockchip_drm_psr_flush);
>   
>   /**
> - * rockchip_drm_psr_flush - force to flush all registered PSR encoders
> + * rockchip_drm_psr_flush_all - force to flush all registered PSR encoders
>    * @dev: drm device
>    *
>    * Disable the PSR function for all registered encoders, and then enable the
> @@ -164,22 +195,18 @@ EXPORT_SYMBOL(rockchip_drm_psr_disable);
>    * Returns:
>    * Zero on success, negative errno on failure.
>    */
> -void rockchip_drm_psr_flush(struct drm_device *dev)
> +void rockchip_drm_psr_flush_all(struct drm_device *dev)
>   {
>   	struct rockchip_drm_private *drm_drv = dev->dev_private;
>   	struct psr_drv *psr;
>   	unsigned long flags;
>   
>   	spin_lock_irqsave(&drm_drv->psr_list_lock, flags);
> -	list_for_each_entry(psr, &drm_drv->psr_list, list) {
> -		mod_timer(&psr->flush_timer,
> -			  round_jiffies_up(jiffies + PSR_FLUSH_TIMEOUT));
> -
> -		psr_set_state(psr, PSR_FLUSH);
> -	}
> +	list_for_each_entry(psr, &drm_drv->psr_list, list)
> +		rockchip_drm_do_flush(psr);
>   	spin_unlock_irqrestore(&drm_drv->psr_list_lock, flags);
>   }
> -EXPORT_SYMBOL(rockchip_drm_psr_flush);
> +EXPORT_SYMBOL(rockchip_drm_psr_flush_all);
>   
>   /**
>    * rockchip_drm_psr_register - register encoder to psr driver
> @@ -206,6 +233,7 @@ int rockchip_drm_psr_register(struct drm_encoder *encoder,
>   	setup_timer(&psr->flush_timer, psr_flush_handler, (unsigned long)psr);
>   	spin_lock_init(&psr->lock);
>   
> +	psr->active = true;
>   	psr->state = PSR_DISABLE;
>   	psr->encoder = encoder;
>   	psr->set = psr_set;
> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_psr.h b/drivers/gpu/drm/rockchip/rockchip_drm_psr.h
> index c35b688..b420cf1 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_drm_psr.h
> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_psr.h
> @@ -15,9 +15,11 @@
>   #ifndef __ROCKCHIP_DRM_PSR___
>   #define __ROCKCHIP_DRM_PSR___
>   
> -void rockchip_drm_psr_flush(struct drm_device *dev);
> -int rockchip_drm_psr_enable(struct drm_crtc *crtc);
> -int rockchip_drm_psr_disable(struct drm_crtc *crtc);
> +void rockchip_drm_psr_flush_all(struct drm_device *dev);
> +int rockchip_drm_psr_flush(struct drm_crtc *crtc);
> +
> +int rockchip_drm_psr_activate(struct drm_crtc *crtc);
> +int rockchip_drm_psr_deactivate(struct drm_crtc *crtc);
>   
>   int rockchip_drm_psr_register(struct drm_encoder *encoder,
>   			void (*psr_set)(struct drm_encoder *, bool enable));
> diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
> index 7003e4d..354f814 100644
> --- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
> +++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
> @@ -573,6 +573,8 @@ static void vop_crtc_disable(struct drm_crtc *crtc)
>   
>   	WARN_ON(vop->event);
>   
> +	rockchip_drm_psr_deactivate(&vop->crtc);
> +
>   	/*
>   	 * We need to make sure that all windows are disabled before we
>   	 * disable that crtc. Otherwise we might try to scan from a destroyed
> @@ -938,8 +940,6 @@ static int vop_crtc_enable_vblank(struct drm_crtc *crtc)
>   
>   	spin_unlock_irqrestore(&vop->irq_lock, flags);
>   
> -	rockchip_drm_psr_disable(&vop->crtc);
> -
>   	return 0;
>   }
>   
> @@ -956,8 +956,6 @@ static void vop_crtc_disable_vblank(struct drm_crtc *crtc)
>   	VOP_INTR_SET_TYPE(vop, enable, FS_INTR, 0);
>   
>   	spin_unlock_irqrestore(&vop->irq_lock, flags);
> -
> -	rockchip_drm_psr_enable(&vop->crtc);
>   }
>   
>   static void vop_crtc_wait_for_update(struct drm_crtc *crtc)
> @@ -1084,6 +1082,8 @@ static void vop_crtc_enable(struct drm_crtc *crtc)
>   	clk_set_rate(vop->dclk, adjusted_mode->clock * 1000);
>   
>   	VOP_CTRL_SET(vop, standby, 0);
> +
> +	rockchip_drm_psr_activate(&vop->crtc);
>   }
>   
>   static void vop_crtc_atomic_flush(struct drm_crtc *crtc,
> @@ -1106,6 +1106,8 @@ static void vop_crtc_atomic_begin(struct drm_crtc *crtc,
>   {
>   	struct vop *vop = to_vop(crtc);
>   
> +	rockchip_drm_psr_flush(crtc);
> +
>   	spin_lock_irq(&crtc->dev->event_lock);
>   	if (crtc->state->event) {
>   		vop->event = crtc->state->event;
diff mbox

Patch

diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
index ba45d9d..10cafbc 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_fb.c
@@ -70,7 +70,7 @@  static int rockchip_drm_fb_dirty(struct drm_framebuffer *fb,
 				 struct drm_clip_rect *clips,
 				 unsigned int num_clips)
 {
-	rockchip_drm_psr_flush(fb->dev);
+	rockchip_drm_psr_flush_all(fb->dev);
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_psr.c b/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
index c6ac5d0..de6252f 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_psr.c
@@ -31,6 +31,7 @@  struct psr_drv {
 	struct drm_encoder	*encoder;
 
 	spinlock_t		lock;
+	bool			active;
 	enum psr_state		state;
 
 	struct timer_list	flush_timer;
@@ -67,11 +68,7 @@  static void psr_set_state_locked(struct psr_drv *psr, enum psr_state state)
 	 *       v |                        |
 	 *   PSR_DISABLE < - - - - - - - - -
 	 */
-	if (state == psr->state)
-		return;
-
-	/* Requesting a flush when disabled is a noop */
-	if (state == PSR_FLUSH && psr->state == PSR_DISABLE)
+	if (state == psr->state || !psr->active)
 		return;
 
 	psr->state = state;
@@ -115,45 +112,79 @@  static void psr_flush_handler(unsigned long data)
 }
 
 /**
- * rockchip_drm_psr_enable - enable the encoder PSR which bind to given CRTC
+ * rockchip_drm_psr_activate - activate PSR on the given pipe
  * @crtc: CRTC to obtain the PSR encoder
  *
  * Returns:
  * Zero on success, negative errno on failure.
  */
-int rockchip_drm_psr_enable(struct drm_crtc *crtc)
+int rockchip_drm_psr_activate(struct drm_crtc *crtc)
 {
 	struct psr_drv *psr = find_psr_by_crtc(crtc);
+	unsigned long flags;
 
 	if (IS_ERR(psr))
 		return PTR_ERR(psr);
 
-	psr_set_state(psr, PSR_ENABLE);
+	spin_lock_irqsave(&psr->lock, flags);
+	psr->active = true;
+	spin_unlock_irqrestore(&psr->lock, flags);
+
 	return 0;
 }
-EXPORT_SYMBOL(rockchip_drm_psr_enable);
+EXPORT_SYMBOL(rockchip_drm_psr_activate);
 
 /**
- * rockchip_drm_psr_disable - disable the encoder PSR which bind to given CRTC
+ * rockchip_drm_psr_deactivate - deactivate PSR on the given pipe
  * @crtc: CRTC to obtain the PSR encoder
  *
  * Returns:
  * Zero on success, negative errno on failure.
  */
-int rockchip_drm_psr_disable(struct drm_crtc *crtc)
+int rockchip_drm_psr_deactivate(struct drm_crtc *crtc)
 {
 	struct psr_drv *psr = find_psr_by_crtc(crtc);
+	unsigned long flags;
+
+	if (IS_ERR(psr))
+		return PTR_ERR(psr);
+
+	spin_lock_irqsave(&psr->lock, flags);
+	psr->active = false;
+	spin_unlock_irqrestore(&psr->lock, flags);
+	del_timer_sync(&psr->flush_timer);
+
+	return 0;
+}
+EXPORT_SYMBOL(rockchip_drm_psr_deactivate);
+
+static void rockchip_drm_do_flush(struct psr_drv *psr)
+{
+	mod_timer(&psr->flush_timer,
+		  round_jiffies_up(jiffies + PSR_FLUSH_TIMEOUT));
+	psr_set_state(psr, PSR_FLUSH);
+}
 
+/**
+ * rockchip_drm_psr_flush - flush a single pipe
+ * @crtc: CRTC of the pipe to flush
+ *
+ * Returns:
+ * 0 on success, -errno on fail
+ */
+int rockchip_drm_psr_flush(struct drm_crtc *crtc)
+{
+	struct psr_drv *psr = find_psr_by_crtc(crtc);
 	if (IS_ERR(psr))
 		return PTR_ERR(psr);
 
-	psr_set_state(psr, PSR_DISABLE);
+	rockchip_drm_do_flush(psr);
 	return 0;
 }
-EXPORT_SYMBOL(rockchip_drm_psr_disable);
+EXPORT_SYMBOL(rockchip_drm_psr_flush);
 
 /**
- * rockchip_drm_psr_flush - force to flush all registered PSR encoders
+ * rockchip_drm_psr_flush_all - force to flush all registered PSR encoders
  * @dev: drm device
  *
  * Disable the PSR function for all registered encoders, and then enable the
@@ -164,22 +195,18 @@  EXPORT_SYMBOL(rockchip_drm_psr_disable);
  * Returns:
  * Zero on success, negative errno on failure.
  */
-void rockchip_drm_psr_flush(struct drm_device *dev)
+void rockchip_drm_psr_flush_all(struct drm_device *dev)
 {
 	struct rockchip_drm_private *drm_drv = dev->dev_private;
 	struct psr_drv *psr;
 	unsigned long flags;
 
 	spin_lock_irqsave(&drm_drv->psr_list_lock, flags);
-	list_for_each_entry(psr, &drm_drv->psr_list, list) {
-		mod_timer(&psr->flush_timer,
-			  round_jiffies_up(jiffies + PSR_FLUSH_TIMEOUT));
-
-		psr_set_state(psr, PSR_FLUSH);
-	}
+	list_for_each_entry(psr, &drm_drv->psr_list, list)
+		rockchip_drm_do_flush(psr);
 	spin_unlock_irqrestore(&drm_drv->psr_list_lock, flags);
 }
-EXPORT_SYMBOL(rockchip_drm_psr_flush);
+EXPORT_SYMBOL(rockchip_drm_psr_flush_all);
 
 /**
  * rockchip_drm_psr_register - register encoder to psr driver
@@ -206,6 +233,7 @@  int rockchip_drm_psr_register(struct drm_encoder *encoder,
 	setup_timer(&psr->flush_timer, psr_flush_handler, (unsigned long)psr);
 	spin_lock_init(&psr->lock);
 
+	psr->active = true;
 	psr->state = PSR_DISABLE;
 	psr->encoder = encoder;
 	psr->set = psr_set;
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_psr.h b/drivers/gpu/drm/rockchip/rockchip_drm_psr.h
index c35b688..b420cf1 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_psr.h
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_psr.h
@@ -15,9 +15,11 @@ 
 #ifndef __ROCKCHIP_DRM_PSR___
 #define __ROCKCHIP_DRM_PSR___
 
-void rockchip_drm_psr_flush(struct drm_device *dev);
-int rockchip_drm_psr_enable(struct drm_crtc *crtc);
-int rockchip_drm_psr_disable(struct drm_crtc *crtc);
+void rockchip_drm_psr_flush_all(struct drm_device *dev);
+int rockchip_drm_psr_flush(struct drm_crtc *crtc);
+
+int rockchip_drm_psr_activate(struct drm_crtc *crtc);
+int rockchip_drm_psr_deactivate(struct drm_crtc *crtc);
 
 int rockchip_drm_psr_register(struct drm_encoder *encoder,
 			void (*psr_set)(struct drm_encoder *, bool enable));
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
index 7003e4d..354f814 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_vop.c
@@ -573,6 +573,8 @@  static void vop_crtc_disable(struct drm_crtc *crtc)
 
 	WARN_ON(vop->event);
 
+	rockchip_drm_psr_deactivate(&vop->crtc);
+
 	/*
 	 * We need to make sure that all windows are disabled before we
 	 * disable that crtc. Otherwise we might try to scan from a destroyed
@@ -938,8 +940,6 @@  static int vop_crtc_enable_vblank(struct drm_crtc *crtc)
 
 	spin_unlock_irqrestore(&vop->irq_lock, flags);
 
-	rockchip_drm_psr_disable(&vop->crtc);
-
 	return 0;
 }
 
@@ -956,8 +956,6 @@  static void vop_crtc_disable_vblank(struct drm_crtc *crtc)
 	VOP_INTR_SET_TYPE(vop, enable, FS_INTR, 0);
 
 	spin_unlock_irqrestore(&vop->irq_lock, flags);
-
-	rockchip_drm_psr_enable(&vop->crtc);
 }
 
 static void vop_crtc_wait_for_update(struct drm_crtc *crtc)
@@ -1084,6 +1082,8 @@  static void vop_crtc_enable(struct drm_crtc *crtc)
 	clk_set_rate(vop->dclk, adjusted_mode->clock * 1000);
 
 	VOP_CTRL_SET(vop, standby, 0);
+
+	rockchip_drm_psr_activate(&vop->crtc);
 }
 
 static void vop_crtc_atomic_flush(struct drm_crtc *crtc,
@@ -1106,6 +1106,8 @@  static void vop_crtc_atomic_begin(struct drm_crtc *crtc,
 {
 	struct vop *vop = to_vop(crtc);
 
+	rockchip_drm_psr_flush(crtc);
+
 	spin_lock_irq(&crtc->dev->event_lock);
 	if (crtc->state->event) {
 		vop->event = crtc->state->event;