diff mbox series

[1/5] drm/vblank: Introduce drm_crtc_vblank_crtc()

Message ID 20240408190611.24914-1-ville.syrjala@linux.intel.com (mailing list archive)
State New
Headers show
Series [1/5] drm/vblank: Introduce drm_crtc_vblank_crtc() | expand

Commit Message

Ville Syrjala April 8, 2024, 7:06 p.m. UTC
From: Ville Syrjälä <ville.syrjala@linux.intel.com>

Make life easier by providing a function that hands
out the the correct drm_vblank_crtc for a given a drm_crtc.

Also abstract the lower level internals of the vblank
code in a similar fashion.

Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
---
 drivers/gpu/drm/drm_vblank.c      | 58 ++++++++++++++++++-------------
 drivers/gpu/drm/drm_vblank_work.c |  2 +-
 include/drm/drm_vblank.h          |  1 +
 3 files changed, 36 insertions(+), 25 deletions(-)

Comments

Dmitry Baryshkov April 9, 2024, 3:02 p.m. UTC | #1
On Mon, Apr 08, 2024 at 10:06:07PM +0300, Ville Syrjala wrote:
> From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> 
> Make life easier by providing a function that hands
> out the the correct drm_vblank_crtc for a given a drm_crtc.
> 
> Also abstract the lower level internals of the vblank
> code in a similar fashion.
> 
> Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> ---
>  drivers/gpu/drm/drm_vblank.c      | 58 ++++++++++++++++++-------------
>  drivers/gpu/drm/drm_vblank_work.c |  2 +-
>  include/drm/drm_vblank.h          |  1 +
>  3 files changed, 36 insertions(+), 25 deletions(-)


Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>

I'm looking forward to using this in drm/msm

