aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_irq.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/drm_irq.c')
-rw-r--r--drivers/gpu/drm/drm_irq.c129
1 files changed, 72 insertions, 57 deletions
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
index 8c866cac62dd..c7debaad67f8 100644
--- a/drivers/gpu/drm/drm_irq.c
+++ b/drivers/gpu/drm/drm_irq.c
@@ -54,7 +54,7 @@
54 54
55static bool 55static bool
56drm_get_last_vbltimestamp(struct drm_device *dev, unsigned int pipe, 56drm_get_last_vbltimestamp(struct drm_device *dev, unsigned int pipe,
57 struct timeval *tvblank, unsigned flags); 57 struct timeval *tvblank, bool in_vblank_irq);
58 58
59static unsigned int drm_timestamp_precision = 20; /* Default to 20 usecs. */ 59static unsigned int drm_timestamp_precision = 20; /* Default to 20 usecs. */
60 60
@@ -138,7 +138,7 @@ static void drm_reset_vblank_timestamp(struct drm_device *dev, unsigned int pipe
138 */ 138 */
139 do { 139 do {
140 cur_vblank = __get_vblank_counter(dev, pipe); 140 cur_vblank = __get_vblank_counter(dev, pipe);
141 rc = drm_get_last_vbltimestamp(dev, pipe, &t_vblank, 0); 141 rc = drm_get_last_vbltimestamp(dev, pipe, &t_vblank, false);
142 } while (cur_vblank != __get_vblank_counter(dev, pipe) && --count > 0); 142 } while (cur_vblank != __get_vblank_counter(dev, pipe) && --count > 0);
143 143
144 /* 144 /*
@@ -171,7 +171,7 @@ static void drm_reset_vblank_timestamp(struct drm_device *dev, unsigned int pipe
171 * device vblank fields. 171 * device vblank fields.
172 */ 172 */
173static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe, 173static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe,
174 unsigned long flags) 174 bool in_vblank_irq)
175{ 175{
176 struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; 176 struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
177 u32 cur_vblank, diff; 177 u32 cur_vblank, diff;
@@ -194,7 +194,7 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe,
194 */ 194 */
195 do { 195 do {
196 cur_vblank = __get_vblank_counter(dev, pipe); 196 cur_vblank = __get_vblank_counter(dev, pipe);
197 rc = drm_get_last_vbltimestamp(dev, pipe, &t_vblank, flags); 197 rc = drm_get_last_vbltimestamp(dev, pipe, &t_vblank, in_vblank_irq);
198 } while (cur_vblank != __get_vblank_counter(dev, pipe) && --count > 0); 198 } while (cur_vblank != __get_vblank_counter(dev, pipe) && --count > 0);
199 199
200 if (dev->max_vblank_count != 0) { 200 if (dev->max_vblank_count != 0) {
@@ -214,13 +214,13 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe,
214 */ 214 */
215 diff = DIV_ROUND_CLOSEST_ULL(diff_ns, framedur_ns); 215 diff = DIV_ROUND_CLOSEST_ULL(diff_ns, framedur_ns);
216 216
217 if (diff == 0 && flags & DRM_CALLED_FROM_VBLIRQ) 217 if (diff == 0 && in_vblank_irq)
218 DRM_DEBUG_VBL("crtc %u: Redundant vblirq ignored." 218 DRM_DEBUG_VBL("crtc %u: Redundant vblirq ignored."
219 " diff_ns = %lld, framedur_ns = %d)\n", 219 " diff_ns = %lld, framedur_ns = %d)\n",
220 pipe, (long long) diff_ns, framedur_ns); 220 pipe, (long long) diff_ns, framedur_ns);
221 } else { 221 } else {
222 /* some kind of default for drivers w/o accurate vbl timestamping */ 222 /* some kind of default for drivers w/o accurate vbl timestamping */
223 diff = (flags & DRM_CALLED_FROM_VBLIRQ) != 0; 223 diff = in_vblank_irq ? 1 : 0;
224 } 224 }
225 225
226 /* 226 /*
@@ -253,7 +253,7 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe,
253 * Otherwise reinitialize delayed at next vblank interrupt and assign 0 253 * Otherwise reinitialize delayed at next vblank interrupt and assign 0
254 * for now, to mark the vblanktimestamp as invalid. 254 * for now, to mark the vblanktimestamp as invalid.
255 */ 255 */
256 if (!rc && (flags & DRM_CALLED_FROM_VBLIRQ) == 0) 256 if (!rc && in_vblank_irq)
257 t_vblank = (struct timeval) {0, 0}; 257 t_vblank = (struct timeval) {0, 0};
258 258
259 store_vblank(dev, pipe, diff, &t_vblank, cur_vblank); 259 store_vblank(dev, pipe, diff, &t_vblank, cur_vblank);
@@ -291,7 +291,7 @@ u32 drm_accurate_vblank_count(struct drm_crtc *crtc)
291 291
292 spin_lock_irqsave(&dev->vblank_time_lock, flags); 292 spin_lock_irqsave(&dev->vblank_time_lock, flags);
293 293
294 drm_update_vblank_count(dev, pipe, 0); 294 drm_update_vblank_count(dev, pipe, false);
295 vblank = drm_vblank_count(dev, pipe); 295 vblank = drm_vblank_count(dev, pipe);
296 296
297 spin_unlock_irqrestore(&dev->vblank_time_lock, flags); 297 spin_unlock_irqrestore(&dev->vblank_time_lock, flags);
@@ -349,7 +349,7 @@ static void vblank_disable_and_save(struct drm_device *dev, unsigned int pipe)
349 * this time. This makes the count account for the entire time 349 * this time. This makes the count account for the entire time
350 * between drm_crtc_vblank_on() and drm_crtc_vblank_off(). 350 * between drm_crtc_vblank_on() and drm_crtc_vblank_off().
351 */ 351 */
352 drm_update_vblank_count(dev, pipe, 0); 352 drm_update_vblank_count(dev, pipe, false);
353 353
354 spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags); 354 spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags);
355} 355}
@@ -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,
@@ -700,10 +701,10 @@ EXPORT_SYMBOL(drm_calc_timestamping_constants);
700 * @max_error: Desired maximum allowable error in timestamps (nanosecs) 701 * @max_error: Desired maximum allowable error in timestamps (nanosecs)
701 * On return contains true maximum error of timestamp 702 * On return contains true maximum error of timestamp
702 * @vblank_time: Pointer to struct timeval which should receive the timestamp 703 * @vblank_time: Pointer to struct timeval which should receive the timestamp
703 * @flags: Flags to pass to driver: 704 * @in_vblank_irq:
704 * 0 = Default, 705 * True when called from drm_crtc_handle_vblank(). Some drivers
705 * DRM_CALLED_FROM_VBLIRQ = If function is called from vbl IRQ handler 706 * need to apply some workarounds for gpu-specific vblank irq quirks
706 * @mode: mode which defines the scanout timings 707 * if flag is set.
707 * 708 *
708 * Implements calculation of exact vblank timestamps from given drm_display_mode 709 * Implements calculation of exact vblank timestamps from given drm_display_mode
709 * 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
@@ -723,52 +724,62 @@ EXPORT_SYMBOL(drm_calc_timestamping_constants);
723 * 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
724 * active. Higher level code is expected to handle this. 725 * active. Higher level code is expected to handle this.
725 * 726 *
726 * Returns: 727 * This function can be used to implement the &drm_driver.get_vblank_timestamp
727 * Negative value on error, failure or if not supported in current 728 * directly, if the driver implements the &drm_driver.get_scanout_position hook.
728 * video mode:
729 *
730 * -EINVAL Invalid CRTC.
731 * -EAGAIN Temporary unavailable, e.g., called before initial modeset.
732 * -ENOTSUPP Function not supported in current display mode.
733 * -EIO Failed, e.g., due to failed scanout position query.
734 * 729 *
735 * Returns or'ed positive status flags on success: 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().
736 * 733 *
737 * DRM_VBLANKTIME_SCANOUTPOS_METHOD - Signal this method used for timestamping. 734 * Returns:
738 * DRM_VBLANKTIME_INVBL - Timestamp taken while scanout was in vblank interval.
739 * 735 *
736 * Returns true on success, and false on failure, i.e. when no accurate
737 * timestamp could be acquired.
740 */ 738 */
741int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, 739bool drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
742 unsigned int pipe, 740 unsigned int pipe,
743 int *max_error, 741 int *max_error,
744 struct timeval *vblank_time, 742 struct timeval *vblank_time,
745 unsigned flags, 743 bool in_vblank_irq)
746 const struct drm_display_mode *mode)
747{ 744{
748 struct timeval tv_etime; 745 struct timeval tv_etime;
749 ktime_t stime, etime; 746 ktime_t stime, etime;
750 unsigned int vbl_status; 747 bool vbl_status;
751 int ret = DRM_VBLANKTIME_SCANOUTPOS_METHOD; 748 struct drm_crtc *crtc;
749 const struct drm_display_mode *mode;
750 struct drm_vblank_crtc *vblank = &dev->vblank[pipe];
752 int vpos, hpos, i; 751 int vpos, hpos, i;
753 int delta_ns, duration_ns; 752 int delta_ns, duration_ns;
754 753
755 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) {
756 DRM_ERROR("Invalid crtc %u\n", pipe); 760 DRM_ERROR("Invalid crtc %u\n", pipe);
757 return -EINVAL; 761 return false;
758 } 762 }
759 763
760 /* Scanout position query not supported? Should not happen. */ 764 /* Scanout position query not supported? Should not happen. */
761 if (!dev->driver->get_scanout_position) { 765 if (!dev->driver->get_scanout_position) {
762 DRM_ERROR("Called from driver w/o get_scanout_position()!?\n"); 766 DRM_ERROR("Called from driver w/o get_scanout_position()!?\n");
763 return -EIO; 767 return false;
764 } 768 }
765 769
770 if (drm_drv_uses_atomic_modeset(dev))
771 mode = &vblank->hwmode;
772 else
773 mode = &crtc->hwmode;
774
766 /* If mode timing undefined, just return as no-op: 775 /* If mode timing undefined, just return as no-op:
767 * Happens during initial modesetting of a crtc. 776 * Happens during initial modesetting of a crtc.
768 */ 777 */
769 if (mode->crtc_clock == 0) { 778 if (mode->crtc_clock == 0) {
770 DRM_DEBUG("crtc %u: Noop due to uninitialized mode.\n", pipe); 779 DRM_DEBUG("crtc %u: Noop due to uninitialized mode.\n", pipe);
771 return -EAGAIN; 780 WARN_ON_ONCE(drm_drv_uses_atomic_modeset(dev));
781
782 return false;
772 } 783 }
773 784
774 /* Get current scanout position with system timestamp. 785 /* Get current scanout position with system timestamp.
@@ -783,16 +794,17 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
783 * Get vertical and horizontal scanout position vpos, hpos, 794 * Get vertical and horizontal scanout position vpos, hpos,
784 * and bounding timestamps stime, etime, pre/post query. 795 * and bounding timestamps stime, etime, pre/post query.
785 */ 796 */
786 vbl_status = dev->driver->get_scanout_position(dev, pipe, flags, 797 vbl_status = dev->driver->get_scanout_position(dev, pipe,
798 in_vblank_irq,
787 &vpos, &hpos, 799 &vpos, &hpos,
788 &stime, &etime, 800 &stime, &etime,
789 mode); 801 mode);
790 802
791 /* Return as no-op if scanout query unsupported or failed. */ 803 /* Return as no-op if scanout query unsupported or failed. */
792 if (!(vbl_status & DRM_SCANOUTPOS_VALID)) { 804 if (!vbl_status) {
793 DRM_DEBUG("crtc %u : scanoutpos query failed [0x%x].\n", 805 DRM_DEBUG("crtc %u : scanoutpos query failed.\n",
794 pipe, vbl_status); 806 pipe);
795 return -EIO; 807 return false;
796 } 808 }
797 809
798 /* Compute uncertainty in timestamp of scanout position query. */ 810 /* Compute uncertainty in timestamp of scanout position query. */
@@ -830,13 +842,13 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev,
830 etime = ktime_sub_ns(etime, delta_ns); 842 etime = ktime_sub_ns(etime, delta_ns);
831 *vblank_time = ktime_to_timeval(etime); 843 *vblank_time = ktime_to_timeval(etime);
832 844
833 DRM_DEBUG_VBL("crtc %u : v 0x%x p(%d,%d)@ %ld.%ld -> %ld.%ld [e %d us, %d rep]\n", 845 DRM_DEBUG_VBL("crtc %u : v p(%d,%d)@ %ld.%ld -> %ld.%ld [e %d us, %d rep]\n",
834 pipe, vbl_status, hpos, vpos, 846 pipe, hpos, vpos,
835 (long)tv_etime.tv_sec, (long)tv_etime.tv_usec, 847 (long)tv_etime.tv_sec, (long)tv_etime.tv_usec,
836 (long)vblank_time->tv_sec, (long)vblank_time->tv_usec, 848 (long)vblank_time->tv_sec, (long)vblank_time->tv_usec,
837 duration_ns/1000, i); 849 duration_ns/1000, i);
838 850
839 return ret; 851 return true;
840} 852}
841EXPORT_SYMBOL(drm_calc_vbltimestamp_from_scanoutpos); 853EXPORT_SYMBOL(drm_calc_vbltimestamp_from_scanoutpos);
842 854
@@ -854,9 +866,10 @@ static struct timeval get_drm_timestamp(void)
854 * @dev: DRM device 866 * @dev: DRM device
855 * @pipe: index of CRTC whose vblank timestamp to retrieve 867 * @pipe: index of CRTC whose vblank timestamp to retrieve
856 * @tvblank: Pointer to target struct timeval which should receive the timestamp 868 * @tvblank: Pointer to target struct timeval which should receive the timestamp
857 * @flags: Flags to pass to driver: 869 * @in_vblank_irq:
858 * 0 = Default, 870 * True when called from drm_crtc_handle_vblank(). Some drivers
859 * DRM_CALLED_FROM_VBLIRQ = If function is called from vbl IRQ handler 871 * need to apply some workarounds for gpu-specific vblank irq quirks
872 * if flag is set.
860 * 873 *
861 * Fetches the system timestamp corresponding to the time of the most recent 874 * Fetches the system timestamp corresponding to the time of the most recent
862 * vblank interval on specified CRTC. May call into kms-driver to 875 * vblank interval on specified CRTC. May call into kms-driver to
@@ -870,27 +883,25 @@ static struct timeval get_drm_timestamp(void)
870 */ 883 */
871static bool 884static bool
872drm_get_last_vbltimestamp(struct drm_device *dev, unsigned int pipe, 885drm_get_last_vbltimestamp(struct drm_device *dev, unsigned int pipe,
873 struct timeval *tvblank, unsigned flags) 886 struct timeval *tvblank, bool in_vblank_irq)
874{ 887{
875 int ret; 888 bool ret = false;
876 889
877 /* Define requested maximum error on timestamps (nanoseconds). */ 890 /* Define requested maximum error on timestamps (nanoseconds). */
878 int max_error = (int) drm_timestamp_precision * 1000; 891 int max_error = (int) drm_timestamp_precision * 1000;
879 892
880 /* Query driver if possible and precision timestamping enabled. */ 893 /* Query driver if possible and precision timestamping enabled. */
881 if (dev->driver->get_vblank_timestamp && (max_error > 0)) { 894 if (dev->driver->get_vblank_timestamp && (max_error > 0))
882 ret = dev->driver->get_vblank_timestamp(dev, pipe, &max_error, 895 ret = dev->driver->get_vblank_timestamp(dev, pipe, &max_error,
883 tvblank, flags); 896 tvblank, in_vblank_irq);
884 if (ret > 0)
885 return true;
886 }
887 897
888 /* GPU high precision timestamp query unsupported or failed. 898 /* GPU high precision timestamp query unsupported or failed.
889 * Return current monotonic/gettimeofday timestamp as best estimate. 899 * Return current monotonic/gettimeofday timestamp as best estimate.
890 */ 900 */
891 *tvblank = get_drm_timestamp(); 901 if (!ret)
902 *tvblank = get_drm_timestamp();
892 903
893 return false; 904 return ret;
894} 905}
895 906
896/** 907/**
@@ -1329,6 +1340,10 @@ void drm_crtc_vblank_off(struct drm_crtc *crtc)
1329 send_vblank_event(dev, e, seq, &now); 1340 send_vblank_event(dev, e, seq, &now);
1330 } 1341 }
1331 spin_unlock_irqrestore(&dev->event_lock, irqflags); 1342 spin_unlock_irqrestore(&dev->event_lock, irqflags);
1343
1344 /* Will be reset by the modeset helpers when re-enabling the crtc by
1345 * calling drm_calc_timestamping_constants(). */
1346 vblank->hwmode.crtc_clock = 0;
1332} 1347}
1333EXPORT_SYMBOL(drm_crtc_vblank_off); 1348EXPORT_SYMBOL(drm_crtc_vblank_off);
1334 1349
@@ -1760,7 +1775,7 @@ bool drm_handle_vblank(struct drm_device *dev, unsigned int pipe)
1760 return false; 1775 return false;
1761 } 1776 }
1762 1777
1763 drm_update_vblank_count(dev, pipe, DRM_CALLED_FROM_VBLIRQ); 1778 drm_update_vblank_count(dev, pipe, true);
1764 1779
1765 spin_unlock(&dev->vblank_time_lock); 1780 spin_unlock(&dev->vblank_time_lock);
1766 1781