Message ID | 20230227193535.2822389-11-robdclark@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | dma-fence: Deadline awareness | expand |
LGTM. This one is Reviewed-by: Mario Kleiner <mario.kleiner.de@gmail.com> -mario On Mon, Feb 27, 2023 at 8:36 PM Rob Clark <robdclark@gmail.com> wrote: > From: Rob Clark <robdclark@chromium.org> > > Will be used in the next commit to set a deadline on fences that an > atomic update is waiting on. > > v2: Calculate time at *start* of vblank period, not end > v3: Fix kbuild complaints > > Signed-off-by: Rob Clark <robdclark@chromium.org> > --- > drivers/gpu/drm/drm_vblank.c | 53 ++++++++++++++++++++++++++++++------ > include/drm/drm_vblank.h | 1 + > 2 files changed, 45 insertions(+), 9 deletions(-) > > diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c > index 2ff31717a3de..299fa2a19a90 100644 > --- a/drivers/gpu/drm/drm_vblank.c > +++ b/drivers/gpu/drm/drm_vblank.c > @@ -844,10 +844,9 @@ bool > drm_crtc_vblank_helper_get_vblank_timestamp(struct drm_crtc *crtc, > EXPORT_SYMBOL(drm_crtc_vblank_helper_get_vblank_timestamp); > > /** > - * drm_get_last_vbltimestamp - retrieve raw timestamp for the most recent > - * vblank interval > - * @dev: DRM device > - * @pipe: index of CRTC whose vblank timestamp to retrieve > + * drm_crtc_get_last_vbltimestamp - retrieve raw timestamp for the most > + * recent vblank interval > + * @crtc: CRTC whose vblank timestamp to retrieve > * @tvblank: Pointer to target time which should receive the timestamp > * @in_vblank_irq: > * True when called from drm_crtc_handle_vblank(). Some drivers > @@ -865,10 +864,9 @@ > EXPORT_SYMBOL(drm_crtc_vblank_helper_get_vblank_timestamp); > * True if timestamp is considered to be very precise, false otherwise. > */ > static bool > -drm_get_last_vbltimestamp(struct drm_device *dev, unsigned int pipe, > - ktime_t *tvblank, bool in_vblank_irq) > +drm_crtc_get_last_vbltimestamp(struct drm_crtc *crtc, ktime_t *tvblank, > + bool in_vblank_irq) > { > - struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe); > bool ret = false; > > /* Define requested maximum error on timestamps (nanoseconds). */ > @@ -876,8 +874,6 @@ drm_get_last_vbltimestamp(struct drm_device *dev, > unsigned int pipe, > > /* Query driver if possible and precision timestamping enabled. */ > if (crtc && crtc->funcs->get_vblank_timestamp && max_error > 0) { > - struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe); > - > ret = crtc->funcs->get_vblank_timestamp(crtc, &max_error, > tvblank, > in_vblank_irq); > } > @@ -891,6 +887,15 @@ drm_get_last_vbltimestamp(struct drm_device *dev, > unsigned int pipe, > return ret; > } > > +static bool > +drm_get_last_vbltimestamp(struct drm_device *dev, unsigned int pipe, > + ktime_t *tvblank, bool in_vblank_irq) > +{ > + struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe); > + > + return drm_crtc_get_last_vbltimestamp(crtc, tvblank, > in_vblank_irq); > +} > + > /** > * drm_crtc_vblank_count - retrieve "cooked" vblank counter value > * @crtc: which counter to retrieve > @@ -980,6 +985,36 @@ u64 drm_crtc_vblank_count_and_time(struct drm_crtc > *crtc, > } > EXPORT_SYMBOL(drm_crtc_vblank_count_and_time); > > +/** > + * drm_crtc_next_vblank_start - calculate the time of the next vblank > + * @crtc: the crtc for which to calculate next vblank time > + * @vblanktime: pointer to time to receive the next vblank timestamp. > + * > + * Calculate the expected time of the start of the next vblank period, > + * based on time of previous vblank and frame duration > + */ > +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 = &crtc->dev->vblank[pipe]; > + struct drm_display_mode *mode = &vblank->hwmode; > + u64 vblank_start; > + > + if (!vblank->framedur_ns || !vblank->linedur_ns) > + return -EINVAL; > + > + if (!drm_crtc_get_last_vbltimestamp(crtc, vblanktime, false)) > + return -EINVAL; > + > + vblank_start = DIV_ROUND_DOWN_ULL( > + (u64)vblank->framedur_ns * mode->crtc_vblank_start, > + mode->crtc_vtotal); > + *vblanktime = ktime_add(*vblanktime, ns_to_ktime(vblank_start)); > + > + return 0; > +} > +EXPORT_SYMBOL(drm_crtc_next_vblank_start); > + > static void send_vblank_event(struct drm_device *dev, > struct drm_pending_vblank_event *e, > u64 seq, ktime_t now) > diff --git a/include/drm/drm_vblank.h b/include/drm/drm_vblank.h > index 733a3e2d1d10..7f3957943dd1 100644 > --- a/include/drm/drm_vblank.h > +++ b/include/drm/drm_vblank.h > @@ -230,6 +230,7 @@ bool drm_dev_has_vblank(const struct drm_device *dev); > u64 drm_crtc_vblank_count(struct drm_crtc *crtc); > u64 drm_crtc_vblank_count_and_time(struct drm_crtc *crtc, > ktime_t *vblanktime); > +int drm_crtc_next_vblank_start(struct drm_crtc *crtc, ktime_t > *vblanktime); > void drm_crtc_send_vblank_event(struct drm_crtc *crtc, > struct drm_pending_vblank_event *e); > void drm_crtc_arm_vblank_event(struct drm_crtc *crtc, > -- > 2.39.1 > >
diff --git a/drivers/gpu/drm/drm_vblank.c b/drivers/gpu/drm/drm_vblank.c index 2ff31717a3de..299fa2a19a90 100644 --- a/drivers/gpu/drm/drm_vblank.c +++ b/drivers/gpu/drm/drm_vblank.c @@ -844,10 +844,9 @@ bool drm_crtc_vblank_helper_get_vblank_timestamp(struct drm_crtc *crtc, EXPORT_SYMBOL(drm_crtc_vblank_helper_get_vblank_timestamp); /** - * drm_get_last_vbltimestamp - retrieve raw timestamp for the most recent - * vblank interval - * @dev: DRM device - * @pipe: index of CRTC whose vblank timestamp to retrieve + * drm_crtc_get_last_vbltimestamp - retrieve raw timestamp for the most + * recent vblank interval + * @crtc: CRTC whose vblank timestamp to retrieve * @tvblank: Pointer to target time which should receive the timestamp * @in_vblank_irq: * True when called from drm_crtc_handle_vblank(). Some drivers @@ -865,10 +864,9 @@ EXPORT_SYMBOL(drm_crtc_vblank_helper_get_vblank_timestamp); * True if timestamp is considered to be very precise, false otherwise. */ static bool -drm_get_last_vbltimestamp(struct drm_device *dev, unsigned int pipe, - ktime_t *tvblank, bool in_vblank_irq) +drm_crtc_get_last_vbltimestamp(struct drm_crtc *crtc, ktime_t *tvblank, + bool in_vblank_irq) { - struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe); bool ret = false; /* Define requested maximum error on timestamps (nanoseconds). */ @@ -876,8 +874,6 @@ drm_get_last_vbltimestamp(struct drm_device *dev, unsigned int pipe, /* Query driver if possible and precision timestamping enabled. */ if (crtc && crtc->funcs->get_vblank_timestamp && max_error > 0) { - struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe); - ret = crtc->funcs->get_vblank_timestamp(crtc, &max_error, tvblank, in_vblank_irq); } @@ -891,6 +887,15 @@ drm_get_last_vbltimestamp(struct drm_device *dev, unsigned int pipe, return ret; } +static bool +drm_get_last_vbltimestamp(struct drm_device *dev, unsigned int pipe, + ktime_t *tvblank, bool in_vblank_irq) +{ + struct drm_crtc *crtc = drm_crtc_from_index(dev, pipe); + + return drm_crtc_get_last_vbltimestamp(crtc, tvblank, in_vblank_irq); +} + /** * drm_crtc_vblank_count - retrieve "cooked" vblank counter value * @crtc: which counter to retrieve @@ -980,6 +985,36 @@ u64 drm_crtc_vblank_count_and_time(struct drm_crtc *crtc, } EXPORT_SYMBOL(drm_crtc_vblank_count_and_time); +/** + * drm_crtc_next_vblank_start - calculate the time of the next vblank + * @crtc: the crtc for which to calculate next vblank time + * @vblanktime: pointer to time to receive the next vblank timestamp. + * + * Calculate the expected time of the start of the next vblank period, + * based on time of previous vblank and frame duration + */ +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 = &crtc->dev->vblank[pipe]; + struct drm_display_mode *mode = &vblank->hwmode; + u64 vblank_start; + + if (!vblank->framedur_ns || !vblank->linedur_ns) + return -EINVAL; + + if (!drm_crtc_get_last_vbltimestamp(crtc, vblanktime, false)) + return -EINVAL; + + vblank_start = DIV_ROUND_DOWN_ULL( + (u64)vblank->framedur_ns * mode->crtc_vblank_start, + mode->crtc_vtotal); + *vblanktime = ktime_add(*vblanktime, ns_to_ktime(vblank_start)); + + return 0; +} +EXPORT_SYMBOL(drm_crtc_next_vblank_start); + static void send_vblank_event(struct drm_device *dev, struct drm_pending_vblank_event *e, u64 seq, ktime_t now) diff --git a/include/drm/drm_vblank.h b/include/drm/drm_vblank.h index 733a3e2d1d10..7f3957943dd1 100644 --- a/include/drm/drm_vblank.h +++ b/include/drm/drm_vblank.h @@ -230,6 +230,7 @@ bool drm_dev_has_vblank(const struct drm_device *dev); u64 drm_crtc_vblank_count(struct drm_crtc *crtc); u64 drm_crtc_vblank_count_and_time(struct drm_crtc *crtc, ktime_t *vblanktime); +int drm_crtc_next_vblank_start(struct drm_crtc *crtc, ktime_t *vblanktime); void drm_crtc_send_vblank_event(struct drm_crtc *crtc, struct drm_pending_vblank_event *e); void drm_crtc_arm_vblank_event(struct drm_crtc *crtc,