> 
> diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c
> index 702a12bc93bd..cc3571e25a9a 100644
> --- a/drivers/gpu/drm/drm_vblank.c
> +++ b/drivers/gpu/drm/drm_vblank.c
> @@ -166,11 +166,24 @@ module_param_named(timestamp_precision_usec, drm_timestamp_precision, int, 0600)
>  MODULE_PARM_DESC(vblankoffdelay, "Delay until vblank irq auto-disable [msecs] (0: never disable, <0: disable immediately)");
>  MODULE_PARM_DESC(timestamp_precision_usec, "Max. error on timestamps [usecs]");
>  
> +static struct drm_vblank_crtc *
> +drm_vblank_crtc(struct drm_device *dev, unsigned int pipe)
> +{
> +	return &dev->vblank[pipe];
> +}
> +
> +struct drm_vblank_crtc *
> +drm_crtc_vblank_crtc(struct drm_crtc *crtc)
> +{
> +	return drm_vblank_crtc(crtc->dev, drm_crtc_index(crtc));
> +}
> +EXPORT_SYMBOL(drm_crtc_vblank_crtc);
> +
>  static void store_vblank(struct drm_device *dev, unsigned int pipe,
>  			 u32 vblank_count_inc,
>  			 ktime_t t_vblank, u32 last)
>  {
> -	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
> +	struct drm_vblank_crtc *vblank = drm_vblank_crtc(dev, pipe);
>  
>  	assert_spin_locked(&dev->vblank_time_lock);
>  
> @@ -184,7 +197,7 @@ static void store_vblank(struct drm_device *dev, unsigned int pipe,
>  
>  static u32 drm_max_vblank_count(struct drm_device *dev, unsigned int pipe)
>  {
> -	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
> +	struct drm_vblank_crtc *vblank = drm_vblank_crtc(dev, pipe);
>  
>  	return vblank->max_vblank_count ?: dev->max_vblank_count;
>  }
> @@ -273,7 +286,7 @@ static void drm_reset_vblank_timestamp(struct drm_device *dev, unsigned int pipe
>  static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe,
>  				    bool in_vblank_irq)
>  {
> -	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
> +	struct drm_vblank_crtc *vblank = drm_vblank_crtc(dev, pipe);
>  	u32 cur_vblank, diff;
>  	bool rc;
>  	ktime_t t_vblank;
> @@ -364,7 +377,7 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe,
>  
>  u64 drm_vblank_count(struct drm_device *dev, unsigned int pipe)
>  {
> -	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
> +	struct drm_vblank_crtc *vblank = drm_vblank_crtc(dev, pipe);
>  	u64 count;
>  
>  	if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
> @@ -438,7 +451,7 @@ static void __disable_vblank(struct drm_device *dev, unsigned int pipe)
>   */
>  void drm_vblank_disable_and_save(struct drm_device *dev, unsigned int pipe)
>  {
> -	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
> +	struct drm_vblank_crtc *vblank = drm_vblank_crtc(dev, pipe);
>  	unsigned long irqflags;
>  
>  	assert_spin_locked(&dev->vbl_lock);
> @@ -600,7 +613,7 @@ void drm_calc_timestamping_constants(struct drm_crtc *crtc,
>  {
>  	struct drm_device *dev = crtc->dev;
>  	unsigned int pipe = drm_crtc_index(crtc);
> -	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
> +	struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);
>  	int linedur_ns = 0, framedur_ns = 0;
>  	int dotclock = mode->crtc_clock;
>  
> @@ -930,7 +943,7 @@ EXPORT_SYMBOL(drm_crtc_vblank_count);
>  static u64 drm_vblank_count_and_time(struct drm_device *dev, unsigned int pipe,
>  				     ktime_t *vblanktime)
>  {
> -	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
> +	struct drm_vblank_crtc *vblank = drm_vblank_crtc(dev, pipe);
>  	u64 vblank_count;
>  	unsigned int seq;
>  
> @@ -985,7 +998,6 @@ EXPORT_SYMBOL(drm_crtc_vblank_count_and_time);
>   */
>  int drm_crtc_next_vblank_start(struct drm_crtc *crtc, ktime_t *vblanktime)
>  {
> -	unsigned int pipe = drm_crtc_index(crtc);
>  	struct drm_vblank_crtc *vblank;
>  	struct drm_display_mode *mode;
>  	u64 vblank_start;
> @@ -993,7 +1005,7 @@ int drm_crtc_next_vblank_start(struct drm_crtc *crtc, ktime_t *vblanktime)
>  	if (!drm_dev_has_vblank(crtc->dev))
>  		return -EINVAL;
>  
> -	vblank = &crtc->dev->vblank[pipe];
> +	vblank = drm_crtc_vblank_crtc(crtc);
>  	mode = &vblank->hwmode;
>  
>  	if (!vblank->framedur_ns || !vblank->linedur_ns)
> @@ -1147,7 +1159,7 @@ static int __enable_vblank(struct drm_device *dev, unsigned int pipe)
>  
>  static int drm_vblank_enable(struct drm_device *dev, unsigned int pipe)
>  {
> -	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
> +	struct drm_vblank_crtc *vblank = drm_vblank_crtc(dev, pipe);
>  	int ret = 0;
>  
>  	assert_spin_locked(&dev->vbl_lock);
> @@ -1185,7 +1197,7 @@ static int drm_vblank_enable(struct drm_device *dev, unsigned int pipe)
>  
>  int drm_vblank_get(struct drm_device *dev, unsigned int pipe)
>  {
> -	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
> +	struct drm_vblank_crtc *vblank = drm_vblank_crtc(dev, pipe);
>  	unsigned long irqflags;
>  	int ret = 0;
>  
> @@ -1228,7 +1240,7 @@ EXPORT_SYMBOL(drm_crtc_vblank_get);
>  
>  void drm_vblank_put(struct drm_device *dev, unsigned int pipe)
>  {
> -	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
> +	struct drm_vblank_crtc *vblank = drm_vblank_crtc(dev, pipe);
>  
>  	if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
>  		return;
> @@ -1274,7 +1286,7 @@ EXPORT_SYMBOL(drm_crtc_vblank_put);
>   */
>  void drm_wait_one_vblank(struct drm_device *dev, unsigned int pipe)
>  {
> -	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
> +	struct drm_vblank_crtc *vblank = drm_vblank_crtc(dev, pipe);
>  	int ret;
>  	u64 last;
>  
> @@ -1327,7 +1339,7 @@ void drm_crtc_vblank_off(struct drm_crtc *crtc)
>  {
>  	struct drm_device *dev = crtc->dev;
>  	unsigned int pipe = drm_crtc_index(crtc);
> -	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
> +	struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);
>  	struct drm_pending_vblank_event *e, *t;
>  	ktime_t now;
>  	u64 seq;
> @@ -1405,8 +1417,7 @@ EXPORT_SYMBOL(drm_crtc_vblank_off);
>  void drm_crtc_vblank_reset(struct drm_crtc *crtc)
>  {
>  	struct drm_device *dev = crtc->dev;
> -	unsigned int pipe = drm_crtc_index(crtc);
> -	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
> +	struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);
>  
>  	spin_lock_irq(&dev->vbl_lock);
>  	/*
> @@ -1445,8 +1456,7 @@ void drm_crtc_set_max_vblank_count(struct drm_crtc *crtc,
>  				   u32 max_vblank_count)
>  {
>  	struct drm_device *dev = crtc->dev;
> -	unsigned int pipe = drm_crtc_index(crtc);
> -	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
> +	struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);
>  
>  	drm_WARN_ON(dev, dev->max_vblank_count);
>  	drm_WARN_ON(dev, !READ_ONCE(vblank->inmodeset));
> @@ -1469,7 +1479,7 @@ void drm_crtc_vblank_on(struct drm_crtc *crtc)
>  {
>  	struct drm_device *dev = crtc->dev;
>  	unsigned int pipe = drm_crtc_index(crtc);
> -	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
> +	struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);
>  
>  	if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
>  		return;
> @@ -1512,7 +1522,7 @@ static void drm_vblank_restore(struct drm_device *dev, unsigned int pipe)
>  	assert_spin_locked(&dev->vbl_lock);
>  	assert_spin_locked(&dev->vblank_time_lock);
>  
> -	vblank = &dev->vblank[pipe];
> +	vblank = drm_vblank_crtc(dev, pipe);
>  	drm_WARN_ONCE(dev,
>  		      drm_debug_enabled(DRM_UT_VBL) && !vblank->framedur_ns,
>  		      "Cannot compute missed vblanks without frame duration\n");
> @@ -1564,7 +1574,7 @@ static int drm_queue_vblank_event(struct drm_device *dev, unsigned int pipe,
>  				  union drm_wait_vblank *vblwait,
>  				  struct drm_file *file_priv)
>  {
> -	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
> +	struct drm_vblank_crtc *vblank = drm_vblank_crtc(dev, pipe);
>  	struct drm_pending_vblank_event *e;
>  	ktime_t now;
>  	u64 seq;
> @@ -1872,7 +1882,7 @@ static void drm_handle_vblank_events(struct drm_device *dev, unsigned int pipe)
>   */
>  bool drm_handle_vblank(struct drm_device *dev, unsigned int pipe)
>  {
> -	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
> +	struct drm_vblank_crtc *vblank = drm_vblank_crtc(dev, pipe);
>  	unsigned long irqflags;
>  	bool disable_irq;
>  
> @@ -1981,7 +1991,7 @@ int drm_crtc_get_sequence_ioctl(struct drm_device *dev, void *data,
>  
>  	pipe = drm_crtc_index(crtc);
>  
> -	vblank = &dev->vblank[pipe];
> +	vblank = drm_crtc_vblank_crtc(crtc);
>  	vblank_enabled = dev->vblank_disable_immediate && READ_ONCE(vblank->enabled);
>  
>  	if (!vblank_enabled) {
> @@ -2046,7 +2056,7 @@ int drm_crtc_queue_sequence_ioctl(struct drm_device *dev, void *data,
>  
>  	pipe = drm_crtc_index(crtc);
>  
> -	vblank = &dev->vblank[pipe];
> +	vblank = drm_crtc_vblank_crtc(crtc);
>  
>  	e = kzalloc(sizeof(*e), GFP_KERNEL);
>  	if (e == NULL)
> diff --git a/drivers/gpu/drm/drm_vblank_work.c b/drivers/gpu/drm/drm_vblank_work.c
> index 43cd5c0f4f6f..4fe9b1d3b00f 100644
> --- a/drivers/gpu/drm/drm_vblank_work.c
> +++ b/drivers/gpu/drm/drm_vblank_work.c
> @@ -245,7 +245,7 @@ void drm_vblank_work_init(struct drm_vblank_work *work, struct drm_crtc *crtc,
>  {
>  	kthread_init_work(&work->base, func);
>  	INIT_LIST_HEAD(&work->node);
> -	work->vblank = &crtc->dev->vblank[drm_crtc_index(crtc)];
> +	work->vblank = drm_crtc_vblank_crtc(crtc);
>  }
>  EXPORT_SYMBOL(drm_vblank_work_init);
>  
> diff --git a/include/drm/drm_vblank.h b/include/drm/drm_vblank.h
> index 7f3957943dd1..c8f829b4307c 100644
> --- a/include/drm/drm_vblank.h
> +++ b/include/drm/drm_vblank.h
> @@ -225,6 +225,7 @@ struct drm_vblank_crtc {
>  	wait_queue_head_t work_wait_queue;
>  };
>  
> +struct drm_vblank_crtc *drm_crtc_vblank_crtc(struct drm_crtc *crtc);
>  int drm_vblank_init(struct drm_device *dev, unsigned int num_crtcs);
>  bool drm_dev_has_vblank(const struct drm_device *dev);
>  u64 drm_crtc_vblank_count(struct drm_crtc *crtc);
> -- 
> 2.43.2
>
Ville Syrjala April 18, 2024, 10:41 a.m. UTC | #2
On Tue, Apr 09, 2024 at 06:02:49PM +0300, Dmitry Baryshkov wrote:
> On Mon, Apr 08, 2024 at 10:06:07PM +0300, Ville Syrjala wrote:
> > From: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > 
> > Make life easier by providing a function that hands
> > out the the correct drm_vblank_crtc for a given a drm_crtc.
> > 
> > Also abstract the lower level internals of the vblank
> > code in a similar fashion.
> > 
> > Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com>
> > ---
> >  drivers/gpu/drm/drm_vblank.c      | 58 ++++++++++++++++++-------------
> >  drivers/gpu/drm/drm_vblank_work.c |  2 +-
> >  include/drm/drm_vblank.h          |  1 +
> >  3 files changed, 36 insertions(+), 25 deletions(-)
> 
> 
> Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
> 
> I'm looking forward to using this in drm/msm

This+nouveau+vkms parts push to the drm-misc-next.
Thanks for the reviews.

amdgpu and i915 parts still pending.
diff mbox series

Patch

diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c
index 702a12bc93bd..cc3571e25a9a 100644
--- a/drivers/gpu/drm/drm_vblank.c
+++ b/drivers/gpu/drm/drm_vblank.c
@@ -166,11 +166,24 @@  module_param_named(timestamp_precision_usec, drm_timestamp_precision, int, 0600)
 MODULE_PARM_DESC(vblankoffdelay, "Delay until vblank irq auto-disable [msecs] (0: never disable, <0: disable immediately)");
 MODULE_PARM_DESC(timestamp_precision_usec, "Max. error on timestamps [usecs]");
 
+static struct drm_vblank_crtc *
+drm_vblank_crtc(struct drm_device *dev, unsigned int pipe)
+{
+	return &dev->vblank[pipe];
+}
+
+struct drm_vblank_crtc *
+drm_crtc_vblank_crtc(struct drm_crtc *crtc)
+{
+	return drm_vblank_crtc(crtc->dev, drm_crtc_index(crtc));
+}
+EXPORT_SYMBOL(drm_crtc_vblank_crtc);
+
 static void store_vblank(struct drm_device *dev, unsigned int pipe,
 			 u32 vblank_count_inc,
 			 ktime_t t_vblank, u32 last)
 {
-	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
+	struct drm_vblank_crtc *vblank = drm_vblank_crtc(dev, pipe);
 
 	assert_spin_locked(&dev->vblank_time_lock);
 
@@ -184,7 +197,7 @@  static void store_vblank(struct drm_device *dev, unsigned int pipe,
 
 static u32 drm_max_vblank_count(struct drm_device *dev, unsigned int pipe)
 {
-	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
+	struct drm_vblank_crtc *vblank = drm_vblank_crtc(dev, pipe);
 
 	return vblank->max_vblank_count ?: dev->max_vblank_count;
 }
@@ -273,7 +286,7 @@  static void drm_reset_vblank_timestamp(struct drm_device *dev, unsigned int pipe
 static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe,
 				    bool in_vblank_irq)
 {
-	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
+	struct drm_vblank_crtc *vblank = drm_vblank_crtc(dev, pipe);
 	u32 cur_vblank, diff;
 	bool rc;
 	ktime_t t_vblank;
@@ -364,7 +377,7 @@  static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe,
 
 u64 drm_vblank_count(struct drm_device *dev, unsigned int pipe)
 {
-	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
+	struct drm_vblank_crtc *vblank = drm_vblank_crtc(dev, pipe);
 	u64 count;
 
 	if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
@@ -438,7 +451,7 @@  static void __disable_vblank(struct drm_device *dev, unsigned int pipe)
  */
 void drm_vblank_disable_and_save(struct drm_device *dev, unsigned int pipe)
 {
-	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
+	struct drm_vblank_crtc *vblank = drm_vblank_crtc(dev, pipe);
 	unsigned long irqflags;
 
 	assert_spin_locked(&dev->vbl_lock);
@@ -600,7 +613,7 @@  void drm_calc_timestamping_constants(struct drm_crtc *crtc,
 {
 	struct drm_device *dev = crtc->dev;
 	unsigned int pipe = drm_crtc_index(crtc);
-	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
+	struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);
 	int linedur_ns = 0, framedur_ns = 0;
 	int dotclock = mode->crtc_clock;
 
@@ -930,7 +943,7 @@  EXPORT_SYMBOL(drm_crtc_vblank_count);
 static u64 drm_vblank_count_and_time(struct drm_device *dev, unsigned int pipe,
 				     ktime_t *vblanktime)
 {
-	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
+	struct drm_vblank_crtc *vblank = drm_vblank_crtc(dev, pipe);
 	u64 vblank_count;
 	unsigned int seq;
 
@@ -985,7 +998,6 @@  EXPORT_SYMBOL(drm_crtc_vblank_count_and_time);
  */
 int drm_crtc_next_vblank_start(struct drm_crtc *crtc, ktime_t *vblanktime)
 {
-	unsigned int pipe = drm_crtc_index(crtc);
 	struct drm_vblank_crtc *vblank;
 	struct drm_display_mode *mode;
 	u64 vblank_start;
@@ -993,7 +1005,7 @@  int drm_crtc_next_vblank_start(struct drm_crtc *crtc, ktime_t *vblanktime)
 	if (!drm_dev_has_vblank(crtc->dev))
 		return -EINVAL;
 
-	vblank = &crtc->dev->vblank[pipe];
+	vblank = drm_crtc_vblank_crtc(crtc);
 	mode = &vblank->hwmode;
 
 	if (!vblank->framedur_ns || !vblank->linedur_ns)
@@ -1147,7 +1159,7 @@  static int __enable_vblank(struct drm_device *dev, unsigned int pipe)
 
 static int drm_vblank_enable(struct drm_device *dev, unsigned int pipe)
 {
-	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
+	struct drm_vblank_crtc *vblank = drm_vblank_crtc(dev, pipe);
 	int ret = 0;
 
 	assert_spin_locked(&dev->vbl_lock);
@@ -1185,7 +1197,7 @@  static int drm_vblank_enable(struct drm_device *dev, unsigned int pipe)
 
 int drm_vblank_get(struct drm_device *dev, unsigned int pipe)
 {
-	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
+	struct drm_vblank_crtc *vblank = drm_vblank_crtc(dev, pipe);
 	unsigned long irqflags;
 	int ret = 0;
 
@@ -1228,7 +1240,7 @@  EXPORT_SYMBOL(drm_crtc_vblank_get);
 
 void drm_vblank_put(struct drm_device *dev, unsigned int pipe)
 {
-	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
+	struct drm_vblank_crtc *vblank = drm_vblank_crtc(dev, pipe);
 
 	if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
 		return;
@@ -1274,7 +1286,7 @@  EXPORT_SYMBOL(drm_crtc_vblank_put);
  */
 void drm_wait_one_vblank(struct drm_device *dev, unsigned int pipe)
 {
-	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
+	struct drm_vblank_crtc *vblank = drm_vblank_crtc(dev, pipe);
 	int ret;
 	u64 last;
 
@@ -1327,7 +1339,7 @@  void drm_crtc_vblank_off(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
 	unsigned int pipe = drm_crtc_index(crtc);
-	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
+	struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);
 	struct drm_pending_vblank_event *e, *t;
 	ktime_t now;
 	u64 seq;
@@ -1405,8 +1417,7 @@  EXPORT_SYMBOL(drm_crtc_vblank_off);
 void drm_crtc_vblank_reset(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
-	unsigned int pipe = drm_crtc_index(crtc);
-	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
+	struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);
 
 	spin_lock_irq(&dev->vbl_lock);
 	/*
@@ -1445,8 +1456,7 @@  void drm_crtc_set_max_vblank_count(struct drm_crtc *crtc,
 				   u32 max_vblank_count)
 {
 	struct drm_device *dev = crtc->dev;
-	unsigned int pipe = drm_crtc_index(crtc);
-	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
+	struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);
 
 	drm_WARN_ON(dev, dev->max_vblank_count);
 	drm_WARN_ON(dev, !READ_ONCE(vblank->inmodeset));
@@ -1469,7 +1479,7 @@  void drm_crtc_vblank_on(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
 	unsigned int pipe = drm_crtc_index(crtc);
-	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
+	struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(crtc);
 
 	if (drm_WARN_ON(dev, pipe >= dev->num_crtcs))
 		return;
@@ -1512,7 +1522,7 @@  static void drm_vblank_restore(struct drm_device *dev, unsigned int pipe)
 	assert_spin_locked(&dev->vbl_lock);
 	assert_spin_locked(&dev->vblank_time_lock);
 
-	vblank = &dev->vblank[pipe];
+	vblank = drm_vblank_crtc(dev, pipe);
 	drm_WARN_ONCE(dev,
 		      drm_debug_enabled(DRM_UT_VBL) && !vblank->framedur_ns,
 		      "Cannot compute missed vblanks without frame duration\n");
@@ -1564,7 +1574,7 @@  static int drm_queue_vblank_event(struct drm_device *dev, unsigned int pipe,
 				  union drm_wait_vblank *vblwait,
 				  struct drm_file *file_priv)
 {
-	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
+	struct drm_vblank_crtc *vblank = drm_vblank_crtc(dev, pipe);
 	struct drm_pending_vblank_event *e;
 	ktime_t now;
 	u64 seq;
@@ -1872,7 +1882,7 @@  static void drm_handle_vblank_events(struct drm_device *dev, unsigned int pipe)
  */
 bool drm_handle_vblank(struct drm_device *dev, unsigned int pipe)
 {
-	struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
+	struct drm_vblank_crtc *vblank = drm_vblank_crtc(dev, pipe);
 	unsigned long irqflags;
 	bool disable_irq;
 
@@ -1981,7 +1991,7 @@  int drm_crtc_get_sequence_ioctl(struct drm_device *dev, void *data,
 
 	pipe = drm_crtc_index(crtc);
 
-	vblank = &dev->vblank[pipe];
+	vblank = drm_crtc_vblank_crtc(crtc);
 	vblank_enabled = dev->vblank_disable_immediate && READ_ONCE(vblank->enabled);
 
 	if (!vblank_enabled) {
@@ -2046,7 +2056,7 @@  int drm_crtc_queue_sequence_ioctl(struct drm_device *dev, void *data,
 
 	pipe = drm_crtc_index(crtc);
 
-	vblank = &dev->vblank[pipe];
+	vblank = drm_crtc_vblank_crtc(crtc);
 
 	e = kzalloc(sizeof(*e), GFP_KERNEL);
 	if (e == NULL)
diff --git a/drivers/gpu/drm/drm_vblank_work.c b/drivers/gpu/drm/drm_vblank_work.c
index 43cd5c0f4f6f..4fe9b1d3b00f 100644
--- a/drivers/gpu/drm/drm_vblank_work.c
+++ b/drivers/gpu/drm/drm_vblank_work.c
@@ -245,7 +245,7 @@  void drm_vblank_work_init(struct drm_vblank_work *work, struct drm_crtc *crtc,
 {
 	kthread_init_work(&work->base, func);
 	INIT_LIST_HEAD(&work->node);
-	work->vblank = &crtc->dev->vblank[drm_crtc_index(crtc)];
+	work->vblank = drm_crtc_vblank_crtc(crtc);
 }
 EXPORT_SYMBOL(drm_vblank_work_init);
 
diff --git a/include/drm/drm_vblank.h b/include/drm/drm_vblank.h
index 7f3957943dd1..c8f829b4307c 100644
--- a/include/drm/drm_vblank.h
+++ b/include/drm/drm_vblank.h
@@ -225,6 +225,7 @@  struct drm_vblank_crtc {
 	wait_queue_head_t work_wait_queue;
 };
 
+struct drm_vblank_crtc *drm_crtc_vblank_crtc(struct drm_crtc *crtc);
 int drm_vblank_init(struct drm_device *dev, unsigned int num_crtcs);
 bool drm_dev_has_vblank(const struct drm_device *dev);
 u64 drm_crtc_vblank_count(struct drm_crtc *crtc);