aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2017-05-09 10:03:28 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2017-05-10 04:21:31 -0400
commit1bf6ad622b9be58484279978f85716fbb10d545b (patch)
treef7add5183253140848bff995e5084e8fd35dacb8
parent2a39b88bc121645e95a2b3b25a97ef4ceb4208b8 (diff)
drm/vblank: drop the mode argument from drm_calc_vbltimestamp_from_scanoutpos
If we restrict this helper to only kms drivers (which is the case) we can look up the correct mode easily ourselves. But it's a bit tricky: - All legacy drivers look at crtc->hwmode. But that is updated already at the beginning of the modeset helper, which means when we disable a pipe. Hence the final timestamps might be a bit off. But since this is an existing bug I'm not going to change it, but just try to be bug-for-bug compatible with the current code. This only applies to radeon&amdgpu. - i915 tries to get it perfect by updating crtc->hwmode when the pipe is off (i.e. vblank->enabled = false). - All other atomic drivers look at crtc->state->adjusted_mode. Those that look at state->requested_mode simply don't adjust their mode, so it's the same. That has two problems: Accessing crtc->state from interrupt handling code is unsafe, and it's updated before we shut down the pipe. For nonblocking modesets it's even worse. For atomic drivers try to implement what i915 does. To do that we add a new hwmode field to the vblank structure, and update it from drm_calc_timestamping_constants(). For atomic drivers that's called from the right spot by the helper library already, so all fine. But for safety let's enforce that. For legacy driver this function is only called at the end (oh the fun), which is broken, so again let's not bother and just stay bug-for-bug compatible. The benefit is that we can use drm_calc_vbltimestamp_from_scanoutpos directly to implement ->get_vblank_timestamp in every driver, deleting a lot of code. v2: Completely new approach, trying to mimick the i915 solution. v3: Fixup kerneldoc. v4: Drop the WARN_ON to check that the vblank is off, atomic helpers currently unconditionally call this. Recomputing the same stuff should be harmless. v5: Fix typos and move misplaced hunks to the right patches (Neil). v6: Undo hunk movement (kbuild). Cc: Mario Kleiner <mario.kleiner@tuebingen.mpg.de> Cc: Eric Anholt <eric@anholt.net> Cc: Rob Clark <robdclark@gmail.com> Cc: linux-arm-msm@vger.kernel.org Cc: freedreno@lists.freedesktop.org Cc: Alex Deucher <alexander.deucher@amd.com> Cc: Christian König <christian.koenig@amd.com> Cc: Ben Skeggs <bskeggs@redhat.com> Reviewed-by: Neil Armstrong <narmstrong@baylibre.com> Acked-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@intel.com> Link: http://patchwork.freedesktop.org/patch/msgid/20170509140329.24114-4-daniel.vetter@ffwll.ch
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu.h4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c14
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c41
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h3
-rw-r--r--drivers/gpu/drm/drm_irq.c43
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c52
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c45
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_display.c38
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_display.h8
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drm.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_drv.c18
-rw-r--r--drivers/gpu/drm/radeon/radeon_kms.c37
-rw-r--r--drivers/gpu/drm/radeon/radeon_mode.h3
-rw-r--r--drivers/gpu/drm/vc4/vc4_crtc.c34
-rw-r--r--drivers/gpu/drm/vc4/vc4_drv.c2
-rw-r--r--drivers/gpu/drm/vc4/vc4_drv.h11
-rw-r--r--include/drm/drmP.h8
-rw-r--r--include/drm/drm_drv.h20
-rw-r--r--include/drm/drm_irq.h15
19 files changed, 121 insertions, 277 deletions
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 0ce8292d97c0..9de615bb0c2e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -1910,10 +1910,6 @@ int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon);
1910u32 amdgpu_get_vblank_counter_kms(struct drm_device *dev, unsigned int pipe); 1910u32 amdgpu_get_vblank_counter_kms(struct drm_device *dev, unsigned int pipe);
1911int amdgpu_enable_vblank_kms(struct drm_device *dev, unsigned int pipe); 1911int amdgpu_enable_vblank_kms(struct drm_device *dev, unsigned int pipe);
1912void amdgpu_disable_vblank_kms(struct drm_device *dev, unsigned int pipe); 1912void amdgpu_disable_vblank_kms(struct drm_device *dev, unsigned int pipe);
1913bool amdgpu_get_vblank_timestamp_kms(struct drm_device *dev, unsigned int pipe,
1914 int *max_error,
1915 struct timeval *vblank_time,
1916 bool in_vblank_irq);
1917long amdgpu_kms_compat_ioctl(struct file *filp, unsigned int cmd, 1913long amdgpu_kms_compat_ioctl(struct file *filp, unsigned int cmd,
1918 unsigned long arg); 1914 unsigned long arg);
1919 1915
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index 4e0f7d2d87f1..73e982cd6136 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -711,6 +711,16 @@ static const struct file_operations amdgpu_driver_kms_fops = {
711#endif 711#endif
712}; 712};
713 713
714static bool
715amdgpu_get_crtc_scanout_position(struct drm_device *dev, unsigned int pipe,
716 bool in_vblank_irq, int *vpos, int *hpos,
717 ktime_t *stime, ktime_t *etime,
718 const struct drm_display_mode *mode)
719{
720 return amdgpu_get_crtc_scanoutpos(dev, pipe, 0, vpos, hpos,
721 stime, etime, mode);
722}
723
714static struct drm_driver kms_driver = { 724static struct drm_driver kms_driver = {
715 .driver_features = 725 .driver_features =
716 DRIVER_USE_AGP | 726 DRIVER_USE_AGP |
@@ -725,8 +735,8 @@ static struct drm_driver kms_driver = {
725 .get_vblank_counter = amdgpu_get_vblank_counter_kms, 735 .get_vblank_counter = amdgpu_get_vblank_counter_kms,
726 .enable_vblank = amdgpu_enable_vblank_kms, 736 .enable_vblank = amdgpu_enable_vblank_kms,
727 .disable_vblank = amdgpu_disable_vblank_kms, 737 .disable_vblank = amdgpu_disable_vblank_kms,
728 .get_vblank_timestamp = amdgpu_get_vblank_timestamp_kms, 738 .get_vblank_timestamp = drm_calc_vbltimestamp_from_scanoutpos,
729 .get_scanout_position = amdgpu_get_crtc_scanoutpos, 739 .get_scanout_position = amdgpu_get_crtc_scanout_position,
730#if defined(CONFIG_DEBUG_FS) 740#if defined(CONFIG_DEBUG_FS)
731 .debugfs_init = amdgpu_debugfs_init, 741 .debugfs_init = amdgpu_debugfs_init,
732#endif 742#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
index babd969a63d1..40f45ba71b86 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
@@ -934,47 +934,6 @@ void amdgpu_disable_vblank_kms(struct drm_device *dev, unsigned int pipe)
934 amdgpu_irq_put(adev, &adev->crtc_irq, idx); 934 amdgpu_irq_put(adev, &adev->crtc_irq, idx);
935} 935}
936 936
937/**
938 * amdgpu_get_vblank_timestamp_kms - get vblank timestamp
939 *
940 * @dev: drm dev pointer
941 * @crtc: crtc to get the timestamp for
942 * @max_error: max error
943 * @vblank_time: time value
944 * @in_vblank_irq: called from drm_handle_vblank()
945 *
946 * Gets the timestamp on the requested crtc based on the
947 * scanout position. (all asics).
948 * Returns true on success, false on failure.
949 */
950bool amdgpu_get_vblank_timestamp_kms(struct drm_device *dev, unsigned int pipe,
951 int *max_error,
952 struct timeval *vblank_time,
953 bool in_vblank_irq)
954{
955 struct drm_crtc *crtc;
956 struct amdgpu_device *adev = dev->dev_private;
957
958 if (pipe >= dev->num_crtcs) {
959 DRM_ERROR("Invalid crtc %u\n", pipe);
960 return false;
961 }
962
963 /* Get associated drm_crtc: */
964 crtc = &adev->mode_info.crtcs[pipe]->base;
965 if (!crtc) {
966 /* This can occur on driver load if some component fails to
967 * initialize completely and driver is unloaded */
968 DRM_ERROR("Uninitialized crtc %d\n", pipe);
969 return false;
970 }
971
972 /* Helper routine in DRM core does all the work: */
973 return drm_calc_vbltimestamp_from_scanoutpos(dev, pipe, max_error,
974 vblank_time, in_vblank_irq,
975 &crtc->hwmode);
976}
977
978const struct drm_ioctl_desc amdgpu_ioctls_kms[] = { 937const struct drm_ioctl_desc amdgpu_ioctls_kms[] = {
979 DRM_IOCTL_DEF_DRV(AMDGPU_GEM_CREATE, amdgpu_gem_create_ioctl, DRM_AUTH|DRM_RENDER_ALLOW), 938 DRM_IOCTL_DEF_DRV(AMDGPU_GEM_CREATE, amdgpu_gem_create_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
980 DRM_IOCTL_DEF_DRV(AMDGPU_CTX, amdgpu_ctx_ioctl, DRM_AUTH|DRM_RENDER_ALLOW), 939 DRM_IOCTL_DEF_DRV(AMDGPU_CTX, amdgpu_ctx_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
index db8f8dda209c..20d6522fd7b4 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
@@ -534,6 +534,9 @@ struct amdgpu_framebuffer {
534 ((em) == ATOM_ENCODER_MODE_DP_MST)) 534 ((em) == ATOM_ENCODER_MODE_DP_MST))
535 535
536/* Driver internal use only flags of amdgpu_get_crtc_scanoutpos() */ 536/* Driver internal use only flags of amdgpu_get_crtc_scanoutpos() */
537#define DRM_SCANOUTPOS_VALID (1 << 0)
538#define DRM_SCANOUTPOS_IN_VBLANK (1 << 1)
539#define DRM_SCANOUTPOS_ACCURATE (1 << 2)
537#define USE_REAL_VBLANKSTART (1 << 30) 540#define USE_REAL_VBLANKSTART (1 << 30)
538#define GET_DISTANCE_TO_VBLANKSTART (1 << 31) 541#define GET_DISTANCE_TO_VBLANKSTART (1 << 31)
539 542
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
index fba6a842f4cd..89f0928b042a 100644
--- a/drivers/gpu/drm/drm_irq.c
+++ b/drivers/gpu/drm/drm_irq.c
@@ -684,6 +684,7 @@ void drm_calc_timestamping_constants(struct drm_crtc *crtc,
684 684
685 vblank->linedur_ns = linedur_ns; 685 vblank->linedur_ns = linedur_ns;
686 vblank->framedur_ns = framedur_ns; 686 vblank->framedur_ns = framedur_ns;
687 vblank->hwmode = *mode;
687 688
688 DRM_DEBUG("crtc %u: hwmode: htotal %d, vtotal %d, vdisplay %d\n", 689 DRM_DEBUG("crtc %u: hwmode: htotal %d, vtotal %d, vdisplay %d\n",
689 crtc->base.id, mode->crtc_htotal, 690 crtc->base.id, mode->crtc_htotal,
@@ -704,7 +705,6 @@ EXPORT_SYMBOL(drm_calc_timestamping_constants);
704 * True when called from drm_crtc_handle_vblank(). Some drivers 705 * True when called from drm_crtc_handle_vblank(). Some drivers
705 * need to apply some workarounds for gpu-specific vblank irq quirks 706 * need to apply some workarounds for gpu-specific vblank irq quirks
706 * if flag is set. 707 * if flag is set.
707 * @mode: mode which defines the scanout timings
708 * 708 *
709 * Implements calculation of exact vblank timestamps from given drm_display_mode 709 * Implements calculation of exact vblank timestamps from given drm_display_mode
710 * timings and current video scanout position of a CRTC. This can be called from 710 * timings and current video scanout position of a CRTC. This can be called from
@@ -724,6 +724,13 @@ EXPORT_SYMBOL(drm_calc_timestamping_constants);
724 * returns as no operation if a doublescan or interlaced video mode is 724 * returns as no operation if a doublescan or interlaced video mode is
725 * active. Higher level code is expected to handle this. 725 * active. Higher level code is expected to handle this.
726 * 726 *
727 * This function can be used to implement the &drm_driver.get_vblank_timestamp
728 * directly, if the driver implements the &drm_driver.get_scanout_position hook.
729 *
730 * Note that atomic drivers must call drm_calc_timestamping_constants() before
731 * enabling a CRTC. The atomic helpers already take care of that in
732 * drm_atomic_helper_update_legacy_modeset_state().
733 *
727 * Returns: 734 * Returns:
728 * 735 *
729 * Returns true on success, and false on failure, i.e. when no accurate 736 * Returns true on success, and false on failure, i.e. when no accurate
@@ -733,17 +740,23 @@ bool drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
733 unsigned int pipe, 740 unsigned int pipe,
734 int *max_error, 741 int *max_error,
735 struct timeval *vblank_time, 742 struct timeval *vblank_time,
736 bool in_vblank_irq, 743 bool in_vblank_irq)
737 const struct drm_display_mode *mode)
738{ 744{
739 struct timeval tv_etime; 745 struct timeval tv_etime;
740 ktime_t stime, etime; 746 ktime_t stime, etime;
741 unsigned int vbl_status; 747 bool vbl_status;
748 struct drm_crtc *crtc;
749 const struct drm_display_mode *mode;
750 struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
742 int vpos, hpos, i; 751 int vpos, hpos, i;
743 int delta_ns, duration_ns; 752 int delta_ns, duration_ns;
744 unsigned flags = in_vblank_irq ? DRM_CALLED_FROM_VBLIRQ : 0;
745 753
746 if (pipe >= dev->num_crtcs) { 754 if (!drm_core_check_feature(dev, DRIVER_MODESET))
755 return false;
756
757 crtc = drm_crtc_from_index(dev, pipe);
758
759 if (pipe >= dev->num_crtcs || !crtc) {
747 DRM_ERROR("Invalid crtc %u\n", pipe); 760 DRM_ERROR("Invalid crtc %u\n", pipe);
748 return false; 761 return false;
749 } 762 }
@@ -754,6 +767,11 @@ bool drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
754 return false; 767 return false;
755 } 768 }
756 769
770 if (drm_drv_uses_atomic_modeset(dev))
771 mode = &vblank->hwmode;
772 else
773 mode = &crtc->hwmode;
774
757 /* If mode timing undefined, just return as no-op: 775 /* If mode timing undefined, just return as no-op:
758 * Happens during initial modesetting of a crtc. 776 * Happens during initial modesetting of a crtc.
759 */ 777 */
@@ -774,15 +792,16 @@ bool drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
774 * Get vertical and horizontal scanout position vpos, hpos, 792 * Get vertical and horizontal scanout position vpos, hpos,
775 * and bounding timestamps stime, etime, pre/post query. 793 * and bounding timestamps stime, etime, pre/post query.
776 */ 794 */
777 vbl_status = dev->driver->get_scanout_position(dev, pipe, flags, 795 vbl_status = dev->driver->get_scanout_position(dev, pipe,
796 in_vblank_irq,
778 &vpos, &hpos, 797 &vpos, &hpos,
779 &stime, &etime, 798 &stime, &etime,
780 mode); 799 mode);
781 800
782 /* Return as no-op if scanout query unsupported or failed. */ 801 /* Return as no-op if scanout query unsupported or failed. */
783 if (!(vbl_status & DRM_SCANOUTPOS_VALID)) { 802 if (!vbl_status) {
784 DRM_DEBUG("crtc %u : scanoutpos query failed [0x%x].\n", 803 DRM_DEBUG("crtc %u : scanoutpos query failed.\n",
785 pipe, vbl_status); 804 pipe);
786 return false; 805 return false;
787 } 806 }
788 807
@@ -821,8 +840,8 @@ bool drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
821 etime = ktime_sub_ns(etime, delta_ns); 840 etime = ktime_sub_ns(etime, delta_ns);
822 *vblank_time = ktime_to_timeval(etime); 841 *vblank_time = ktime_to_timeval(etime);
823 842
824 DRM_DEBUG_VBL("crtc %u : v 0x%x p(%d,%d)@ %ld.%ld -> %ld.%ld [e %d us, %d rep]\n", 843 DRM_DEBUG_VBL("crtc %u : v p(%d,%d)@ %ld.%ld -> %ld.%ld [e %d us, %d rep]\n",
825 pipe, vbl_status, hpos, vpos, 844 pipe, hpos, vpos,
826 (long)tv_etime.tv_sec, (long)tv_etime.tv_usec, 845 (long)tv_etime.tv_sec, (long)tv_etime.tv_usec,
827 (long)vblank_time->tv_sec, (long)vblank_time->tv_usec, 846 (long)vblank_time->tv_sec, (long)vblank_time->tv_usec,
828 duration_ns/1000, i); 847 duration_ns/1000, i);
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index ae09c29662a1..dccb7c2560fe 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -827,10 +827,10 @@ static int __intel_get_crtc_scanline(struct intel_crtc *crtc)
827 return (position + crtc->scanline_offset) % vtotal; 827 return (position + crtc->scanline_offset) % vtotal;
828} 828}
829 829
830static int i915_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe, 830static bool i915_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe,
831 unsigned int flags, int *vpos, int *hpos, 831 bool in_vblank_irq, int *vpos, int *hpos,
832 ktime_t *stime, ktime_t *etime, 832 ktime_t *stime, ktime_t *etime,
833 const struct drm_display_mode *mode) 833 const struct drm_display_mode *mode)
834{ 834{
835 struct drm_i915_private *dev_priv = to_i915(dev); 835 struct drm_i915_private *dev_priv = to_i915(dev);
836 struct intel_crtc *intel_crtc = intel_get_crtc_for_pipe(dev_priv, 836 struct intel_crtc *intel_crtc = intel_get_crtc_for_pipe(dev_priv,
@@ -838,13 +838,12 @@ static int i915_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe,
838 int position; 838 int position;
839 int vbl_start, vbl_end, hsync_start, htotal, vtotal; 839 int vbl_start, vbl_end, hsync_start, htotal, vtotal;
840 bool in_vbl = true; 840 bool in_vbl = true;
841 int ret = 0;
842 unsigned long irqflags; 841 unsigned long irqflags;
843 842
844 if (WARN_ON(!mode->crtc_clock)) { 843 if (WARN_ON(!mode->crtc_clock)) {
845 DRM_DEBUG_DRIVER("trying to get scanoutpos for disabled " 844 DRM_DEBUG_DRIVER("trying to get scanoutpos for disabled "
846 "pipe %c\n", pipe_name(pipe)); 845 "pipe %c\n", pipe_name(pipe));
847 return 0; 846 return false;
848 } 847 }
849 848
850 htotal = mode->crtc_htotal; 849 htotal = mode->crtc_htotal;
@@ -859,8 +858,6 @@ static int i915_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe,
859 vtotal /= 2; 858 vtotal /= 2;
860 } 859 }
861 860
862 ret |= DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE;
863
864 /* 861 /*
865 * Lock uncore.lock, as we will do multiple timing critical raw 862 * Lock uncore.lock, as we will do multiple timing critical raw
866 * register reads, potentially with preemption disabled, so the 863 * register reads, potentially with preemption disabled, so the
@@ -944,11 +941,7 @@ static int i915_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe,
944 *hpos = position - (*vpos * htotal); 941 *hpos = position - (*vpos * htotal);
945 } 942 }
946 943
947 /* In vblank? */ 944 return true;
948 if (in_vbl)
949 ret |= DRM_SCANOUTPOS_IN_VBLANK;
950
951 return ret;
952} 945}
953 946
954int intel_get_crtc_scanline(struct intel_crtc *crtc) 947int intel_get_crtc_scanline(struct intel_crtc *crtc)
@@ -964,37 +957,6 @@ int intel_get_crtc_scanline(struct intel_crtc *crtc)
964 return position; 957 return position;
965} 958}
966 959
967static bool i915_get_vblank_timestamp(struct drm_device *dev, unsigned int pipe,
968 int *max_error,
969 struct timeval *vblank_time,
970 bool in_vblank_irq)
971{
972 struct drm_i915_private *dev_priv = to_i915(dev);
973 struct intel_crtc *crtc;
974
975 if (pipe >= INTEL_INFO(dev_priv)->num_pipes) {
976 DRM_ERROR("Invalid crtc %u\n", pipe);
977 return false;
978 }
979
980 /* Get drm_crtc to timestamp: */
981 crtc = intel_get_crtc_for_pipe(dev_priv, pipe);
982 if (crtc == NULL) {
983 DRM_ERROR("Invalid crtc %u\n", pipe);
984 return false;
985 }
986
987 if (!crtc->base.hwmode.crtc_clock) {
988 DRM_DEBUG_KMS("crtc %u is disabled\n", pipe);
989 return false;
990 }
991
992 /* Helper routine in DRM core does all the work: */
993 return drm_calc_vbltimestamp_from_scanoutpos(dev, pipe, max_error,
994 vblank_time, in_vblank_irq,
995 &crtc->base.hwmode);
996}
997
998static void ironlake_rps_change_irq_handler(struct drm_i915_private *dev_priv) 960static void ironlake_rps_change_irq_handler(struct drm_i915_private *dev_priv)
999{ 961{
1000 u32 busy_up, busy_down, max_avg, min_avg; 962 u32 busy_up, busy_down, max_avg, min_avg;
@@ -4294,7 +4256,7 @@ void intel_irq_init(struct drm_i915_private *dev_priv)
4294 4256
4295 dev_priv->hotplug.hpd_storm_threshold = HPD_STORM_DEFAULT_THRESHOLD; 4257 dev_priv->hotplug.hpd_storm_threshold = HPD_STORM_DEFAULT_THRESHOLD;
4296 4258
4297 dev->driver->get_vblank_timestamp = i915_get_vblank_timestamp; 4259 dev->driver->get_vblank_timestamp = drm_calc_vbltimestamp_from_scanoutpos;
4298 dev->driver->get_scanout_position = i915_get_crtc_scanoutpos; 4260 dev->driver->get_scanout_position = i915_get_crtc_scanoutpos;
4299 4261
4300 if (IS_CHERRYVIEW(dev_priv)) { 4262 if (IS_CHERRYVIEW(dev_priv)) {
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
index 07e2b1335f65..e2b3346ead48 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
@@ -527,31 +527,28 @@ static struct drm_encoder *get_encoder_from_crtc(struct drm_crtc *crtc)
527 return NULL; 527 return NULL;
528} 528}
529 529
530static int mdp5_get_scanoutpos(struct drm_device *dev, unsigned int pipe, 530static bool mdp5_get_scanoutpos(struct drm_device *dev, unsigned int pipe,
531 unsigned int flags, int *vpos, int *hpos, 531 bool in_vblank_irq, int *vpos, int *hpos,
532 ktime_t *stime, ktime_t *etime, 532 ktime_t *stime, ktime_t *etime,
533 const struct drm_display_mode *mode) 533 const struct drm_display_mode *mode)
534{ 534{
535 struct msm_drm_private *priv = dev->dev_private; 535 struct msm_drm_private *priv = dev->dev_private;
536 struct drm_crtc *crtc; 536 struct drm_crtc *crtc;
537 struct drm_encoder *encoder; 537 struct drm_encoder *encoder;
538 int line, vsw, vbp, vactive_start, vactive_end, vfp_end; 538 int line, vsw, vbp, vactive_start, vactive_end, vfp_end;
539 int ret = 0;
540 539
541 crtc = priv->crtcs[pipe]; 540 crtc = priv->crtcs[pipe];
542 if (!crtc) { 541 if (!crtc) {
543 DRM_ERROR("Invalid crtc %d\n", pipe); 542 DRM_ERROR("Invalid crtc %d\n", pipe);
544 return 0; 543 return false;
545 } 544 }
546 545
547 encoder = get_encoder_from_crtc(crtc); 546 encoder = get_encoder_from_crtc(crtc);
548 if (!encoder) { 547 if (!encoder) {
549 DRM_ERROR("no encoder found for crtc %d\n", pipe); 548 DRM_ERROR("no encoder found for crtc %d\n", pipe);
550 return 0; 549 return false;
551 } 550 }
552 551
553 ret |= DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE;
554
555 vsw = mode->crtc_vsync_end - mode->crtc_vsync_start; 552 vsw = mode->crtc_vsync_end - mode->crtc_vsync_start;
556 vbp = mode->crtc_vtotal - mode->crtc_vsync_end; 553 vbp = mode->crtc_vtotal - mode->crtc_vsync_end;
557 554
@@ -575,10 +572,8 @@ static int mdp5_get_scanoutpos(struct drm_device *dev, unsigned int pipe,
575 572
576 if (line < vactive_start) { 573 if (line < vactive_start) {
577 line -= vactive_start; 574 line -= vactive_start;
578 ret |= DRM_SCANOUTPOS_IN_VBLANK;
579 } else if (line > vactive_end) { 575 } else if (line > vactive_end) {
580 line = line - vfp_end - vactive_start; 576 line = line - vfp_end - vactive_start;
581 ret |= DRM_SCANOUTPOS_IN_VBLANK;
582 } else { 577 } else {
583 line -= vactive_start; 578 line -= vactive_start;
584 } 579 }
@@ -589,31 +584,7 @@ static int mdp5_get_scanoutpos(struct drm_device *dev, unsigned int pipe,
589 if (etime) 584 if (etime)
590 *etime = ktime_get(); 585 *etime = ktime_get();
591 586
592 return ret; 587 return true;
593}
594
595static bool mdp5_get_vblank_timestamp(struct drm_device *dev, unsigned int pipe,
596 int *max_error,
597 struct timeval *vblank_time,
598 bool in_vblank_irq)
599{
600 struct msm_drm_private *priv = dev->dev_private;
601 struct drm_crtc *crtc;
602
603 if (pipe < 0 || pipe >= priv->num_crtcs) {
604 DRM_ERROR("Invalid crtc %d\n", pipe);
605 return false;
606 }
607
608 crtc = priv->crtcs[pipe];
609 if (!crtc) {
610 DRM_ERROR("Invalid crtc %d\n", pipe);
611 return false;
612 }
613
614 return drm_calc_vbltimestamp_from_scanoutpos(dev, pipe, max_error,
615 vblank_time, in_vblank_irq,
616 &crtc->mode);
617} 588}
618 589
619static u32 mdp5_get_vblank_counter(struct drm_device *dev, unsigned int pipe) 590static u32 mdp5_get_vblank_counter(struct drm_device *dev, unsigned int pipe)
@@ -725,7 +696,7 @@ struct msm_kms *mdp5_kms_init(struct drm_device *dev)
725 dev->mode_config.max_width = 0xffff; 696 dev->mode_config.max_width = 0xffff;
726 dev->mode_config.max_height = 0xffff; 697 dev->mode_config.max_height = 0xffff;
727 698
728 dev->driver->get_vblank_timestamp = mdp5_get_vblank_timestamp; 699 dev->driver->get_vblank_timestamp = drm_calc_vbltimestamp_from_scanoutpos;
729 dev->driver->get_scanout_position = mdp5_get_scanoutpos; 700 dev->driver->get_scanout_position = mdp5_get_scanoutpos;
730 dev->driver->get_vblank_counter = mdp5_get_vblank_counter; 701 dev->driver->get_vblank_counter = mdp5_get_vblank_counter;
731 dev->max_vblank_count = 0xffffffff; 702 dev->max_vblank_count = 0xffffffff;
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index 2d28ef57f2bf..6718c84fb862 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -98,7 +98,7 @@ calc(int blanks, int blanke, int total, int line)
98 return line; 98 return line;
99} 99}
100 100
101static int 101static bool
102nouveau_display_scanoutpos_head(struct drm_crtc *crtc, int *vpos, int *hpos, 102nouveau_display_scanoutpos_head(struct drm_crtc *crtc, int *vpos, int *hpos,
103 ktime_t *stime, ktime_t *etime) 103 ktime_t *stime, ktime_t *etime)
104{ 104{
@@ -111,16 +111,16 @@ nouveau_display_scanoutpos_head(struct drm_crtc *crtc, int *vpos, int *hpos,
111 }; 111 };
112 struct nouveau_display *disp = nouveau_display(crtc->dev); 112 struct nouveau_display *disp = nouveau_display(crtc->dev);
113 struct drm_vblank_crtc *vblank = &crtc->dev->vblank[drm_crtc_index(crtc)]; 113 struct drm_vblank_crtc *vblank = &crtc->dev->vblank[drm_crtc_index(crtc)];
114 int ret, retry = 20; 114 int retry = 20;
115 bool ret = false;
115 116
116 do { 117 do {
117 ret = nvif_mthd(&disp->disp, 0, &args, sizeof(args)); 118 ret = nvif_mthd(&disp->disp, 0, &args, sizeof(args));
118 if (ret != 0) 119 if (ret != 0)
119 return 0; 120 return false;
120 121
121 if (args.scan.vline) { 122 if (args.scan.vline) {
122 ret |= DRM_SCANOUTPOS_ACCURATE; 123 ret = true;
123 ret |= DRM_SCANOUTPOS_VALID;
124 break; 124 break;
125 } 125 }
126 126
@@ -133,14 +133,12 @@ nouveau_display_scanoutpos_head(struct drm_crtc *crtc, int *vpos, int *hpos,
133 if (stime) *stime = ns_to_ktime(args.scan.time[0]); 133 if (stime) *stime = ns_to_ktime(args.scan.time[0]);
134 if (etime) *etime = ns_to_ktime(args.scan.time[1]); 134 if (etime) *etime = ns_to_ktime(args.scan.time[1]);
135 135
136 if (*vpos < 0)
137 ret |= DRM_SCANOUTPOS_IN_VBLANK;
138 return ret; 136 return ret;
139} 137}
140 138
141int 139bool
142nouveau_display_scanoutpos(struct drm_device *dev, unsigned int pipe, 140nouveau_display_scanoutpos(struct drm_device *dev, unsigned int pipe,
143 unsigned int flags, int *vpos, int *hpos, 141 bool in_vblank_irq, int *vpos, int *hpos,
144 ktime_t *stime, ktime_t *etime, 142 ktime_t *stime, ktime_t *etime,
145 const struct drm_display_mode *mode) 143 const struct drm_display_mode *mode)
146{ 144{
@@ -153,28 +151,6 @@ nouveau_display_scanoutpos(struct drm_device *dev, unsigned int pipe,
153 } 151 }
154 } 152 }
155 153
156 return 0;
157}
158
159bool
160nouveau_display_vblstamp(struct drm_device *dev, unsigned int pipe,
161 int *max_error, struct timeval *time, bool in_vblank_irq)
162{
163 struct drm_crtc *crtc;
164
165 list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
166 if (nouveau_crtc(crtc)->index == pipe) {
167 struct drm_display_mode *mode;
168 if (drm_drv_uses_atomic_modeset(dev))
169 mode = &crtc->state->adjusted_mode;
170 else
171 mode = &crtc->hwmode;
172 return drm_calc_vbltimestamp_from_scanoutpos(dev,
173 pipe, max_error, time, in_vblank_irq,
174 mode);
175 }
176 }
177
178 return false; 154 return false;
179} 155}
180 156
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.h b/drivers/gpu/drm/nouveau/nouveau_display.h
index 8ec86259c5ac..201aec2ea5b8 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.h
+++ b/drivers/gpu/drm/nouveau/nouveau_display.h
@@ -68,11 +68,9 @@ int nouveau_display_suspend(struct drm_device *dev, bool runtime);
68void nouveau_display_resume(struct drm_device *dev, bool runtime); 68void nouveau_display_resume(struct drm_device *dev, bool runtime);
69int nouveau_display_vblank_enable(struct drm_device *, unsigned int); 69int nouveau_display_vblank_enable(struct drm_device *, unsigned int);
70void nouveau_display_vblank_disable(struct drm_device *, unsigned int); 70void nouveau_display_vblank_disable(struct drm_device *, unsigned int);
71int nouveau_display_scanoutpos(struct drm_device *, unsigned int, 71bool nouveau_display_scanoutpos(struct drm_device *, unsigned int,
72 unsigned int, int *, int *, ktime_t *, 72 bool, int *, int *, ktime_t *,
73 ktime_t *, const struct drm_display_mode *); 73 ktime_t *, const struct drm_display_mode *);
74bool nouveau_display_vblstamp(struct drm_device *, unsigned int, int *,
75 struct timeval *, bool);
76 74
77int nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, 75int nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb,
78 struct drm_pending_vblank_event *event, 76 struct drm_pending_vblank_event *event,
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
index ec719df619a6..1f751a3f570c 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -978,7 +978,7 @@ driver_stub = {
978 .enable_vblank = nouveau_display_vblank_enable, 978 .enable_vblank = nouveau_display_vblank_enable,
979 .disable_vblank = nouveau_display_vblank_disable, 979 .disable_vblank = nouveau_display_vblank_disable,
980 .get_scanout_position = nouveau_display_scanoutpos, 980 .get_scanout_position = nouveau_display_scanoutpos,
981 .get_vblank_timestamp = nouveau_display_vblstamp, 981 .get_vblank_timestamp = drm_calc_vbltimestamp_from_scanoutpos,
982 982
983 .ioctls = nouveau_ioctls, 983 .ioctls = nouveau_ioctls,
984 .num_ioctls = ARRAY_SIZE(nouveau_ioctls), 984 .num_ioctls = ARRAY_SIZE(nouveau_ioctls),
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c
index 88fc791ec8fb..ef8a75940980 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -115,10 +115,6 @@ int radeon_resume_kms(struct drm_device *dev, bool resume, bool fbcon);
115u32 radeon_get_vblank_counter_kms(struct drm_device *dev, unsigned int pipe); 115u32 radeon_get_vblank_counter_kms(struct drm_device *dev, unsigned int pipe);
116int radeon_enable_vblank_kms(struct drm_device *dev, unsigned int pipe); 116int radeon_enable_vblank_kms(struct drm_device *dev, unsigned int pipe);
117void radeon_disable_vblank_kms(struct drm_device *dev, unsigned int pipe); 117void radeon_disable_vblank_kms(struct drm_device *dev, unsigned int pipe);
118bool radeon_get_vblank_timestamp_kms(struct drm_device *dev, unsigned int pipe,
119 int *max_error,
120 struct timeval *vblank_time,
121 bool in_vblank_irq);
122void radeon_driver_irq_preinstall_kms(struct drm_device *dev); 118void radeon_driver_irq_preinstall_kms(struct drm_device *dev);
123int radeon_driver_irq_postinstall_kms(struct drm_device *dev); 119int radeon_driver_irq_postinstall_kms(struct drm_device *dev);
124void radeon_driver_irq_uninstall_kms(struct drm_device *dev); 120void radeon_driver_irq_uninstall_kms(struct drm_device *dev);
@@ -530,6 +526,16 @@ static const struct file_operations radeon_driver_kms_fops = {
530#endif 526#endif
531}; 527};
532 528
529static bool
530radeon_get_crtc_scanout_position(struct drm_device *dev, unsigned int pipe,
531 bool in_vblank_irq, int *vpos, int *hpos,
532 ktime_t *stime, ktime_t *etime,
533 const struct drm_display_mode *mode)
534{
535 return radeon_get_crtc_scanoutpos(dev, pipe, 0, vpos, hpos,
536 stime, etime, mode);
537}
538
533static struct drm_driver kms_driver = { 539static struct drm_driver kms_driver = {
534 .driver_features = 540 .driver_features =
535 DRIVER_USE_AGP | 541 DRIVER_USE_AGP |
@@ -544,8 +550,8 @@ static struct drm_driver kms_driver = {
544 .get_vblank_counter = radeon_get_vblank_counter_kms, 550 .get_vblank_counter = radeon_get_vblank_counter_kms,
545 .enable_vblank = radeon_enable_vblank_kms, 551 .enable_vblank = radeon_enable_vblank_kms,
546 .disable_vblank = radeon_disable_vblank_kms, 552 .disable_vblank = radeon_disable_vblank_kms,
547 .get_vblank_timestamp = radeon_get_vblank_timestamp_kms, 553 .get_vblank_timestamp = drm_calc_vbltimestamp_from_scanoutpos,
548 .get_scanout_position = radeon_get_crtc_scanoutpos, 554 .get_scanout_position = radeon_get_crtc_scanout_position,
549 .irq_preinstall = radeon_driver_irq_preinstall_kms, 555 .irq_preinstall = radeon_driver_irq_preinstall_kms,
550 .irq_postinstall = radeon_driver_irq_postinstall_kms, 556 .irq_postinstall = radeon_driver_irq_postinstall_kms,
551 .irq_uninstall = radeon_driver_irq_uninstall_kms, 557 .irq_uninstall = radeon_driver_irq_uninstall_kms,
diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c
index 5bccdeae0773..6a68d440bc44 100644
--- a/drivers/gpu/drm/radeon/radeon_kms.c
+++ b/drivers/gpu/drm/radeon/radeon_kms.c
@@ -858,43 +858,6 @@ void radeon_disable_vblank_kms(struct drm_device *dev, int crtc)
858 spin_unlock_irqrestore(&rdev->irq.lock, irqflags); 858 spin_unlock_irqrestore(&rdev->irq.lock, irqflags);
859} 859}
860 860
861/**
862 * radeon_get_vblank_timestamp_kms - get vblank timestamp
863 *
864 * @dev: drm dev pointer
865 * @crtc: crtc to get the timestamp for
866 * @max_error: max error
867 * @vblank_time: time value
868 * @flags: flags passed to the driver
869 *
870 * Gets the timestamp on the requested crtc based on the
871 * scanout position. (all asics).
872 * Returns true on success, false on failure.
873 */
874bool radeon_get_vblank_timestamp_kms(struct drm_device *dev, int crtc,
875 int *max_error,
876 struct timeval *vblank_time,
877 bool in_vblank_irq)
878{
879 struct drm_crtc *drmcrtc;
880 struct radeon_device *rdev = dev->dev_private;
881
882 if (crtc < 0 || crtc >= dev->num_crtcs) {
883 DRM_ERROR("Invalid crtc %d\n", crtc);
884 return false;
885 }
886
887 /* Get associated drm_crtc: */
888 drmcrtc = &rdev->mode_info.crtcs[crtc]->base;
889 if (!drmcrtc)
890 return false;
891
892 /* Helper routine in DRM core does all the work: */
893 return drm_calc_vbltimestamp_from_scanoutpos(dev, crtc, max_error,
894 vblank_time, in_vblank_irq,
895 &drmcrtc->hwmode);
896}
897
898const struct drm_ioctl_desc radeon_ioctls_kms[] = { 861const struct drm_ioctl_desc radeon_ioctls_kms[] = {
899 DRM_IOCTL_DEF_DRV(RADEON_CP_INIT, drm_invalid_op, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 862 DRM_IOCTL_DEF_DRV(RADEON_CP_INIT, drm_invalid_op, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
900 DRM_IOCTL_DEF_DRV(RADEON_CP_START, drm_invalid_op, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 863 DRM_IOCTL_DEF_DRV(RADEON_CP_START, drm_invalid_op, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h
index ad282648fc8b..00f5ec5c12c7 100644
--- a/drivers/gpu/drm/radeon/radeon_mode.h
+++ b/drivers/gpu/drm/radeon/radeon_mode.h
@@ -691,6 +691,9 @@ struct atom_voltage_table
691}; 691};
692 692
693/* Driver internal use only flags of radeon_get_crtc_scanoutpos() */ 693/* Driver internal use only flags of radeon_get_crtc_scanoutpos() */
694#define DRM_SCANOUTPOS_VALID (1 << 0)
695#define DRM_SCANOUTPOS_IN_VBLANK (1 << 1)
696#define DRM_SCANOUTPOS_ACCURATE (1 << 2)
694#define USE_REAL_VBLANKSTART (1 << 30) 697#define USE_REAL_VBLANKSTART (1 << 30)
695#define GET_DISTANCE_TO_VBLANKSTART (1 << 31) 698#define GET_DISTANCE_TO_VBLANKSTART (1 << 31)
696 699
diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 6ed53d2867c4..1b4dbe9e1c6d 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -151,10 +151,10 @@ int vc4_crtc_debugfs_regs(struct seq_file *m, void *unused)
151} 151}
152#endif 152#endif
153 153
154int vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id, 154bool vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id,
155 unsigned int flags, int *vpos, int *hpos, 155 bool in_vblank_irq, int *vpos, int *hpos,
156 ktime_t *stime, ktime_t *etime, 156 ktime_t *stime, ktime_t *etime,
157 const struct drm_display_mode *mode) 157 const struct drm_display_mode *mode)
158{ 158{
159 struct vc4_dev *vc4 = to_vc4_dev(dev); 159 struct vc4_dev *vc4 = to_vc4_dev(dev);
160 struct drm_crtc *crtc = drm_crtc_from_index(dev, crtc_id); 160 struct drm_crtc *crtc = drm_crtc_from_index(dev, crtc_id);
@@ -162,7 +162,7 @@ int vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id,
162 u32 val; 162 u32 val;
163 int fifo_lines; 163 int fifo_lines;
164 int vblank_lines; 164 int vblank_lines;
165 int ret = 0; 165 bool ret = false;
166 166
167 /* preempt_disable_rt() should go right here in PREEMPT_RT patchset. */ 167 /* preempt_disable_rt() should go right here in PREEMPT_RT patchset. */
168 168
@@ -198,7 +198,7 @@ int vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id,
198 fifo_lines = vc4_crtc->cob_size / mode->crtc_hdisplay; 198 fifo_lines = vc4_crtc->cob_size / mode->crtc_hdisplay;
199 199
200 if (fifo_lines > 0) 200 if (fifo_lines > 0)
201 ret |= DRM_SCANOUTPOS_VALID; 201 ret = true;
202 202
203 /* HVS more than fifo_lines into frame for compositing? */ 203 /* HVS more than fifo_lines into frame for compositing? */
204 if (*vpos > fifo_lines) { 204 if (*vpos > fifo_lines) {
@@ -216,7 +216,6 @@ int vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id,
216 */ 216 */
217 *vpos -= fifo_lines + 1; 217 *vpos -= fifo_lines + 1;
218 218
219 ret |= DRM_SCANOUTPOS_ACCURATE;
220 return ret; 219 return ret;
221 } 220 }
222 221
@@ -229,10 +228,9 @@ int vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id,
229 * We can't get meaningful readings wrt. scanline position of the PV 228 * We can't get meaningful readings wrt. scanline position of the PV
230 * and need to make things up in a approximative but consistent way. 229 * and need to make things up in a approximative but consistent way.
231 */ 230 */
232 ret |= DRM_SCANOUTPOS_IN_VBLANK;
233 vblank_lines = mode->vtotal - mode->vdisplay; 231 vblank_lines = mode->vtotal - mode->vdisplay;
234 232
235 if (flags & DRM_CALLED_FROM_VBLIRQ) { 233 if (in_vblank_irq) {
236 /* 234 /*
237 * Assume the irq handler got called close to first 235 * Assume the irq handler got called close to first
238 * line of vblank, so PV has about a full vblank 236 * line of vblank, so PV has about a full vblank
@@ -254,9 +252,10 @@ int vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id,
254 * we are at the very beginning of vblank, as the hvs just 252 * we are at the very beginning of vblank, as the hvs just
255 * started refilling, and the stime and etime timestamps 253 * started refilling, and the stime and etime timestamps
256 * truly correspond to start of vblank. 254 * truly correspond to start of vblank.
255 *
256 * Unfortunately there's no way to report this to upper levels
257 * and make it more useful.
257 */ 258 */
258 if ((val & SCALER_DISPSTATX_FULL) != SCALER_DISPSTATX_FULL)
259 ret |= DRM_SCANOUTPOS_ACCURATE;
260 } else { 259 } else {
261 /* 260 /*
262 * No clue where we are inside vblank. Return a vpos of zero, 261 * No clue where we are inside vblank. Return a vpos of zero,
@@ -270,19 +269,6 @@ int vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id,
270 return ret; 269 return ret;
271} 270}
272 271
273bool vc4_crtc_get_vblank_timestamp(struct drm_device *dev, unsigned int crtc_id,
274 int *max_error, struct timeval *vblank_time,
275 bool in_vblank_irq)
276{
277 struct drm_crtc *crtc = drm_crtc_from_index(dev, crtc_id);
278 struct drm_crtc_state *state = crtc->state;
279
280 /* Helper routine in DRM core does all the work: */
281 return drm_calc_vbltimestamp_from_scanoutpos(dev, crtc_id, max_error,
282 vblank_time, in_vblank_irq,
283 &state->adjusted_mode);
284}
285
286static void vc4_crtc_destroy(struct drm_crtc *crtc) 272static void vc4_crtc_destroy(struct drm_crtc *crtc)
287{ 273{
288 drm_crtc_cleanup(crtc); 274 drm_crtc_cleanup(crtc);
diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c
index 754ce76d4b98..863974942c66 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.c
+++ b/drivers/gpu/drm/vc4/vc4_drv.c
@@ -154,7 +154,7 @@ static struct drm_driver vc4_drm_driver = {
154 .irq_uninstall = vc4_irq_uninstall, 154 .irq_uninstall = vc4_irq_uninstall,
155 155
156 .get_scanout_position = vc4_crtc_get_scanoutpos, 156 .get_scanout_position = vc4_crtc_get_scanoutpos,
157 .get_vblank_timestamp = vc4_crtc_get_vblank_timestamp, 157 .get_vblank_timestamp = drm_calc_vbltimestamp_from_scanoutpos,
158 158
159#if defined(CONFIG_DEBUG_FS) 159#if defined(CONFIG_DEBUG_FS)
160 .debugfs_init = vc4_debugfs_init, 160 .debugfs_init = vc4_debugfs_init,
diff --git a/drivers/gpu/drm/vc4/vc4_drv.h b/drivers/gpu/drm/vc4/vc4_drv.h
index d192f7e5c1eb..5ba281361fb7 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.h
+++ b/drivers/gpu/drm/vc4/vc4_drv.h
@@ -489,13 +489,10 @@ int vc4_bo_stats_debugfs(struct seq_file *m, void *arg);
489extern struct platform_driver vc4_crtc_driver; 489extern struct platform_driver vc4_crtc_driver;
490bool vc4_event_pending(struct drm_crtc *crtc); 490bool vc4_event_pending(struct drm_crtc *crtc);
491int vc4_crtc_debugfs_regs(struct seq_file *m, void *arg); 491int vc4_crtc_debugfs_regs(struct seq_file *m, void *arg);
492int vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id, 492bool vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id,
493 unsigned int flags, int *vpos, int *hpos, 493 bool in_vblank_irq, int *vpos, int *hpos,
494 ktime_t *stime, ktime_t *etime, 494 ktime_t *stime, ktime_t *etime,
495 const struct drm_display_mode *mode); 495 const struct drm_display_mode *mode);
496bool vc4_crtc_get_vblank_timestamp(struct drm_device *dev, unsigned int crtc_id,
497 int *max_error, struct timeval *vblank_time,
498 bool in_vblank_irq);
499 496
500/* vc4_debugfs.c */ 497/* vc4_debugfs.c */
501int vc4_debugfs_init(struct drm_minor *minor); 498int vc4_debugfs_init(struct drm_minor *minor);
diff --git a/include/drm/drmP.h b/include/drm/drmP.h
index a1b19bf45fb3..52085832f711 100644
--- a/include/drm/drmP.h
+++ b/include/drm/drmP.h
@@ -320,14 +320,6 @@ struct pci_controller;
320#define DRM_IF_VERSION(maj, min) (maj << 16 | min) 320#define DRM_IF_VERSION(maj, min) (maj << 16 | min)
321 321
322 322
323/* Flags and return codes for get_vblank_timestamp() driver function. */
324#define DRM_CALLED_FROM_VBLIRQ 1
325
326/* get_scanout_position() return flags */
327#define DRM_SCANOUTPOS_VALID (1 << 0)
328#define DRM_SCANOUTPOS_IN_VBLANK (1 << 1)
329#define DRM_SCANOUTPOS_ACCURATE (1 << 2)
330
331/** 323/**
332 * DRM device structure. This structure represent a complete card that 324 * DRM device structure. This structure represent a complete card that
333 * may contain multiple heads. 325 * may contain multiple heads.
diff --git a/include/drm/drm_drv.h b/include/drm/drm_drv.h
index 619da98533cd..e64e33b9dd26 100644
--- a/include/drm/drm_drv.h
+++ b/include/drm/drm_drv.h
@@ -265,16 +265,8 @@ struct drm_driver {
265 * 265 *
266 * Returns: 266 * Returns:
267 * 267 *
268 * Flags, or'ed together as follows: 268 * True on success, false if a reliable scanout position counter could
269 * 269 * not be read out.
270 * DRM_SCANOUTPOS_VALID:
271 * Query successful.
272 * DRM_SCANOUTPOS_INVBL:
273 * Inside vblank.
274 * DRM_SCANOUTPOS_ACCURATE: Returned position is accurate. A lack of
275 * this flag means that returned position may be offset by a
276 * constant but unknown small number of scanlines wrt. real scanout
277 * position.
278 * 270 *
279 * FIXME: 271 * FIXME:
280 * 272 *
@@ -282,10 +274,10 @@ struct drm_driver {
282 * move it to &struct drm_crtc_helper_funcs, like all the other 274 * move it to &struct drm_crtc_helper_funcs, like all the other
283 * helper-internal hooks. 275 * helper-internal hooks.
284 */ 276 */
285 int (*get_scanout_position) (struct drm_device *dev, unsigned int pipe, 277 bool (*get_scanout_position) (struct drm_device *dev, unsigned int pipe,
286 unsigned int flags, int *vpos, int *hpos, 278 bool in_vblank_irq, int *vpos, int *hpos,
287 ktime_t *stime, ktime_t *etime, 279 ktime_t *stime, ktime_t *etime,
288 const struct drm_display_mode *mode); 280 const struct drm_display_mode *mode);
289 281
290 /** 282 /**
291 * @get_vblank_timestamp: 283 * @get_vblank_timestamp:
diff --git a/include/drm/drm_irq.h b/include/drm/drm_irq.h
index 445406efb8dc..569ca86d4e1f 100644
--- a/include/drm/drm_irq.h
+++ b/include/drm/drm_irq.h
@@ -121,6 +121,18 @@ struct drm_vblank_crtc {
121 * drm_calc_timestamping_constants(). 121 * drm_calc_timestamping_constants().
122 */ 122 */
123 int linedur_ns; 123 int linedur_ns;
124
125 /**
126 * @hwmode:
127 *
128 * Cache of the current hardware display mode. Only valid when @enabled
129 * is set. This is used by helpers like
130 * drm_calc_vbltimestamp_from_scanoutpos(). We can't just access the
131 * hardware mode by e.g. looking at &drm_crtc_state.adjusted_mode,
132 * because that one is really hard to get from interrupt context.
133 */
134 struct drm_display_mode hwmode;
135
124 /** 136 /**
125 * @enabled: Tracks the enabling state of the corresponding &drm_crtc to 137 * @enabled: Tracks the enabling state of the corresponding &drm_crtc to
126 * avoid double-disabling and hence corrupting saved state. Needed by 138 * avoid double-disabling and hence corrupting saved state. Needed by
@@ -156,8 +168,7 @@ u32 drm_accurate_vblank_count(struct drm_crtc *crtc);
156bool drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, 168bool drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
157 unsigned int pipe, int *max_error, 169 unsigned int pipe, int *max_error,
158 struct timeval *vblank_time, 170 struct timeval *vblank_time,
159 bool in_vblank_irq, 171 bool in_vblank_irq);
160 const struct drm_display_mode *mode);
161void drm_calc_timestamping_constants(struct drm_crtc *crtc, 172void drm_calc_timestamping_constants(struct drm_crtc *crtc,
162 const struct drm_display_mode *mode); 173 const struct drm_display_mode *mode);
163 174