aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_irq.c
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 /drivers/gpu/drm/drm_irq.c
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
Diffstat (limited to 'drivers/gpu/drm/drm_irq.c')
-rw-r--r--drivers/gpu/drm/drm_irq.c43
1 files changed, 31 insertions, 12 deletions
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);