Rev 4539 | Rev 5060 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 4539 | Rev 4560 | ||
---|---|---|---|
Line 42... | Line 42... | ||
42 | 42 | ||
43 | //#include |
43 | //#include |
Line 44... | Line 44... | ||
44 | #include |
44 | #include |
45 | 45 | ||
46 | /* Access macro for slots in vblank timestamp ringbuffer. */ |
46 | /* Access macro for slots in vblank timestamp ringbuffer. */ |
47 | #define vblanktimestamp(dev, crtc, count) ( \ |
- | |
Line 48... | Line 47... | ||
48 | (dev)->_vblank_time[(crtc) * DRM_VBLANKTIME_RBSIZE + \ |
47 | #define vblanktimestamp(dev, crtc, count) \ |
49 | ((count) % DRM_VBLANKTIME_RBSIZE)]) |
48 | ((dev)->vblank[crtc].time[(count) % DRM_VBLANKTIME_RBSIZE]) |
50 | 49 | ||
51 | /* Retry timestamp calculation up to 3 times to satisfy |
50 | /* Retry timestamp calculation up to 3 times to satisfy |
Line 100... | Line 99... | ||
100 | 99 | ||
101 | if (dev->irq_enabled) { |
100 | if (dev->irq_enabled) { |
102 | mutex_unlock(&dev->struct_mutex); |
101 | mutex_unlock(&dev->struct_mutex); |
103 | return -EBUSY; |
102 | return -EBUSY; |
104 | } |
103 | } |
105 | dev->irq_enabled = 1; |
104 | dev->irq_enabled = true; |
Line 106... | Line 105... | ||
106 | mutex_unlock(&dev->struct_mutex); |
105 | mutex_unlock(&dev->struct_mutex); |
Line 107... | Line 106... | ||
107 | 106 | ||
Line 148... | Line 147... | ||
148 | 147 | ||
149 | return div_u64(dividend, d); |
148 | return div_u64(dividend, d); |
Line 150... | Line 149... | ||
150 | } |
149 | } |
151 | 150 | ||
152 | /** |
- | |
153 | * drm_calc_timestamping_constants - Calculate and |
- | |
154 | * store various constants which are later needed by |
- | |
155 | * vblank and swap-completion timestamping, e.g, by |
- | |
156 | * drm_calc_vbltimestamp_from_scanoutpos(). |
- | |
157 | * They are derived from crtc's true scanout timing, |
- | |
158 | * so they take things like panel scaling or other |
151 | /** |
159 | * adjustments into account. |
152 | * drm_calc_timestamping_constants - Calculate vblank timestamp constants |
- | 153 | * |
|
160 | * |
154 | * @crtc drm_crtc whose timestamp constants should be updated. |
- | 155 | * @mode display mode containing the scanout timings |
|
- | 156 | * |
|
- | 157 | * Calculate and store various constants which are later |
|
- | 158 | * needed by vblank and swap-completion timestamping, e.g, |
|
- | 159 | * by drm_calc_vbltimestamp_from_scanoutpos(). They are |
|
161 | * @crtc drm_crtc whose timestamp constants should be updated. |
160 | * derived from crtc's true scanout timing, so they take |
162 | * |
161 | * things like panel scaling or other adjustments into account. |
- | 162 | */ |
|
163 | */ |
163 | void drm_calc_timestamping_constants(struct drm_crtc *crtc, |
164 | void drm_calc_timestamping_constants(struct drm_crtc *crtc) |
164 | const struct drm_display_mode *mode) |
165 | { |
165 | { |
Line -... | Line 166... | ||
- | 166 | int linedur_ns = 0, pixeldur_ns = 0, framedur_ns = 0; |
|
166 | s64 linedur_ns = 0, pixeldur_ns = 0, framedur_ns = 0; |
167 | int dotclock = mode->crtc_clock; |
167 | u64 dotclock; |
168 | |
Line -... | Line 169... | ||
- | 169 | /* Valid dotclock? */ |
|
168 | 170 | if (dotclock > 0) { |
|
169 | /* Dot clock in Hz: */ |
171 | int frame_size = mode->crtc_htotal * mode->crtc_vtotal; |
- | 172 | ||
170 | dotclock = (u64) crtc->hwmode.clock * 1000; |
173 | /* |
171 | 174 | * Convert scanline length in pixels and video |
|
172 | /* Fields of interlaced scanout modes are only halve a frame duration. |
175 | * dot clock to line duration, frame duration |
- | 176 | * and pixel duration in nanoseconds: |
|
Line 173... | Line -... | ||
173 | * Double the dotclock to get halve the frame-/line-/pixelduration. |
- | |
174 | */ |
- | |
175 | if (crtc->hwmode.flags & DRM_MODE_FLAG_INTERLACE) |
177 | */ |
176 | dotclock *= 2; |
- | |
177 | 178 | pixeldur_ns = 1000000 / dotclock; |
|
178 | /* Valid dotclock? */ |
- | |
179 | if (dotclock > 0) { |
179 | linedur_ns = div_u64((u64) mode->crtc_htotal * 1000000, dotclock); |
180 | int frame_size; |
- | |
181 | /* Convert scanline length in pixels and video dot clock to |
- | |
182 | * line duration, frame duration and pixel duration in |
- | |
183 | * nanoseconds: |
180 | framedur_ns = div_u64((u64) frame_size * 1000000, dotclock); |
184 | */ |
- | |
185 | pixeldur_ns = (s64) div64_u64(1000000000, dotclock); |
- | |
186 | linedur_ns = (s64) div64_u64(((u64) crtc->hwmode.crtc_htotal * |
181 | |
187 | 1000000000), dotclock); |
182 | /* |
188 | frame_size = crtc->hwmode.crtc_htotal * |
183 | * Fields of interlaced scanout modes are only half a frame duration. |
189 | crtc->hwmode.crtc_vtotal; |
184 | */ |
Line 190... | Line 185... | ||
190 | framedur_ns = (s64) div64_u64((u64) frame_size * 1000000000, |
185 | if (mode->flags & DRM_MODE_FLAG_INTERLACE) |
191 | dotclock); |
186 | framedur_ns /= 2; |
192 | } else |
187 | } else |
Line 193... | Line 188... | ||
193 | DRM_ERROR("crtc %d: Can't calculate constants, dotclock = 0!\n", |
188 | DRM_ERROR("crtc %d: Can't calculate constants, dotclock = 0!\n", |
194 | crtc->base.id); |
189 | crtc->base.id); |
195 | 190 | ||
196 | crtc->pixeldur_ns = pixeldur_ns; |
191 | crtc->pixeldur_ns = pixeldur_ns; |
197 | crtc->linedur_ns = linedur_ns; |
192 | crtc->linedur_ns = linedur_ns; |
198 | crtc->framedur_ns = framedur_ns; |
193 | crtc->framedur_ns = framedur_ns; |
199 | 194 | ||
200 | DRM_DEBUG("crtc %d: hwmode: htotal %d, vtotal %d, vdisplay %d\n", |
195 | DRM_DEBUG("crtc %d: hwmode: htotal %d, vtotal %d, vdisplay %d\n", |
Line 201... | Line 196... | ||
201 | crtc->base.id, crtc->hwmode.crtc_htotal, |
196 | crtc->base.id, mode->crtc_htotal, |
202 | crtc->hwmode.crtc_vtotal, crtc->hwmode.crtc_vdisplay); |
197 | mode->crtc_vtotal, mode->crtc_vdisplay); |
Line 233... | Line 228... | ||
233 | * @vblank_time: Pointer to struct timeval which should receive the timestamp. |
228 | * @vblank_time: Pointer to struct timeval which should receive the timestamp. |
234 | * @flags: Flags to pass to driver: |
229 | * @flags: Flags to pass to driver: |
235 | * 0 = Default. |
230 | * 0 = Default. |
236 | * DRM_CALLED_FROM_VBLIRQ = If function is called from vbl irq handler. |
231 | * DRM_CALLED_FROM_VBLIRQ = If function is called from vbl irq handler. |
237 | * @refcrtc: drm_crtc* of crtc which defines scanout timing. |
232 | * @refcrtc: drm_crtc* of crtc which defines scanout timing. |
- | 233 | * @mode: mode which defines the scanout timings |
|
238 | * |
234 | * |
239 | * Returns negative value on error, failure or if not supported in current |
235 | * Returns negative value on error, failure or if not supported in current |
240 | * video mode: |
236 | * video mode: |
241 | * |
237 | * |
242 | * -EINVAL - Invalid crtc. |
238 | * -EINVAL - Invalid crtc. |
Line 252... | Line 248... | ||
252 | */ |
248 | */ |
253 | int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc, |
249 | int drm_calc_vbltimestamp_from_scanoutpos(struct drm_device *dev, int crtc, |
254 | int *max_error, |
250 | int *max_error, |
255 | struct timeval *vblank_time, |
251 | struct timeval *vblank_time, |
256 | unsigned flags, |
252 | unsigned flags, |
257 | struct drm_crtc *refcrtc) |
253 | const struct drm_crtc *refcrtc, |
- | 254 | const struct drm_display_mode *mode) |
|
258 | { |
255 | { |
259 | // ktime_t stime, etime, mono_time_offset; |
- | |
260 | struct timeval tv_etime; |
256 | struct timeval tv_etime; |
261 | struct drm_display_mode *mode; |
- | |
262 | int vbl_status, vtotal, vdisplay; |
257 | int vbl_status; |
263 | int vpos, hpos, i; |
258 | int vpos, hpos, i; |
264 | s64 framedur_ns, linedur_ns, pixeldur_ns, delta_ns, duration_ns; |
259 | int framedur_ns, linedur_ns, pixeldur_ns, delta_ns, duration_ns; |
265 | bool invbl; |
260 | bool invbl; |
Line 266... | Line 261... | ||
266 | 261 | ||
267 | if (crtc < 0 || crtc >= dev->num_crtcs) { |
262 | if (crtc < 0 || crtc >= dev->num_crtcs) { |
268 | DRM_ERROR("Invalid crtc %d\n", crtc); |
263 | DRM_ERROR("Invalid crtc %d\n", crtc); |
Line 273... | Line 268... | ||
273 | if (!dev->driver->get_scanout_position) { |
268 | if (!dev->driver->get_scanout_position) { |
274 | DRM_ERROR("Called from driver w/o get_scanout_position()!?\n"); |
269 | DRM_ERROR("Called from driver w/o get_scanout_position()!?\n"); |
275 | return -EIO; |
270 | return -EIO; |
276 | } |
271 | } |
Line 277... | Line -... | ||
277 | - | ||
278 | mode = &refcrtc->hwmode; |
- | |
279 | vtotal = mode->crtc_vtotal; |
- | |
280 | vdisplay = mode->crtc_vdisplay; |
- | |
281 | 272 | ||
282 | /* Durations of frames, lines, pixels in nanoseconds. */ |
273 | /* Durations of frames, lines, pixels in nanoseconds. */ |
283 | framedur_ns = refcrtc->framedur_ns; |
274 | framedur_ns = refcrtc->framedur_ns; |
284 | linedur_ns = refcrtc->linedur_ns; |
275 | linedur_ns = refcrtc->linedur_ns; |
Line 285... | Line 276... | ||
285 | pixeldur_ns = refcrtc->pixeldur_ns; |
276 | pixeldur_ns = refcrtc->pixeldur_ns; |
286 | 277 | ||
287 | /* If mode timing undefined, just return as no-op: |
278 | /* If mode timing undefined, just return as no-op: |
288 | * Happens during initial modesetting of a crtc. |
279 | * Happens during initial modesetting of a crtc. |
289 | */ |
280 | */ |
290 | if (vtotal <= 0 || vdisplay <= 0 || framedur_ns == 0) { |
281 | if (framedur_ns == 0) { |
291 | DRM_DEBUG("crtc %d: Noop due to uninitialized mode.\n", crtc); |
282 | DRM_DEBUG("crtc %d: Noop due to uninitialized mode.\n", crtc); |
Line 292... | Line 283... | ||
292 | return -EAGAIN; |
283 | return -EAGAIN; |
Line 316... | Line 307... | ||
316 | * were enabled/disabled around or between these calls, we just |
307 | * were enabled/disabled around or between these calls, we just |
317 | * have the kernel take a reference on the CRTC (just once though |
308 | * have the kernel take a reference on the CRTC (just once though |
318 | * to avoid corrupting the count if multiple, mismatch calls occur), |
309 | * to avoid corrupting the count if multiple, mismatch calls occur), |
319 | * so that interrupts remain enabled in the interim. |
310 | * so that interrupts remain enabled in the interim. |
320 | */ |
311 | */ |
321 | if (!dev->vblank_inmodeset[crtc]) { |
312 | if (!dev->vblank[crtc].inmodeset) { |
322 | dev->vblank_inmodeset[crtc] = 0x1; |
313 | dev->vblank[crtc].inmodeset = 0x1; |
323 | if (drm_vblank_get(dev, crtc) == 0) |
314 | if (drm_vblank_get(dev, crtc) == 0) |
324 | dev->vblank_inmodeset[crtc] |= 0x2; |
315 | dev->vblank[crtc].inmodeset |= 0x2; |
325 | } |
316 | } |
326 | #endif |
317 | #endif |
327 | } |
318 | } |
328 | EXPORT_SYMBOL(drm_vblank_pre_modeset); |
319 | EXPORT_SYMBOL(drm_vblank_pre_modeset); |
Line 334... | Line 325... | ||
334 | 325 | ||
335 | /* vblank is not initialized (IRQ not installed ?), or has been freed */ |
326 | /* vblank is not initialized (IRQ not installed ?), or has been freed */ |
336 | if (!dev->num_crtcs) |
327 | if (!dev->num_crtcs) |
Line 337... | Line 328... | ||
337 | return; |
328 | return; |
338 | 329 | ||
339 | if (dev->vblank_inmodeset[crtc]) { |
330 | if (dev->vblank[crtc].inmodeset) { |
340 | spin_lock_irqsave(&dev->vbl_lock, irqflags); |
331 | spin_lock_irqsave(&dev->vbl_lock, irqflags); |
Line 341... | Line 332... | ||
341 | dev->vblank_disable_allowed = 1; |
332 | dev->vblank_disable_allowed = true; |
342 | spin_unlock_irqrestore(&dev->vbl_lock, irqflags); |
333 | spin_unlock_irqrestore(&dev->vbl_lock, irqflags); |
Line 343... | Line 334... | ||
343 | 334 | ||
344 | if (dev->vblank_inmodeset[crtc] & 0x2) |
335 | if (dev->vblank[crtc].inmodeset & 0x2) |
345 | drm_vblank_put(dev, crtc); |
336 | drm_vblank_put(dev, crtc); |
346 | 337 | ||
347 | dev->vblank_inmodeset[crtc] = 0; |
338 | dev->vblank[crtc].inmodeset = 0; |