aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_irq.c
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2014-09-11 08:46:53 -0400
committerDaniel Vetter <daniel.vetter@ffwll.ch>2014-09-11 08:46:53 -0400
commit336879b1da97fffc097f77c6d6f818660f2826f0 (patch)
tree4ddb4d1c5d2b67fb096c72e41d2a03b01a605041 /drivers/gpu/drm/drm_irq.c
parent3d3cbd84300e7be1e53083cac0f6f9c12978ecb4 (diff)
parentfdcaa1dbb7c6ed419b10fb8cdb5001ab0a00538f (diff)
Merge remote-tracking branch 'airlied/drm-next' into topic/vblank-rework
Dave asked me to do the backmerge before sending him the revised pull request, so here we go. Nothing fancy in the conflicts, just a few things changed right next to each another. Conflicts: drivers/gpu/drm/drm_irq.c Signed-off-by: Daniel Vetter <daniel.vetter@intel.com>
Diffstat (limited to 'drivers/gpu/drm/drm_irq.c')
-rw-r--r--drivers/gpu/drm/drm_irq.c84
1 files changed, 71 insertions, 13 deletions
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c
index 79836594030c..034297640b48 100644
--- a/drivers/gpu/drm/drm_irq.c
+++ b/drivers/gpu/drm/drm_irq.c
@@ -639,8 +639,8 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
639 const struct drm_crtc *refcrtc, 639 const struct drm_crtc *refcrtc,
640 const struct drm_display_mode *mode) 640 const struct drm_display_mode *mode)
641{ 641{
642 ktime_t stime, etime, mono_time_offset;
643 struct timeval tv_etime; 642 struct timeval tv_etime;
643 ktime_t stime, etime;
644 int vbl_status; 644 int vbl_status;
645 int vpos, hpos, i; 645 int vpos, hpos, i;
646 int framedur_ns, linedur_ns, pixeldur_ns, delta_ns, duration_ns; 646 int framedur_ns, linedur_ns, pixeldur_ns, delta_ns, duration_ns;
@@ -685,13 +685,6 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
685 vbl_status = dev->driver->get_scanout_position(dev, crtc, flags, &vpos, 685 vbl_status = dev->driver->get_scanout_position(dev, crtc, flags, &vpos,
686 &hpos, &stime, &etime); 686 &hpos, &stime, &etime);
687 687
688 /*
689 * Get correction for CLOCK_MONOTONIC -> CLOCK_REALTIME if
690 * CLOCK_REALTIME is requested.
691 */
692 if (!drm_timestamp_monotonic)
693 mono_time_offset = ktime_get_monotonic_offset();
694
695 /* Return as no-op if scanout query unsupported or failed. */ 688 /* Return as no-op if scanout query unsupported or failed. */
696 if (!(vbl_status & DRM_SCANOUTPOS_VALID)) { 689 if (!(vbl_status & DRM_SCANOUTPOS_VALID)) {
697 DRM_DEBUG("crtc %d : scanoutpos query failed [%d].\n", 690 DRM_DEBUG("crtc %d : scanoutpos query failed [%d].\n",
@@ -730,7 +723,7 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc,
730 delta_ns = vpos * linedur_ns + hpos * pixeldur_ns; 723 delta_ns = vpos * linedur_ns + hpos * pixeldur_ns;
731 724
732 if (!drm_timestamp_monotonic) 725 if (!drm_timestamp_monotonic)
733 etime = ktime_sub(etime, mono_time_offset); 726 etime = ktime_mono_to_real(etime);
734 727
735 /* save this only for debugging purposes */ 728 /* save this only for debugging purposes */
736 tv_etime = ktime_to_timeval(etime); 729 tv_etime = ktime_to_timeval(etime);
@@ -761,10 +754,7 @@ static struct timeval get_drm_timestamp(void)
761{ 754{
762 ktime_t now; 755 ktime_t now;
763 756
764 now = ktime_get(); 757 now = drm_timestamp_monotonic ? ktime_get() : ktime_get_real();
765 if (!drm_timestamp_monotonic)
766 now = ktime_sub(now, ktime_get_monotonic_offset());
767
768 return ktime_to_timeval(now); 758 return ktime_to_timeval(now);
769} 759}
770 760
@@ -829,6 +819,8 @@ u32 drm_vblank_count(struct drm_device *dev, int crtc)
829{ 819{
830 struct drm_vblank_crtc *vblank = &dev->vblank[crtc]; 820 struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
831 821
822 if (WARN_ON(crtc >= dev->num_crtcs))
823 return 0;
832 return atomic_read(&vblank->count); 824 return atomic_read(&vblank->count);
833} 825}
834EXPORT_SYMBOL(drm_vblank_count); 826EXPORT_SYMBOL(drm_vblank_count);
@@ -852,6 +844,9 @@ u32 drm_vblank_count_and_time(struct drm_device *dev, int crtc,
852 struct drm_vblank_crtc *vblank = &dev->vblank[crtc]; 844 struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
853 u32 cur_vblank; 845 u32 cur_vblank;
854 846
847 if (WARN_ON(crtc >= dev->num_crtcs))
848 return 0;
849
855 /* Read timestamp from slot of _vblank_time ringbuffer 850 /* Read timestamp from slot of _vblank_time ringbuffer
856 * that corresponds to current vblank count. Retry if 851 * that corresponds to current vblank count. Retry if
857 * count has incremented during readout. This works like 852 * count has incremented during readout. This works like
@@ -965,6 +960,9 @@ int drm_vblank_get(struct drm_device *dev, int crtc)
965 unsigned long irqflags; 960 unsigned long irqflags;
966 int ret = 0; 961 int ret = 0;
967 962
963 if (WARN_ON(crtc >= dev->num_crtcs))
964 return -EINVAL;
965
968 spin_lock_irqsave(&dev->vbl_lock, irqflags); 966 spin_lock_irqsave(&dev->vbl_lock, irqflags);
969 /* Going from 0->1 means we have to enable interrupts again */ 967 /* Going from 0->1 means we have to enable interrupts again */
970 if (atomic_add_return(1, &vblank->refcount) == 1) { 968 if (atomic_add_return(1, &vblank->refcount) == 1) {
@@ -1015,6 +1013,9 @@ void drm_vblank_put(struct drm_device *dev, int crtc)
1015 1013
1016 BUG_ON(atomic_read(&vblank->refcount) == 0); 1014 BUG_ON(atomic_read(&vblank->refcount) == 0);
1017 1015
1016 if (WARN_ON(crtc >= dev->num_crtcs))
1017 return;
1018
1018 /* Last user schedules interrupt disable */ 1019 /* Last user schedules interrupt disable */
1019 if (atomic_dec_and_test(&vblank->refcount)) { 1020 if (atomic_dec_and_test(&vblank->refcount)) {
1020 if (drm_vblank_offdelay == 0) 1021 if (drm_vblank_offdelay == 0)
@@ -1044,6 +1045,50 @@ void drm_crtc_vblank_put(struct drm_crtc *crtc)
1044EXPORT_SYMBOL(drm_crtc_vblank_put); 1045EXPORT_SYMBOL(drm_crtc_vblank_put);
1045 1046
1046/** 1047/**
1048 * drm_wait_one_vblank - wait for one vblank
1049 * @dev: DRM device
1050 * @crtc: crtc index
1051 *
1052 * This waits for one vblank to pass on @crtc, using the irq driver interfaces.
1053 * It is a failure to call this when the vblank irq for @crtc is disabled, e.g.
1054 * due to lack of driver support or because the crtc is off.
1055 */
1056void drm_wait_one_vblank(struct drm_device *dev, int crtc)
1057{
1058 int ret;
1059 u32 last;
1060
1061 ret = drm_vblank_get(dev, crtc);
1062 if (WARN_ON(ret))
1063 return;
1064
1065 last = drm_vblank_count(dev, crtc);
1066
1067 ret = wait_event_timeout(dev->vblank[crtc].queue,
1068 last != drm_vblank_count(dev, crtc),
1069 msecs_to_jiffies(100));
1070
1071 WARN_ON(ret == 0);
1072
1073 drm_vblank_put(dev, crtc);
1074}
1075EXPORT_SYMBOL(drm_wait_one_vblank);
1076
1077/**
1078 * drm_crtc_wait_one_vblank - wait for one vblank
1079 * @crtc: DRM crtc
1080 *
1081 * This waits for one vblank to pass on @crtc, using the irq driver interfaces.
1082 * It is a failure to call this when the vblank irq for @crtc is disabled, e.g.
1083 * due to lack of driver support or because the crtc is off.
1084 */
1085void drm_crtc_wait_one_vblank(struct drm_crtc *crtc)
1086{
1087 drm_wait_one_vblank(crtc->dev, drm_crtc_index(crtc));
1088}
1089EXPORT_SYMBOL(drm_crtc_wait_one_vblank);
1090
1091/**
1047 * drm_vblank_off - disable vblank events on a CRTC 1092 * drm_vblank_off - disable vblank events on a CRTC
1048 * @dev: DRM device 1093 * @dev: DRM device
1049 * @crtc: CRTC in question 1094 * @crtc: CRTC in question
@@ -1065,6 +1110,9 @@ void drm_vblank_off(struct drm_device *dev, int crtc)
1065 unsigned long irqflags; 1110 unsigned long irqflags;
1066 unsigned int seq; 1111 unsigned int seq;
1067 1112
1113 if (WARN_ON(crtc >= dev->num_crtcs))
1114 return;
1115
1068 spin_lock_irqsave(&dev->event_lock, irqflags); 1116 spin_lock_irqsave(&dev->event_lock, irqflags);
1069 1117
1070 spin_lock(&dev->vbl_lock); 1118 spin_lock(&dev->vbl_lock);
@@ -1134,6 +1182,9 @@ void drm_vblank_on(struct drm_device *dev, int crtc)
1134 struct drm_vblank_crtc *vblank = &dev->vblank[crtc]; 1182 struct drm_vblank_crtc *vblank = &dev->vblank[crtc];
1135 unsigned long irqflags; 1183 unsigned long irqflags;
1136 1184
1185 if (WARN_ON(crtc >= dev->num_crtcs))
1186 return;
1187
1137 spin_lock_irqsave(&dev->vbl_lock, irqflags); 1188 spin_lock_irqsave(&dev->vbl_lock, irqflags);
1138 /* Drop our private "prevent drm_vblank_get" refcount */ 1189 /* Drop our private "prevent drm_vblank_get" refcount */
1139 if (vblank->inmodeset) { 1190 if (vblank->inmodeset) {
@@ -1209,6 +1260,10 @@ void drm_vblank_pre_modeset(struct drm_device *dev, int crtc)
1209 /* vblank is not initialized (IRQ not installed ?), or has been freed */ 1260 /* vblank is not initialized (IRQ not installed ?), or has been freed */
1210 if (!dev->num_crtcs) 1261 if (!dev->num_crtcs)
1211 return; 1262 return;
1263
1264 if (WARN_ON(crtc >= dev->num_crtcs))
1265 return;
1266
1212 /* 1267 /*
1213 * To avoid all the problems that might happen if interrupts 1268 * To avoid all the problems that might happen if interrupts
1214 * were enabled/disabled around or between these calls, we just 1269 * were enabled/disabled around or between these calls, we just
@@ -1532,6 +1587,9 @@ bool drm_handle_vblank(struct drm_device *dev, int crtc)
1532 if (!dev->num_crtcs) 1587 if (!dev->num_crtcs)
1533 return false; 1588 return false;
1534 1589
1590 if (WARN_ON(crtc >= dev->num_crtcs))
1591 return false;
1592
1535 spin_lock_irqsave(&dev->event_lock, irqflags); 1593 spin_lock_irqsave(&dev->event_lock, irqflags);
1536 1594
1537 /* Need timestamp lock to prevent concurrent execution with 1595 /* Need timestamp lock to prevent concurrent execution with