diff options
Diffstat (limited to 'drivers/gpu/drm/drm_irq.c')
-rw-r--r-- | drivers/gpu/drm/drm_irq.c | 331 |
1 files changed, 161 insertions, 170 deletions
diff --git a/drivers/gpu/drm/drm_irq.c b/drivers/gpu/drm/drm_irq.c index 22d207e211e7..ed2394e1720b 100644 --- a/drivers/gpu/drm/drm_irq.c +++ b/drivers/gpu/drm/drm_irq.c | |||
@@ -74,22 +74,22 @@ module_param_named(vblankoffdelay, drm_vblank_offdelay, int, 0600); | |||
74 | module_param_named(timestamp_precision_usec, drm_timestamp_precision, int, 0600); | 74 | module_param_named(timestamp_precision_usec, drm_timestamp_precision, int, 0600); |
75 | module_param_named(timestamp_monotonic, drm_timestamp_monotonic, int, 0600); | 75 | module_param_named(timestamp_monotonic, drm_timestamp_monotonic, int, 0600); |
76 | 76 | ||
77 | static void store_vblank(struct drm_device *dev, int crtc, | 77 | static void store_vblank(struct drm_device *dev, unsigned int pipe, |
78 | u32 vblank_count_inc, | 78 | u32 vblank_count_inc, |
79 | struct timeval *t_vblank) | 79 | struct timeval *t_vblank, u32 last) |
80 | { | 80 | { |
81 | struct drm_vblank_crtc *vblank = &dev->vblank[crtc]; | 81 | struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; |
82 | u32 tslot; | 82 | u32 tslot; |
83 | 83 | ||
84 | assert_spin_locked(&dev->vblank_time_lock); | 84 | assert_spin_locked(&dev->vblank_time_lock); |
85 | 85 | ||
86 | if (t_vblank) { | 86 | vblank->last = last; |
87 | /* All writers hold the spinlock, but readers are serialized by | 87 | |
88 | * the latching of vblank->count below. | 88 | /* All writers hold the spinlock, but readers are serialized by |
89 | */ | 89 | * the latching of vblank->count below. |
90 | tslot = vblank->count + vblank_count_inc; | 90 | */ |
91 | vblanktimestamp(dev, crtc, tslot) = *t_vblank; | 91 | tslot = vblank->count + vblank_count_inc; |
92 | } | 92 | vblanktimestamp(dev, pipe, tslot) = *t_vblank; |
93 | 93 | ||
94 | /* | 94 | /* |
95 | * vblank timestamp updates are protected on the write side with | 95 | * vblank timestamp updates are protected on the write side with |
@@ -105,12 +105,60 @@ static void store_vblank(struct drm_device *dev, int crtc, | |||
105 | } | 105 | } |
106 | 106 | ||
107 | /** | 107 | /** |
108 | * drm_reset_vblank_timestamp - reset the last timestamp to the last vblank | ||
109 | * @dev: DRM device | ||
110 | * @pipe: index of CRTC for which to reset the timestamp | ||
111 | * | ||
112 | * Reset the stored timestamp for the current vblank count to correspond | ||
113 | * to the last vblank occurred. | ||
114 | * | ||
115 | * Only to be called from drm_vblank_on(). | ||
116 | * | ||
117 | * Note: caller must hold dev->vbl_lock since this reads & writes | ||
118 | * device vblank fields. | ||
119 | */ | ||
120 | static void drm_reset_vblank_timestamp(struct drm_device *dev, unsigned int pipe) | ||
121 | { | ||
122 | u32 cur_vblank; | ||
123 | bool rc; | ||
124 | struct timeval t_vblank; | ||
125 | int count = DRM_TIMESTAMP_MAXRETRIES; | ||
126 | |||
127 | spin_lock(&dev->vblank_time_lock); | ||
128 | |||
129 | /* | ||
130 | * sample the current counter to avoid random jumps | ||
131 | * when drm_vblank_enable() applies the diff | ||
132 | */ | ||
133 | do { | ||
134 | cur_vblank = dev->driver->get_vblank_counter(dev, pipe); | ||
135 | rc = drm_get_last_vbltimestamp(dev, pipe, &t_vblank, 0); | ||
136 | } while (cur_vblank != dev->driver->get_vblank_counter(dev, pipe) && --count > 0); | ||
137 | |||
138 | /* | ||
139 | * Only reinitialize corresponding vblank timestamp if high-precision query | ||
140 | * available and didn't fail. Otherwise reinitialize delayed at next vblank | ||
141 | * interrupt and assign 0 for now, to mark the vblanktimestamp as invalid. | ||
142 | */ | ||
143 | if (!rc) | ||
144 | t_vblank = (struct timeval) {0, 0}; | ||
145 | |||
146 | /* | ||
147 | * +1 to make sure user will never see the same | ||
148 | * vblank counter value before and after a modeset | ||
149 | */ | ||
150 | store_vblank(dev, pipe, 1, &t_vblank, cur_vblank); | ||
151 | |||
152 | spin_unlock(&dev->vblank_time_lock); | ||
153 | } | ||
154 | |||
155 | /** | ||
108 | * drm_update_vblank_count - update the master vblank counter | 156 | * drm_update_vblank_count - update the master vblank counter |
109 | * @dev: DRM device | 157 | * @dev: DRM device |
110 | * @pipe: counter to update | 158 | * @pipe: counter to update |
111 | * | 159 | * |
112 | * Call back into the driver to update the appropriate vblank counter | 160 | * Call back into the driver to update the appropriate vblank counter |
113 | * (specified by @crtc). Deal with wraparound, if it occurred, and | 161 | * (specified by @pipe). Deal with wraparound, if it occurred, and |
114 | * update the last read value so we can deal with wraparound on the next | 162 | * update the last read value so we can deal with wraparound on the next |
115 | * call if necessary. | 163 | * call if necessary. |
116 | * | 164 | * |
@@ -120,12 +168,15 @@ static void store_vblank(struct drm_device *dev, int crtc, | |||
120 | * Note: caller must hold dev->vbl_lock since this reads & writes | 168 | * Note: caller must hold dev->vbl_lock since this reads & writes |
121 | * device vblank fields. | 169 | * device vblank fields. |
122 | */ | 170 | */ |
123 | static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe) | 171 | static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe, |
172 | unsigned long flags) | ||
124 | { | 173 | { |
125 | struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; | 174 | struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; |
126 | u32 cur_vblank, diff; | 175 | u32 cur_vblank, diff; |
127 | bool rc; | 176 | bool rc; |
128 | struct timeval t_vblank; | 177 | struct timeval t_vblank; |
178 | int count = DRM_TIMESTAMP_MAXRETRIES; | ||
179 | int framedur_ns = vblank->framedur_ns; | ||
129 | 180 | ||
130 | /* | 181 | /* |
131 | * Interrupts were disabled prior to this call, so deal with counter | 182 | * Interrupts were disabled prior to this call, so deal with counter |
@@ -141,23 +192,43 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe) | |||
141 | */ | 192 | */ |
142 | do { | 193 | do { |
143 | cur_vblank = dev->driver->get_vblank_counter(dev, pipe); | 194 | cur_vblank = dev->driver->get_vblank_counter(dev, pipe); |
144 | rc = drm_get_last_vbltimestamp(dev, pipe, &t_vblank, 0); | 195 | rc = drm_get_last_vbltimestamp(dev, pipe, &t_vblank, flags); |
145 | } while (cur_vblank != dev->driver->get_vblank_counter(dev, pipe)); | 196 | } while (cur_vblank != dev->driver->get_vblank_counter(dev, pipe) && --count > 0); |
197 | |||
198 | if (dev->max_vblank_count != 0) { | ||
199 | /* trust the hw counter when it's around */ | ||
200 | diff = (cur_vblank - vblank->last) & dev->max_vblank_count; | ||
201 | } else if (rc && framedur_ns) { | ||
202 | const struct timeval *t_old; | ||
203 | u64 diff_ns; | ||
146 | 204 | ||
147 | /* Deal with counter wrap */ | 205 | t_old = &vblanktimestamp(dev, pipe, vblank->count); |
148 | diff = cur_vblank - vblank->last; | 206 | diff_ns = timeval_to_ns(&t_vblank) - timeval_to_ns(t_old); |
149 | if (cur_vblank < vblank->last) { | 207 | |
150 | diff += dev->max_vblank_count + 1; | 208 | /* |
209 | * Figure out how many vblanks we've missed based | ||
210 | * on the difference in the timestamps and the | ||
211 | * frame/field duration. | ||
212 | */ | ||
213 | diff = DIV_ROUND_CLOSEST_ULL(diff_ns, framedur_ns); | ||
151 | 214 | ||
152 | DRM_DEBUG("last_vblank[%u]=0x%x, cur_vblank=0x%x => diff=0x%x\n", | 215 | if (diff == 0 && flags & DRM_CALLED_FROM_VBLIRQ) |
153 | pipe, vblank->last, cur_vblank, diff); | 216 | DRM_DEBUG("crtc %u: Redundant vblirq ignored." |
217 | " diff_ns = %lld, framedur_ns = %d)\n", | ||
218 | pipe, (long long) diff_ns, framedur_ns); | ||
219 | } else { | ||
220 | /* some kind of default for drivers w/o accurate vbl timestamping */ | ||
221 | diff = (flags & DRM_CALLED_FROM_VBLIRQ) != 0; | ||
154 | } | 222 | } |
155 | 223 | ||
156 | DRM_DEBUG("updating vblank count on crtc %u, missed %d\n", | 224 | DRM_DEBUG("updating vblank count on crtc %u:" |
157 | pipe, diff); | 225 | " current=%u, diff=%u, hw=%u hw_last=%u\n", |
226 | pipe, vblank->count, diff, cur_vblank, vblank->last); | ||
158 | 227 | ||
159 | if (diff == 0) | 228 | if (diff == 0) { |
229 | WARN_ON_ONCE(cur_vblank != vblank->last); | ||
160 | return; | 230 | return; |
231 | } | ||
161 | 232 | ||
162 | /* | 233 | /* |
163 | * Only reinitialize corresponding vblank timestamp if high-precision query | 234 | * Only reinitialize corresponding vblank timestamp if high-precision query |
@@ -167,7 +238,7 @@ static void drm_update_vblank_count(struct drm_device *dev, unsigned int pipe) | |||
167 | if (!rc) | 238 | if (!rc) |
168 | t_vblank = (struct timeval) {0, 0}; | 239 | t_vblank = (struct timeval) {0, 0}; |
169 | 240 | ||
170 | store_vblank(dev, pipe, diff, &t_vblank); | 241 | store_vblank(dev, pipe, diff, &t_vblank, cur_vblank); |
171 | } | 242 | } |
172 | 243 | ||
173 | /* | 244 | /* |
@@ -180,11 +251,6 @@ static void vblank_disable_and_save(struct drm_device *dev, unsigned int pipe) | |||
180 | { | 251 | { |
181 | struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; | 252 | struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; |
182 | unsigned long irqflags; | 253 | unsigned long irqflags; |
183 | u32 vblcount; | ||
184 | s64 diff_ns; | ||
185 | bool vblrc; | ||
186 | struct timeval tvblank; | ||
187 | int count = DRM_TIMESTAMP_MAXRETRIES; | ||
188 | 254 | ||
189 | /* Prevent vblank irq processing while disabling vblank irqs, | 255 | /* Prevent vblank irq processing while disabling vblank irqs, |
190 | * so no updates of timestamps or count can happen after we've | 256 | * so no updates of timestamps or count can happen after we've |
@@ -193,26 +259,6 @@ static void vblank_disable_and_save(struct drm_device *dev, unsigned int pipe) | |||
193 | spin_lock_irqsave(&dev->vblank_time_lock, irqflags); | 259 | spin_lock_irqsave(&dev->vblank_time_lock, irqflags); |
194 | 260 | ||
195 | /* | 261 | /* |
196 | * If the vblank interrupt was already disabled update the count | ||
197 | * and timestamp to maintain the appearance that the counter | ||
198 | * has been ticking all along until this time. This makes the | ||
199 | * count account for the entire time between drm_vblank_on() and | ||
200 | * drm_vblank_off(). | ||
201 | * | ||
202 | * But only do this if precise vblank timestamps are available. | ||
203 | * Otherwise we might read a totally bogus timestamp since drivers | ||
204 | * lacking precise timestamp support rely upon sampling the system clock | ||
205 | * at vblank interrupt time. Which obviously won't work out well if the | ||
206 | * vblank interrupt is disabled. | ||
207 | */ | ||
208 | if (!vblank->enabled && | ||
209 | drm_get_last_vbltimestamp(dev, pipe, &tvblank, 0)) { | ||
210 | drm_update_vblank_count(dev, pipe); | ||
211 | spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags); | ||
212 | return; | ||
213 | } | ||
214 | |||
215 | /* | ||
216 | * Only disable vblank interrupts if they're enabled. This avoids | 262 | * Only disable vblank interrupts if they're enabled. This avoids |
217 | * calling the ->disable_vblank() operation in atomic context with the | 263 | * calling the ->disable_vblank() operation in atomic context with the |
218 | * hardware potentially runtime suspended. | 264 | * hardware potentially runtime suspended. |
@@ -222,47 +268,13 @@ static void vblank_disable_and_save(struct drm_device *dev, unsigned int pipe) | |||
222 | vblank->enabled = false; | 268 | vblank->enabled = false; |
223 | } | 269 | } |
224 | 270 | ||
225 | /* No further vblank irq's will be processed after | 271 | /* |
226 | * this point. Get current hardware vblank count and | 272 | * Always update the count and timestamp to maintain the |
227 | * vblank timestamp, repeat until they are consistent. | 273 | * appearance that the counter has been ticking all along until |
228 | * | 274 | * this time. This makes the count account for the entire time |
229 | * FIXME: There is still a race condition here and in | 275 | * between drm_vblank_on() and drm_vblank_off(). |
230 | * drm_update_vblank_count() which can cause off-by-one | ||
231 | * reinitialization of software vblank counter. If gpu | ||
232 | * vblank counter doesn't increment exactly at the leading | ||
233 | * edge of a vblank interval, then we can lose 1 count if | ||
234 | * we happen to execute between start of vblank and the | ||
235 | * delayed gpu counter increment. | ||
236 | */ | ||
237 | do { | ||
238 | vblank->last = dev->driver->get_vblank_counter(dev, pipe); | ||
239 | vblrc = drm_get_last_vbltimestamp(dev, pipe, &tvblank, 0); | ||
240 | } while (vblank->last != dev->driver->get_vblank_counter(dev, pipe) && (--count) && vblrc); | ||
241 | |||
242 | if (!count) | ||
243 | vblrc = 0; | ||
244 | |||
245 | /* Compute time difference to stored timestamp of last vblank | ||
246 | * as updated by last invocation of drm_handle_vblank() in vblank irq. | ||
247 | */ | ||
248 | vblcount = vblank->count; | ||
249 | diff_ns = timeval_to_ns(&tvblank) - | ||
250 | timeval_to_ns(&vblanktimestamp(dev, pipe, vblcount)); | ||
251 | |||
252 | /* If there is at least 1 msec difference between the last stored | ||
253 | * timestamp and tvblank, then we are currently executing our | ||
254 | * disable inside a new vblank interval, the tvblank timestamp | ||
255 | * corresponds to this new vblank interval and the irq handler | ||
256 | * for this vblank didn't run yet and won't run due to our disable. | ||
257 | * Therefore we need to do the job of drm_handle_vblank() and | ||
258 | * increment the vblank counter by one to account for this vblank. | ||
259 | * | ||
260 | * Skip this step if there isn't any high precision timestamp | ||
261 | * available. In that case we can't account for this and just | ||
262 | * hope for the best. | ||
263 | */ | 276 | */ |
264 | if (vblrc && (abs64(diff_ns) > 1000000)) | 277 | drm_update_vblank_count(dev, pipe, 0); |
265 | store_vblank(dev, pipe, 1, &tvblank); | ||
266 | 278 | ||
267 | spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags); | 279 | spin_unlock_irqrestore(&dev->vblank_time_lock, irqflags); |
268 | } | 280 | } |
@@ -603,7 +615,8 @@ int drm_control(struct drm_device *dev, void *data, | |||
603 | void drm_calc_timestamping_constants(struct drm_crtc *crtc, | 615 | void drm_calc_timestamping_constants(struct drm_crtc *crtc, |
604 | const struct drm_display_mode *mode) | 616 | const struct drm_display_mode *mode) |
605 | { | 617 | { |
606 | int linedur_ns = 0, pixeldur_ns = 0, framedur_ns = 0; | 618 | struct drm_vblank_crtc *vblank = &crtc->dev->vblank[drm_crtc_index(crtc)]; |
619 | int linedur_ns = 0, framedur_ns = 0; | ||
607 | int dotclock = mode->crtc_clock; | 620 | int dotclock = mode->crtc_clock; |
608 | 621 | ||
609 | /* Valid dotclock? */ | 622 | /* Valid dotclock? */ |
@@ -612,10 +625,9 @@ void drm_calc_timestamping_constants(struct drm_crtc *crtc, | |||
612 | 625 | ||
613 | /* | 626 | /* |
614 | * Convert scanline length in pixels and video | 627 | * Convert scanline length in pixels and video |
615 | * dot clock to line duration, frame duration | 628 | * dot clock to line duration and frame duration |
616 | * and pixel duration in nanoseconds: | 629 | * in nanoseconds: |
617 | */ | 630 | */ |
618 | pixeldur_ns = 1000000 / dotclock; | ||
619 | linedur_ns = div_u64((u64) mode->crtc_htotal * 1000000, dotclock); | 631 | linedur_ns = div_u64((u64) mode->crtc_htotal * 1000000, dotclock); |
620 | framedur_ns = div_u64((u64) frame_size * 1000000, dotclock); | 632 | framedur_ns = div_u64((u64) frame_size * 1000000, dotclock); |
621 | 633 | ||
@@ -628,16 +640,14 @@ void drm_calc_timestamping_constants(struct drm_crtc *crtc, | |||
628 | DRM_ERROR("crtc %u: Can't calculate constants, dotclock = 0!\n", | 640 | DRM_ERROR("crtc %u: Can't calculate constants, dotclock = 0!\n", |
629 | crtc->base.id); | 641 | crtc->base.id); |
630 | 642 | ||
631 | crtc->pixeldur_ns = pixeldur_ns; | 643 | vblank->linedur_ns = linedur_ns; |
632 | crtc->linedur_ns = linedur_ns; | 644 | vblank->framedur_ns = framedur_ns; |
633 | crtc->framedur_ns = framedur_ns; | ||
634 | 645 | ||
635 | DRM_DEBUG("crtc %u: hwmode: htotal %d, vtotal %d, vdisplay %d\n", | 646 | DRM_DEBUG("crtc %u: hwmode: htotal %d, vtotal %d, vdisplay %d\n", |
636 | crtc->base.id, mode->crtc_htotal, | 647 | crtc->base.id, mode->crtc_htotal, |
637 | mode->crtc_vtotal, mode->crtc_vdisplay); | 648 | mode->crtc_vtotal, mode->crtc_vdisplay); |
638 | DRM_DEBUG("crtc %u: clock %d kHz framedur %d linedur %d, pixeldur %d\n", | 649 | DRM_DEBUG("crtc %u: clock %d kHz framedur %d linedur %d\n", |
639 | crtc->base.id, dotclock, framedur_ns, | 650 | crtc->base.id, dotclock, framedur_ns, linedur_ns); |
640 | linedur_ns, pixeldur_ns); | ||
641 | } | 651 | } |
642 | EXPORT_SYMBOL(drm_calc_timestamping_constants); | 652 | EXPORT_SYMBOL(drm_calc_timestamping_constants); |
643 | 653 | ||
@@ -651,7 +661,6 @@ EXPORT_SYMBOL(drm_calc_timestamping_constants); | |||
651 | * @flags: Flags to pass to driver: | 661 | * @flags: Flags to pass to driver: |
652 | * 0 = Default, | 662 | * 0 = Default, |
653 | * DRM_CALLED_FROM_VBLIRQ = If function is called from vbl IRQ handler | 663 | * DRM_CALLED_FROM_VBLIRQ = If function is called from vbl IRQ handler |
654 | * @refcrtc: CRTC which defines scanout timing | ||
655 | * @mode: mode which defines the scanout timings | 664 | * @mode: mode which defines the scanout timings |
656 | * | 665 | * |
657 | * Implements calculation of exact vblank timestamps from given drm_display_mode | 666 | * Implements calculation of exact vblank timestamps from given drm_display_mode |
@@ -692,15 +701,14 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, | |||
692 | int *max_error, | 701 | int *max_error, |
693 | struct timeval *vblank_time, | 702 | struct timeval *vblank_time, |
694 | unsigned flags, | 703 | unsigned flags, |
695 | const struct drm_crtc *refcrtc, | ||
696 | const struct drm_display_mode *mode) | 704 | const struct drm_display_mode *mode) |
697 | { | 705 | { |
698 | struct timeval tv_etime; | 706 | struct timeval tv_etime; |
699 | ktime_t stime, etime; | 707 | ktime_t stime, etime; |
700 | int vbl_status; | 708 | unsigned int vbl_status; |
709 | int ret = DRM_VBLANKTIME_SCANOUTPOS_METHOD; | ||
701 | int vpos, hpos, i; | 710 | int vpos, hpos, i; |
702 | int framedur_ns, linedur_ns, pixeldur_ns, delta_ns, duration_ns; | 711 | int delta_ns, duration_ns; |
703 | bool invbl; | ||
704 | 712 | ||
705 | if (pipe >= dev->num_crtcs) { | 713 | if (pipe >= dev->num_crtcs) { |
706 | DRM_ERROR("Invalid crtc %u\n", pipe); | 714 | DRM_ERROR("Invalid crtc %u\n", pipe); |
@@ -713,15 +721,10 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, | |||
713 | return -EIO; | 721 | return -EIO; |
714 | } | 722 | } |
715 | 723 | ||
716 | /* Durations of frames, lines, pixels in nanoseconds. */ | ||
717 | framedur_ns = refcrtc->framedur_ns; | ||
718 | linedur_ns = refcrtc->linedur_ns; | ||
719 | pixeldur_ns = refcrtc->pixeldur_ns; | ||
720 | |||
721 | /* If mode timing undefined, just return as no-op: | 724 | /* If mode timing undefined, just return as no-op: |
722 | * Happens during initial modesetting of a crtc. | 725 | * Happens during initial modesetting of a crtc. |
723 | */ | 726 | */ |
724 | if (framedur_ns == 0) { | 727 | if (mode->crtc_clock == 0) { |
725 | DRM_DEBUG("crtc %u: Noop due to uninitialized mode.\n", pipe); | 728 | DRM_DEBUG("crtc %u: Noop due to uninitialized mode.\n", pipe); |
726 | return -EAGAIN; | 729 | return -EAGAIN; |
727 | } | 730 | } |
@@ -738,12 +741,14 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, | |||
738 | * Get vertical and horizontal scanout position vpos, hpos, | 741 | * Get vertical and horizontal scanout position vpos, hpos, |
739 | * and bounding timestamps stime, etime, pre/post query. | 742 | * and bounding timestamps stime, etime, pre/post query. |
740 | */ | 743 | */ |
741 | vbl_status = dev->driver->get_scanout_position(dev, pipe, flags, &vpos, | 744 | vbl_status = dev->driver->get_scanout_position(dev, pipe, flags, |
742 | &hpos, &stime, &etime); | 745 | &vpos, &hpos, |
746 | &stime, &etime, | ||
747 | mode); | ||
743 | 748 | ||
744 | /* Return as no-op if scanout query unsupported or failed. */ | 749 | /* Return as no-op if scanout query unsupported or failed. */ |
745 | if (!(vbl_status & DRM_SCANOUTPOS_VALID)) { | 750 | if (!(vbl_status & DRM_SCANOUTPOS_VALID)) { |
746 | DRM_DEBUG("crtc %u : scanoutpos query failed [%d].\n", | 751 | DRM_DEBUG("crtc %u : scanoutpos query failed [0x%x].\n", |
747 | pipe, vbl_status); | 752 | pipe, vbl_status); |
748 | return -EIO; | 753 | return -EIO; |
749 | } | 754 | } |
@@ -770,13 +775,15 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, | |||
770 | * within vblank area, counting down the number of lines until | 775 | * within vblank area, counting down the number of lines until |
771 | * start of scanout. | 776 | * start of scanout. |
772 | */ | 777 | */ |
773 | invbl = vbl_status & DRM_SCANOUTPOS_IN_VBLANK; | 778 | if (vbl_status & DRM_SCANOUTPOS_IN_VBLANK) |
779 | ret |= DRM_VBLANKTIME_IN_VBLANK; | ||
774 | 780 | ||
775 | /* Convert scanout position into elapsed time at raw_time query | 781 | /* Convert scanout position into elapsed time at raw_time query |
776 | * since start of scanout at first display scanline. delta_ns | 782 | * since start of scanout at first display scanline. delta_ns |
777 | * can be negative if start of scanout hasn't happened yet. | 783 | * can be negative if start of scanout hasn't happened yet. |
778 | */ | 784 | */ |
779 | delta_ns = vpos * linedur_ns + hpos * pixeldur_ns; | 785 | delta_ns = div_s64(1000000LL * (vpos * mode->crtc_htotal + hpos), |
786 | mode->crtc_clock); | ||
780 | 787 | ||
781 | if (!drm_timestamp_monotonic) | 788 | if (!drm_timestamp_monotonic) |
782 | etime = ktime_mono_to_real(etime); | 789 | etime = ktime_mono_to_real(etime); |
@@ -792,17 +799,13 @@ int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, | |||
792 | etime = ktime_sub_ns(etime, delta_ns); | 799 | etime = ktime_sub_ns(etime, delta_ns); |
793 | *vblank_time = ktime_to_timeval(etime); | 800 | *vblank_time = ktime_to_timeval(etime); |
794 | 801 | ||
795 | DRM_DEBUG("crtc %u : v %d p(%d,%d)@ %ld.%ld -> %ld.%ld [e %d us, %d rep]\n", | 802 | DRM_DEBUG("crtc %u : v 0x%x p(%d,%d)@ %ld.%ld -> %ld.%ld [e %d us, %d rep]\n", |
796 | pipe, (int)vbl_status, hpos, vpos, | 803 | pipe, vbl_status, hpos, vpos, |
797 | (long)tv_etime.tv_sec, (long)tv_etime.tv_usec, | 804 | (long)tv_etime.tv_sec, (long)tv_etime.tv_usec, |
798 | (long)vblank_time->tv_sec, (long)vblank_time->tv_usec, | 805 | (long)vblank_time->tv_sec, (long)vblank_time->tv_usec, |
799 | duration_ns/1000, i); | 806 | duration_ns/1000, i); |
800 | 807 | ||
801 | vbl_status = DRM_VBLANKTIME_SCANOUTPOS_METHOD; | 808 | return ret; |
802 | if (invbl) | ||
803 | vbl_status |= DRM_VBLANKTIME_IN_VBLANK; | ||
804 | |||
805 | return vbl_status; | ||
806 | } | 809 | } |
807 | EXPORT_SYMBOL(drm_calc_vbltimestamp_from_scanoutpos); | 810 | EXPORT_SYMBOL(drm_calc_vbltimestamp_from_scanoutpos); |
808 | 811 | ||
@@ -914,11 +917,14 @@ EXPORT_SYMBOL(drm_crtc_vblank_count); | |||
914 | * vblank events since the system was booted, including lost events due to | 917 | * vblank events since the system was booted, including lost events due to |
915 | * modesetting activity. Returns corresponding system timestamp of the time | 918 | * modesetting activity. Returns corresponding system timestamp of the time |
916 | * of the vblank interval that corresponds to the current vblank counter value. | 919 | * of the vblank interval that corresponds to the current vblank counter value. |
920 | * | ||
921 | * This is the legacy version of drm_crtc_vblank_count_and_time(). | ||
917 | */ | 922 | */ |
918 | u32 drm_vblank_count_and_time(struct drm_device *dev, unsigned int pipe, | 923 | u32 drm_vblank_count_and_time(struct drm_device *dev, unsigned int pipe, |
919 | struct timeval *vblanktime) | 924 | struct timeval *vblanktime) |
920 | { | 925 | { |
921 | struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; | 926 | struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; |
927 | int count = DRM_TIMESTAMP_MAXRETRIES; | ||
922 | u32 cur_vblank; | 928 | u32 cur_vblank; |
923 | 929 | ||
924 | if (WARN_ON(pipe >= dev->num_crtcs)) | 930 | if (WARN_ON(pipe >= dev->num_crtcs)) |
@@ -934,12 +940,33 @@ u32 drm_vblank_count_and_time(struct drm_device *dev, unsigned int pipe, | |||
934 | smp_rmb(); | 940 | smp_rmb(); |
935 | *vblanktime = vblanktimestamp(dev, pipe, cur_vblank); | 941 | *vblanktime = vblanktimestamp(dev, pipe, cur_vblank); |
936 | smp_rmb(); | 942 | smp_rmb(); |
937 | } while (cur_vblank != vblank->count); | 943 | } while (cur_vblank != vblank->count && --count > 0); |
938 | 944 | ||
939 | return cur_vblank; | 945 | return cur_vblank; |
940 | } | 946 | } |
941 | EXPORT_SYMBOL(drm_vblank_count_and_time); | 947 | EXPORT_SYMBOL(drm_vblank_count_and_time); |
942 | 948 | ||
949 | /** | ||
950 | * drm_crtc_vblank_count_and_time - retrieve "cooked" vblank counter value | ||
951 | * and the system timestamp corresponding to that vblank counter value | ||
952 | * @crtc: which counter to retrieve | ||
953 | * @vblanktime: Pointer to struct timeval to receive the vblank timestamp. | ||
954 | * | ||
955 | * Fetches the "cooked" vblank count value that represents the number of | ||
956 | * vblank events since the system was booted, including lost events due to | ||
957 | * modesetting activity. Returns corresponding system timestamp of the time | ||
958 | * of the vblank interval that corresponds to the current vblank counter value. | ||
959 | * | ||
960 | * This is the native KMS version of drm_vblank_count_and_time(). | ||
961 | */ | ||
962 | u32 drm_crtc_vblank_count_and_time(struct drm_crtc *crtc, | ||
963 | struct timeval *vblanktime) | ||
964 | { | ||
965 | return drm_vblank_count_and_time(crtc->dev, drm_crtc_index(crtc), | ||
966 | vblanktime); | ||
967 | } | ||
968 | EXPORT_SYMBOL(drm_crtc_vblank_count_and_time); | ||
969 | |||
943 | static void send_vblank_event(struct drm_device *dev, | 970 | static void send_vblank_event(struct drm_device *dev, |
944 | struct drm_pending_vblank_event *e, | 971 | struct drm_pending_vblank_event *e, |
945 | unsigned long seq, struct timeval *now) | 972 | unsigned long seq, struct timeval *now) |
@@ -1033,7 +1060,7 @@ static int drm_vblank_enable(struct drm_device *dev, unsigned int pipe) | |||
1033 | atomic_dec(&vblank->refcount); | 1060 | atomic_dec(&vblank->refcount); |
1034 | else { | 1061 | else { |
1035 | vblank->enabled = true; | 1062 | vblank->enabled = true; |
1036 | drm_update_vblank_count(dev, pipe); | 1063 | drm_update_vblank_count(dev, pipe, 0); |
1037 | } | 1064 | } |
1038 | } | 1065 | } |
1039 | 1066 | ||
@@ -1154,8 +1181,8 @@ EXPORT_SYMBOL(drm_crtc_vblank_put); | |||
1154 | * @dev: DRM device | 1181 | * @dev: DRM device |
1155 | * @pipe: CRTC index | 1182 | * @pipe: CRTC index |
1156 | * | 1183 | * |
1157 | * This waits for one vblank to pass on @crtc, using the irq driver interfaces. | 1184 | * This waits for one vblank to pass on @pipe, using the irq driver interfaces. |
1158 | * It is a failure to call this when the vblank irq for @crtc is disabled, e.g. | 1185 | * It is a failure to call this when the vblank irq for @pipe is disabled, e.g. |
1159 | * due to lack of driver support or because the crtc is off. | 1186 | * due to lack of driver support or because the crtc is off. |
1160 | */ | 1187 | */ |
1161 | void drm_wait_one_vblank(struct drm_device *dev, unsigned int pipe) | 1188 | void drm_wait_one_vblank(struct drm_device *dev, unsigned int pipe) |
@@ -1276,7 +1303,7 @@ EXPORT_SYMBOL(drm_crtc_vblank_off); | |||
1276 | 1303 | ||
1277 | /** | 1304 | /** |
1278 | * drm_crtc_vblank_reset - reset vblank state to off on a CRTC | 1305 | * drm_crtc_vblank_reset - reset vblank state to off on a CRTC |
1279 | * @drm_crtc: CRTC in question | 1306 | * @crtc: CRTC in question |
1280 | * | 1307 | * |
1281 | * Drivers can use this function to reset the vblank state to off at load time. | 1308 | * Drivers can use this function to reset the vblank state to off at load time. |
1282 | * Drivers should use this together with the drm_crtc_vblank_off() and | 1309 | * Drivers should use this together with the drm_crtc_vblank_off() and |
@@ -1284,12 +1311,12 @@ EXPORT_SYMBOL(drm_crtc_vblank_off); | |||
1284 | * drm_crtc_vblank_off() is that this function doesn't save the vblank counter | 1311 | * drm_crtc_vblank_off() is that this function doesn't save the vblank counter |
1285 | * and hence doesn't need to call any driver hooks. | 1312 | * and hence doesn't need to call any driver hooks. |
1286 | */ | 1313 | */ |
1287 | void drm_crtc_vblank_reset(struct drm_crtc *drm_crtc) | 1314 | void drm_crtc_vblank_reset(struct drm_crtc *crtc) |
1288 | { | 1315 | { |
1289 | struct drm_device *dev = drm_crtc->dev; | 1316 | struct drm_device *dev = crtc->dev; |
1290 | unsigned long irqflags; | 1317 | unsigned long irqflags; |
1291 | int crtc = drm_crtc_index(drm_crtc); | 1318 | unsigned int pipe = drm_crtc_index(crtc); |
1292 | struct drm_vblank_crtc *vblank = &dev->vblank[crtc]; | 1319 | struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; |
1293 | 1320 | ||
1294 | spin_lock_irqsave(&dev->vbl_lock, irqflags); | 1321 | spin_lock_irqsave(&dev->vbl_lock, irqflags); |
1295 | /* | 1322 | /* |
@@ -1333,16 +1360,8 @@ void drm_vblank_on(struct drm_device *dev, unsigned int pipe) | |||
1333 | vblank->inmodeset = 0; | 1360 | vblank->inmodeset = 0; |
1334 | } | 1361 | } |
1335 | 1362 | ||
1336 | /* | 1363 | drm_reset_vblank_timestamp(dev, pipe); |
1337 | * sample the current counter to avoid random jumps | 1364 | |
1338 | * when drm_vblank_enable() applies the diff | ||
1339 | * | ||
1340 | * -1 to make sure user will never see the same | ||
1341 | * vblank counter value before and after a modeset | ||
1342 | */ | ||
1343 | vblank->last = | ||
1344 | (dev->driver->get_vblank_counter(dev, pipe) - 1) & | ||
1345 | dev->max_vblank_count; | ||
1346 | /* | 1365 | /* |
1347 | * re-enable interrupts if there are users left, or the | 1366 | * re-enable interrupts if there are users left, or the |
1348 | * user wishes vblank interrupts to be enabled all the time. | 1367 | * user wishes vblank interrupts to be enabled all the time. |
@@ -1725,9 +1744,6 @@ static void drm_handle_vblank_events(struct drm_device *dev, unsigned int pipe) | |||
1725 | bool drm_handle_vblank(struct drm_device *dev, unsigned int pipe) | 1744 | bool drm_handle_vblank(struct drm_device *dev, unsigned int pipe) |
1726 | { | 1745 | { |
1727 | struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; | 1746 | struct drm_vblank_crtc *vblank = &dev->vblank[pipe]; |
1728 | u32 vblcount; | ||
1729 | s64 diff_ns; | ||
1730 | struct timeval tvblank; | ||
1731 | unsigned long irqflags; | 1747 | unsigned long irqflags; |
1732 | 1748 | ||
1733 | if (WARN_ON_ONCE(!dev->num_crtcs)) | 1749 | if (WARN_ON_ONCE(!dev->num_crtcs)) |
@@ -1751,32 +1767,7 @@ bool drm_handle_vblank(struct drm_device *dev, unsigned int pipe) | |||
1751 | return false; | 1767 | return false; |
1752 | } | 1768 | } |
1753 | 1769 | ||
1754 | /* Fetch corresponding timestamp for this vblank interval from | 1770 | drm_update_vblank_count(dev, pipe, DRM_CALLED_FROM_VBLIRQ); |
1755 | * driver and store it in proper slot of timestamp ringbuffer. | ||
1756 | */ | ||
1757 | |||
1758 | /* Get current timestamp and count. */ | ||
1759 | vblcount = vblank->count; | ||
1760 | drm_get_last_vbltimestamp(dev, pipe, &tvblank, DRM_CALLED_FROM_VBLIRQ); | ||
1761 | |||
1762 | /* Compute time difference to timestamp of last vblank */ | ||
1763 | diff_ns = timeval_to_ns(&tvblank) - | ||
1764 | timeval_to_ns(&vblanktimestamp(dev, pipe, vblcount)); | ||
1765 | |||
1766 | /* Update vblank timestamp and count if at least | ||
1767 | * DRM_REDUNDANT_VBLIRQ_THRESH_NS nanoseconds | ||
1768 | * difference between last stored timestamp and current | ||
1769 | * timestamp. A smaller difference means basically | ||
1770 | * identical timestamps. Happens if this vblank has | ||
1771 | * been already processed and this is a redundant call, | ||
1772 | * e.g., due to spurious vblank interrupts. We need to | ||
1773 | * ignore those for accounting. | ||
1774 | */ | ||
1775 | if (abs64(diff_ns) > DRM_REDUNDANT_VBLIRQ_THRESH_NS) | ||
1776 | store_vblank(dev, pipe, 1, &tvblank); | ||
1777 | else | ||
1778 | DRM_DEBUG("crtc %u: Redundant vblirq ignored. diff_ns = %d\n", | ||
1779 | pipe, (int) diff_ns); | ||
1780 | 1771 | ||
1781 | spin_unlock(&dev->vblank_time_lock); | 1772 | spin_unlock(&dev->vblank_time_lock); |
1782 | 1773 | ||