Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

+121 -277
-4
drivers/gpu/drm/amd/amdgpu/amdgpu.h
··· 1910 1910 u32 amdgpu_get_vblank_counter_kms(struct drm_device *dev, unsigned int pipe); 1911 1911 int amdgpu_enable_vblank_kms(struct drm_device *dev, unsigned int pipe); 1912 1912 void amdgpu_disable_vblank_kms(struct drm_device *dev, unsigned int pipe); 1913 - bool 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); 1917 1913 long amdgpu_kms_compat_ioctl(struct file *filp, unsigned int cmd, 1918 1914 unsigned long arg); 1919 1915
+12 -2
drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
··· 711 711 #endif 712 712 }; 713 713 714 + static bool 715 + amdgpu_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 + 714 724 static struct drm_driver kms_driver = { 715 725 .driver_features = 716 726 DRIVER_USE_AGP | ··· 735 725 .get_vblank_counter = amdgpu_get_vblank_counter_kms, 736 726 .enable_vblank = amdgpu_enable_vblank_kms, 737 727 .disable_vblank = amdgpu_disable_vblank_kms, 738 - .get_vblank_timestamp = amdgpu_get_vblank_timestamp_kms, 739 - .get_scanout_position = amdgpu_get_crtc_scanoutpos, 728 + .get_vblank_timestamp = drm_calc_vbltimestamp_from_scanoutpos, 729 + .get_scanout_position = amdgpu_get_crtc_scanout_position, 740 730 #if defined(CONFIG_DEBUG_FS) 741 731 .debugfs_init = amdgpu_debugfs_init, 742 732 #endif
-41
drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
··· 934 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 - */ 950 - bool 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 - 978 937 const struct drm_ioctl_desc amdgpu_ioctls_kms[] = { 979 938 DRM_IOCTL_DEF_DRV(AMDGPU_GEM_CREATE, amdgpu_gem_create_ioctl, DRM_AUTH|DRM_RENDER_ALLOW), 980 939 DRM_IOCTL_DEF_DRV(AMDGPU_CTX, amdgpu_ctx_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
+3
drivers/gpu/drm/amd/amdgpu/amdgpu_mode.h
··· 534 534 ((em) == ATOM_ENCODER_MODE_DP_MST)) 535 535 536 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 540 #define USE_REAL_VBLANKSTART (1 << 30) 538 541 #define GET_DISTANCE_TO_VBLANKSTART (1 << 31) 539 542
+31 -12
drivers/gpu/drm/drm_irq.c
··· 684 684 685 685 vblank->linedur_ns = linedur_ns; 686 686 vblank->framedur_ns = framedur_ns; 687 + vblank->hwmode = *mode; 687 688 688 689 DRM_DEBUG("crtc %u: hwmode: htotal %d, vtotal %d, vdisplay %d\n", 689 690 crtc->base.id, mode->crtc_htotal, ··· 705 704 * True when called from drm_crtc_handle_vblank(). Some drivers 706 705 * need to apply some workarounds for gpu-specific vblank irq quirks 707 706 * if flag is set. 708 - * @mode: mode which defines the scanout timings 709 707 * 710 708 * Implements calculation of exact vblank timestamps from given drm_display_mode 711 709 * timings and current video scanout position of a CRTC. This can be called from ··· 724 724 * returns as no operation if a doublescan or interlaced video mode is 725 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 734 * Returns: 728 735 * 729 736 * Returns true on success, and false on failure, i.e. when no accurate ··· 740 733 unsigned int pipe, 741 734 int *max_error, 742 735 struct timeval *vblank_time, 743 - bool in_vblank_irq, 744 - const struct drm_display_mode *mode) 736 + bool in_vblank_irq) 745 737 { 746 738 struct timeval tv_etime; 747 739 ktime_t stime, etime; 748 - unsigned int vbl_status; 740 + bool vbl_status; 741 + struct drm_crtc *crtc; 742 + const struct drm_display_mode *mode; 743 + struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; 749 744 int vpos, hpos, i; 750 745 int delta_ns, duration_ns; 751 - unsigned flags = in_vblank_irq ? DRM_CALLED_FROM_VBLIRQ : 0; 752 746 753 - if (pipe >= dev->num_crtcs) { 747 + if (!drm_core_check_feature(dev, DRIVER_MODESET)) 748 + return false; 749 + 750 + crtc = drm_crtc_from_index(dev, pipe); 751 + 752 + if (pipe >= dev->num_crtcs || !crtc) { 754 753 DRM_ERROR("Invalid crtc %u\n", pipe); 755 754 return false; 756 755 } ··· 766 753 DRM_ERROR("Called from driver w/o get_scanout_position()!?\n"); 767 754 return false; 768 755 } 756 + 757 + if (drm_drv_uses_atomic_modeset(dev)) 758 + mode = &vblank->hwmode; 759 + else 760 + mode = &crtc->hwmode; 769 761 770 762 /* If mode timing undefined, just return as no-op: 771 763 * Happens during initial modesetting of a crtc. ··· 792 774 * Get vertical and horizontal scanout position vpos, hpos, 793 775 * and bounding timestamps stime, etime, pre/post query. 794 776 */ 795 - vbl_status = dev->driver->get_scanout_position(dev, pipe, flags, 777 + vbl_status = dev->driver->get_scanout_position(dev, pipe, 778 + in_vblank_irq, 796 779 &vpos, &hpos, 797 780 &stime, &etime, 798 781 mode); 799 782 800 783 /* Return as no-op if scanout query unsupported or failed. */ 801 - if (!(vbl_status & DRM_SCANOUTPOS_VALID)) { 802 - DRM_DEBUG("crtc %u : scanoutpos query failed [0x%x].\n", 803 - pipe, vbl_status); 784 + if (!vbl_status) { 785 + DRM_DEBUG("crtc %u : scanoutpos query failed.\n", 786 + pipe); 804 787 return false; 805 788 } 806 789 ··· 840 821 etime = ktime_sub_ns(etime, delta_ns); 841 822 *vblank_time = ktime_to_timeval(etime); 842 823 843 - DRM_DEBUG_VBL("crtc %u : v 0x%x p(%d,%d)@ %ld.%ld -> %ld.%ld [e %d us, %d rep]\n", 844 - pipe, vbl_status, hpos, vpos, 824 + DRM_DEBUG_VBL("crtc %u : v p(%d,%d)@ %ld.%ld -> %ld.%ld [e %d us, %d rep]\n", 825 + pipe, hpos, vpos, 845 826 (long)tv_etime.tv_sec, (long)tv_etime.tv_usec, 846 827 (long)vblank_time->tv_sec, (long)vblank_time->tv_usec, 847 828 duration_ns/1000, i);
+7 -45
drivers/gpu/drm/i915/i915_irq.c
··· 827 827 return (position + crtc->scanline_offset) % vtotal; 828 828 } 829 829 830 - static int i915_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe, 831 - unsigned int flags, int *vpos, int *hpos, 832 - ktime_t *stime, ktime_t *etime, 833 - const struct drm_display_mode *mode) 830 + static bool i915_get_crtc_scanoutpos(struct drm_device *dev, unsigned int pipe, 831 + bool in_vblank_irq, int *vpos, int *hpos, 832 + ktime_t *stime, ktime_t *etime, 833 + const struct drm_display_mode *mode) 834 834 { 835 835 struct drm_i915_private *dev_priv = to_i915(dev); 836 836 struct intel_crtc *intel_crtc = intel_get_crtc_for_pipe(dev_priv, ··· 838 838 int position; 839 839 int vbl_start, vbl_end, hsync_start, htotal, vtotal; 840 840 bool in_vbl = true; 841 - int ret = 0; 842 841 unsigned long irqflags; 843 842 844 843 if (WARN_ON(!mode->crtc_clock)) { 845 844 DRM_DEBUG_DRIVER("trying to get scanoutpos for disabled " 846 845 "pipe %c\n", pipe_name(pipe)); 847 - return 0; 846 + return false; 848 847 } 849 848 850 849 htotal = mode->crtc_htotal; ··· 857 858 vbl_end /= 2; 858 859 vtotal /= 2; 859 860 } 860 - 861 - ret |= DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE; 862 861 863 862 /* 864 863 * Lock uncore.lock, as we will do multiple timing critical raw ··· 941 944 *hpos = position - (*vpos * htotal); 942 945 } 943 946 944 - /* In vblank? */ 945 - if (in_vbl) 946 - ret |= DRM_SCANOUTPOS_IN_VBLANK; 947 - 948 - return ret; 947 + return true; 949 948 } 950 949 951 950 int intel_get_crtc_scanline(struct intel_crtc *crtc) ··· 955 962 spin_unlock_irqrestore(&dev_priv->uncore.lock, irqflags); 956 963 957 964 return position; 958 - } 959 - 960 - static bool i915_get_vblank_timestamp(struct drm_device *dev, unsigned int pipe, 961 - int *max_error, 962 - struct timeval *vblank_time, 963 - bool in_vblank_irq) 964 - { 965 - struct drm_i915_private *dev_priv = to_i915(dev); 966 - struct intel_crtc *crtc; 967 - 968 - if (pipe >= INTEL_INFO(dev_priv)->num_pipes) { 969 - DRM_ERROR("Invalid crtc %u\n", pipe); 970 - return false; 971 - } 972 - 973 - /* Get drm_crtc to timestamp: */ 974 - crtc = intel_get_crtc_for_pipe(dev_priv, pipe); 975 - if (crtc == NULL) { 976 - DRM_ERROR("Invalid crtc %u\n", pipe); 977 - return false; 978 - } 979 - 980 - if (!crtc->base.hwmode.crtc_clock) { 981 - DRM_DEBUG_KMS("crtc %u is disabled\n", pipe); 982 - return false; 983 - } 984 - 985 - /* Helper routine in DRM core does all the work: */ 986 - return drm_calc_vbltimestamp_from_scanoutpos(dev, pipe, max_error, 987 - vblank_time, in_vblank_irq, 988 - &crtc->base.hwmode); 989 965 } 990 966 991 967 static void ironlake_rps_change_irq_handler(struct drm_i915_private *dev_priv) ··· 4256 4294 4257 4295 dev_priv->hotplug.hpd_storm_threshold = HPD_STORM_DEFAULT_THRESHOLD; 4258 4296 4259 - dev->driver->get_vblank_timestamp = i915_get_vblank_timestamp; 4297 + dev->driver->get_vblank_timestamp = drm_calc_vbltimestamp_from_scanoutpos; 4260 4298 dev->driver->get_scanout_position = i915_get_crtc_scanoutpos; 4261 4299 4262 4300 if (IS_CHERRYVIEW(dev_priv)) {
+8 -37
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.c
··· 527 527 return NULL; 528 528 } 529 529 530 - static int mdp5_get_scanoutpos(struct drm_device *dev, unsigned int pipe, 531 - unsigned int flags, int *vpos, int *hpos, 532 - ktime_t *stime, ktime_t *etime, 533 - const struct drm_display_mode *mode) 530 + static bool mdp5_get_scanoutpos(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 534 { 535 535 struct msm_drm_private *priv = dev->dev_private; 536 536 struct drm_crtc *crtc; 537 537 struct drm_encoder *encoder; 538 538 int line, vsw, vbp, vactive_start, vactive_end, vfp_end; 539 - int ret = 0; 540 539 541 540 crtc = priv->crtcs[pipe]; 542 541 if (!crtc) { 543 542 DRM_ERROR("Invalid crtc %d\n", pipe); 544 - return 0; 543 + return false; 545 544 } 546 545 547 546 encoder = get_encoder_from_crtc(crtc); 548 547 if (!encoder) { 549 548 DRM_ERROR("no encoder found for crtc %d\n", pipe); 550 - return 0; 549 + return false; 551 550 } 552 - 553 - ret |= DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE; 554 551 555 552 vsw = mode->crtc_vsync_end - mode->crtc_vsync_start; 556 553 vbp = mode->crtc_vtotal - mode->crtc_vsync_end; ··· 572 575 573 576 if (line < vactive_start) { 574 577 line -= vactive_start; 575 - ret |= DRM_SCANOUTPOS_IN_VBLANK; 576 578 } else if (line > vactive_end) { 577 579 line = line - vfp_end - vactive_start; 578 - ret |= DRM_SCANOUTPOS_IN_VBLANK; 579 580 } else { 580 581 line -= vactive_start; 581 582 } ··· 584 589 if (etime) 585 590 *etime = ktime_get(); 586 591 587 - return ret; 588 - } 589 - 590 - static bool mdp5_get_vblank_timestamp(struct drm_device *dev, unsigned int pipe, 591 - int *max_error, 592 - struct timeval *vblank_time, 593 - bool in_vblank_irq) 594 - { 595 - struct msm_drm_private *priv = dev->dev_private; 596 - struct drm_crtc *crtc; 597 - 598 - if (pipe < 0 || pipe >= priv->num_crtcs) { 599 - DRM_ERROR("Invalid crtc %d\n", pipe); 600 - return false; 601 - } 602 - 603 - crtc = priv->crtcs[pipe]; 604 - if (!crtc) { 605 - DRM_ERROR("Invalid crtc %d\n", pipe); 606 - return false; 607 - } 608 - 609 - return drm_calc_vbltimestamp_from_scanoutpos(dev, pipe, max_error, 610 - vblank_time, in_vblank_irq, 611 - &crtc->mode); 592 + return true; 612 593 } 613 594 614 595 static u32 mdp5_get_vblank_counter(struct drm_device *dev, unsigned int pipe) ··· 696 725 dev->mode_config.max_width = 0xffff; 697 726 dev->mode_config.max_height = 0xffff; 698 727 699 - dev->driver->get_vblank_timestamp = mdp5_get_vblank_timestamp; 728 + dev->driver->get_vblank_timestamp = drm_calc_vbltimestamp_from_scanoutpos; 700 729 dev->driver->get_scanout_position = mdp5_get_scanoutpos; 701 730 dev->driver->get_vblank_counter = mdp5_get_vblank_counter; 702 731 dev->max_vblank_count = 0xffffffff;
+7 -31
drivers/gpu/drm/nouveau/nouveau_display.c
··· 98 98 return line; 99 99 } 100 100 101 - static int 101 + static bool 102 102 nouveau_display_scanoutpos_head(struct drm_crtc *crtc, int *vpos, int *hpos, 103 103 ktime_t *stime, ktime_t *etime) 104 104 { ··· 111 111 }; 112 112 struct nouveau_display *disp = nouveau_display(crtc->dev); 113 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 117 do { 117 118 ret = nvif_mthd(&disp->disp, 0, &args, sizeof(args)); 118 119 if (ret != 0) 119 - return 0; 120 + return false; 120 121 121 122 if (args.scan.vline) { 122 - ret |= DRM_SCANOUTPOS_ACCURATE; 123 - ret |= DRM_SCANOUTPOS_VALID; 123 + ret = true; 124 124 break; 125 125 } 126 126 ··· 133 133 if (stime) *stime = ns_to_ktime(args.scan.time[0]); 134 134 if (etime) *etime = ns_to_ktime(args.scan.time[1]); 135 135 136 - if (*vpos < 0) 137 - ret |= DRM_SCANOUTPOS_IN_VBLANK; 138 136 return ret; 139 137 } 140 138 141 - int 139 + bool 142 140 nouveau_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 142 ktime_t *stime, ktime_t *etime, 145 143 const struct drm_display_mode *mode) 146 144 { ··· 148 150 if (nouveau_crtc(crtc)->index == pipe) { 149 151 return nouveau_display_scanoutpos_head(crtc, vpos, hpos, 150 152 stime, etime); 151 - } 152 - } 153 - 154 - return 0; 155 - } 156 - 157 - bool 158 - nouveau_display_vblstamp(struct drm_device *dev, unsigned int pipe, 159 - int *max_error, struct timeval *time, bool in_vblank_irq) 160 - { 161 - struct drm_crtc *crtc; 162 - 163 - list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) { 164 - if (nouveau_crtc(crtc)->index == pipe) { 165 - struct drm_display_mode *mode; 166 - if (drm_drv_uses_atomic_modeset(dev)) 167 - mode = &crtc->state->adjusted_mode; 168 - else 169 - mode = &crtc->hwmode; 170 - return drm_calc_vbltimestamp_from_scanoutpos(dev, 171 - pipe, max_error, time, in_vblank_irq, 172 - mode); 173 153 } 174 154 } 175 155
+3 -5
drivers/gpu/drm/nouveau/nouveau_display.h
··· 68 68 void nouveau_display_resume(struct drm_device *dev, bool runtime); 69 69 int nouveau_display_vblank_enable(struct drm_device *, unsigned int); 70 70 void nouveau_display_vblank_disable(struct drm_device *, unsigned int); 71 - int nouveau_display_scanoutpos(struct drm_device *, unsigned int, 72 - unsigned int, int *, int *, ktime_t *, 73 - ktime_t *, const struct drm_display_mode *); 74 - bool nouveau_display_vblstamp(struct drm_device *, unsigned int, int *, 75 - struct timeval *, bool); 71 + bool nouveau_display_scanoutpos(struct drm_device *, unsigned int, 72 + bool, int *, int *, ktime_t *, 73 + ktime_t *, const struct drm_display_mode *); 76 74 77 75 int nouveau_crtc_page_flip(struct drm_crtc *crtc, struct drm_framebuffer *fb, 78 76 struct drm_pending_vblank_event *event,
+1 -1
drivers/gpu/drm/nouveau/nouveau_drm.c
··· 978 978 .enable_vblank = nouveau_display_vblank_enable, 979 979 .disable_vblank = nouveau_display_vblank_disable, 980 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 983 .ioctls = nouveau_ioctls, 984 984 .num_ioctls = ARRAY_SIZE(nouveau_ioctls),
+12 -6
drivers/gpu/drm/radeon/radeon_drv.c
··· 115 115 u32 radeon_get_vblank_counter_kms(struct drm_device *dev, unsigned int pipe); 116 116 int radeon_enable_vblank_kms(struct drm_device *dev, unsigned int pipe); 117 117 void radeon_disable_vblank_kms(struct drm_device *dev, unsigned int pipe); 118 - bool 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); 122 118 void radeon_driver_irq_preinstall_kms(struct drm_device *dev); 123 119 int radeon_driver_irq_postinstall_kms(struct drm_device *dev); 124 120 void radeon_driver_irq_uninstall_kms(struct drm_device *dev); ··· 526 530 #endif 527 531 }; 528 532 533 + static bool 534 + radeon_get_crtc_scanout_position(struct drm_device *dev, unsigned int pipe, 535 + bool in_vblank_irq, int *vpos, int *hpos, 536 + ktime_t *stime, ktime_t *etime, 537 + const struct drm_display_mode *mode) 538 + { 539 + return radeon_get_crtc_scanoutpos(dev, pipe, 0, vpos, hpos, 540 + stime, etime, mode); 541 + } 542 + 529 543 static struct drm_driver kms_driver = { 530 544 .driver_features = 531 545 DRIVER_USE_AGP | ··· 550 544 .get_vblank_counter = radeon_get_vblank_counter_kms, 551 545 .enable_vblank = radeon_enable_vblank_kms, 552 546 .disable_vblank = radeon_disable_vblank_kms, 553 - .get_vblank_timestamp = radeon_get_vblank_timestamp_kms, 554 - .get_scanout_position = radeon_get_crtc_scanoutpos, 547 + .get_vblank_timestamp = drm_calc_vbltimestamp_from_scanoutpos, 548 + .get_scanout_position = radeon_get_crtc_scanout_position, 555 549 .irq_preinstall = radeon_driver_irq_preinstall_kms, 556 550 .irq_postinstall = radeon_driver_irq_postinstall_kms, 557 551 .irq_uninstall = radeon_driver_irq_uninstall_kms,
-37
drivers/gpu/drm/radeon/radeon_kms.c
··· 858 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 - */ 874 - bool 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 - 898 861 const struct drm_ioctl_desc radeon_ioctls_kms[] = { 899 862 DRM_IOCTL_DEF_DRV(RADEON_CP_INIT, drm_invalid_op, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 900 863 DRM_IOCTL_DEF_DRV(RADEON_CP_START, drm_invalid_op, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
+3
drivers/gpu/drm/radeon/radeon_mode.h
··· 691 691 }; 692 692 693 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 697 #define USE_REAL_VBLANKSTART (1 << 30) 695 698 #define GET_DISTANCE_TO_VBLANKSTART (1 << 31) 696 699
+10 -24
drivers/gpu/drm/vc4/vc4_crtc.c
··· 151 151 } 152 152 #endif 153 153 154 - int vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id, 155 - unsigned int flags, int *vpos, int *hpos, 156 - ktime_t *stime, ktime_t *etime, 157 - const struct drm_display_mode *mode) 154 + bool vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id, 155 + bool in_vblank_irq, int *vpos, int *hpos, 156 + ktime_t *stime, ktime_t *etime, 157 + const struct drm_display_mode *mode) 158 158 { 159 159 struct vc4_dev *vc4 = to_vc4_dev(dev); 160 160 struct drm_crtc *crtc = drm_crtc_from_index(dev, crtc_id); ··· 162 162 u32 val; 163 163 int fifo_lines; 164 164 int vblank_lines; 165 - int ret = 0; 165 + bool ret = false; 166 166 167 167 /* preempt_disable_rt() should go right here in PREEMPT_RT patchset. */ 168 168 ··· 198 198 fifo_lines = vc4_crtc->cob_size / mode->crtc_hdisplay; 199 199 200 200 if (fifo_lines > 0) 201 - ret |= DRM_SCANOUTPOS_VALID; 201 + ret = true; 202 202 203 203 /* HVS more than fifo_lines into frame for compositing? */ 204 204 if (*vpos > fifo_lines) { ··· 216 216 */ 217 217 *vpos -= fifo_lines + 1; 218 218 219 - ret |= DRM_SCANOUTPOS_ACCURATE; 220 219 return ret; 221 220 } 222 221 ··· 228 229 * We can't get meaningful readings wrt. scanline position of the PV 229 230 * and need to make things up in a approximative but consistent way. 230 231 */ 231 - ret |= DRM_SCANOUTPOS_IN_VBLANK; 232 232 vblank_lines = mode->vtotal - mode->vdisplay; 233 233 234 - if (flags & DRM_CALLED_FROM_VBLIRQ) { 234 + if (in_vblank_irq) { 235 235 /* 236 236 * Assume the irq handler got called close to first 237 237 * line of vblank, so PV has about a full vblank ··· 252 254 * we are at the very beginning of vblank, as the hvs just 253 255 * started refilling, and the stime and etime timestamps 254 256 * truly correspond to start of vblank. 257 + * 258 + * Unfortunately there's no way to report this to upper levels 259 + * and make it more useful. 255 260 */ 256 - if ((val & SCALER_DISPSTATX_FULL) != SCALER_DISPSTATX_FULL) 257 - ret |= DRM_SCANOUTPOS_ACCURATE; 258 261 } else { 259 262 /* 260 263 * No clue where we are inside vblank. Return a vpos of zero, ··· 267 268 } 268 269 269 270 return ret; 270 - } 271 - 272 - bool vc4_crtc_get_vblank_timestamp(struct drm_device *dev, unsigned int crtc_id, 273 - int *max_error, struct timeval *vblank_time, 274 - bool in_vblank_irq) 275 - { 276 - struct drm_crtc *crtc = drm_crtc_from_index(dev, crtc_id); 277 - struct drm_crtc_state *state = crtc->state; 278 - 279 - /* Helper routine in DRM core does all the work: */ 280 - return drm_calc_vbltimestamp_from_scanoutpos(dev, crtc_id, max_error, 281 - vblank_time, in_vblank_irq, 282 - &state->adjusted_mode); 283 271 } 284 272 285 273 static void vc4_crtc_destroy(struct drm_crtc *crtc)
+1 -1
drivers/gpu/drm/vc4/vc4_drv.c
··· 154 154 .irq_uninstall = vc4_irq_uninstall, 155 155 156 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 159 #if defined(CONFIG_DEBUG_FS) 160 160 .debugfs_init = vc4_debugfs_init,
+4 -7
drivers/gpu/drm/vc4/vc4_drv.h
··· 489 489 extern struct platform_driver vc4_crtc_driver; 490 490 bool vc4_event_pending(struct drm_crtc *crtc); 491 491 int vc4_crtc_debugfs_regs(struct seq_file *m, void *arg); 492 - int vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id, 493 - unsigned int flags, int *vpos, int *hpos, 494 - ktime_t *stime, ktime_t *etime, 495 - const struct drm_display_mode *mode); 496 - bool 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); 492 + bool vc4_crtc_get_scanoutpos(struct drm_device *dev, unsigned int crtc_id, 493 + bool in_vblank_irq, int *vpos, int *hpos, 494 + ktime_t *stime, ktime_t *etime, 495 + const struct drm_display_mode *mode); 499 496 500 497 /* vc4_debugfs.c */ 501 498 int vc4_debugfs_init(struct drm_minor *minor);
-8
include/drm/drmP.h
··· 320 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 324 * DRM device structure. This structure represent a complete card that 333 325 * may contain multiple heads.
+6 -14
include/drm/drm_drv.h
··· 265 265 * 266 266 * Returns: 267 267 * 268 - * Flags, or'ed together as follows: 269 - * 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. 268 + * True on success, false if a reliable scanout position counter could 269 + * not be read out. 278 270 * 279 271 * FIXME: 280 272 * ··· 274 282 * move it to &struct drm_crtc_helper_funcs, like all the other 275 283 * helper-internal hooks. 276 284 */ 277 - int (*get_scanout_position) (struct drm_device *dev, unsigned int pipe, 278 - unsigned int flags, int *vpos, int *hpos, 279 - ktime_t *stime, ktime_t *etime, 280 - const struct drm_display_mode *mode); 285 + bool (*get_scanout_position) (struct drm_device *dev, unsigned int pipe, 286 + bool in_vblank_irq, int *vpos, int *hpos, 287 + ktime_t *stime, ktime_t *etime, 288 + const struct drm_display_mode *mode); 281 289 282 290 /** 283 291 * @get_vblank_timestamp:
+13 -2
include/drm/drm_irq.h
··· 121 121 * drm_calc_timestamping_constants(). 122 122 */ 123 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 137 * @enabled: Tracks the enabling state of the corresponding &drm_crtc to 126 138 * avoid double-disabling and hence corrupting saved state. Needed by ··· 168 156 bool drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, 169 157 unsigned int pipe, int *max_error, 170 158 struct timeval *vblank_time, 171 - bool in_vblank_irq, 172 - const struct drm_display_mode *mode); 159 + bool in_vblank_irq); 173 160 void drm_calc_timestamping_constants(struct drm_crtc *crtc, 174 161 const struct drm_display_mode *mode); 175 162