Lines Matching +full:interrupt +full:- +full:counter

1 // SPDX-License-Identifier: MIT
3 * Copyright © 2022-2023 Intel Corporation
29 * increment frame counter (ctg+)
30 * generate start of vblank interrupt (gen4+)
33 * | generate frame start interrupt (aka. vblank interrupt) (gmch)
34 * | may be shifted forward 1-3 extra lines via TRANSCONF
37 * | | generate vsync interrupt
41 * ----va---> <-----------------vb--------------------> <--------va-------------
42 * | | <----vs-----> |
43 …* -vbs-----> <---vbs+1---> <---vbs+2---> <-----0-----> <-----1-----> <-----2--- (scanline counter
44 …* -vbs-2---> <---vbs-1---> <---vbs-----> <---vbs+1---> <---vbs+2---> <-----0--- (scanline counter
45 …* -vbs-2---> <---vbs-2---> <---vbs-1---> <---vbs-----> <---vbs+1---> <---vbs+2- (scanline counter
48 * | increment frame counter (gen3/4)
49 * pixel counter = vblank_start * htotal pixel counter = 0 (gen3/4)
60 * - most events happen at the start of horizontal sync
61 * - frame start happens at the start of horizontal blank, 1-4 lines
63 * - gen3/4 pixel and frame counter are synchronized with the start
72 struct intel_display *display = to_intel_display(crtc->dev); in i915_get_vblank_counter()
74 const struct drm_display_mode *mode = &vblank->hwmode; in i915_get_vblank_counter()
75 enum pipe pipe = to_intel_crtc(crtc)->pipe; in i915_get_vblank_counter()
80 * On i965gm TV output the frame counter only works up to in i915_get_vblank_counter()
82 * frame counter ceases to work and reads zero. We need a in i915_get_vblank_counter()
84 * have to enable vblank interrupts while the frame counter in i915_get_vblank_counter()
86 * does not like us returning non-zero frame counter values in i915_get_vblank_counter()
88 * counter. Thus we must stop non-zero values leaking out. in i915_get_vblank_counter()
90 if (!vblank->max_vblank_count) in i915_get_vblank_counter()
93 htotal = mode->crtc_htotal; in i915_get_vblank_counter()
94 hsync_start = mode->crtc_hsync_start; in i915_get_vblank_counter()
101 vbl_start -= htotal - hsync_start; in i915_get_vblank_counter()
115 * The frame counter increments at beginning of active. in i915_get_vblank_counter()
116 * Cook up a vblank counter by also checking the pixel in i915_get_vblank_counter()
117 * counter against vblank start. in i915_get_vblank_counter()
124 struct intel_display *display = to_intel_display(crtc->dev); in g4x_get_vblank_counter()
126 enum pipe pipe = to_intel_crtc(crtc)->pipe; in g4x_get_vblank_counter()
128 if (!vblank->max_vblank_count) in g4x_get_vblank_counter()
137 struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(&crtc->base); in intel_crtc_scanlines_since_frame_timestamp()
138 const struct drm_display_mode *mode = &vblank->hwmode; in intel_crtc_scanlines_since_frame_timestamp()
139 u32 htotal = mode->crtc_htotal; in intel_crtc_scanlines_since_frame_timestamp()
140 u32 clock = mode->crtc_clock; in intel_crtc_scanlines_since_frame_timestamp()
156 PIPE_FRMTMSTMP(crtc->pipe)); in intel_crtc_scanlines_since_frame_timestamp()
165 PIPE_FRMTMSTMP(crtc->pipe)); in intel_crtc_scanlines_since_frame_timestamp()
168 return div_u64(mul_u32_u32(scan_curr_time - scan_prev_time, in intel_crtc_scanlines_since_frame_timestamp()
182 struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(&crtc->base); in __intel_get_crtc_scanline_from_timestamp()
183 const struct drm_display_mode *mode = &vblank->hwmode; in __intel_get_crtc_scanline_from_timestamp()
184 u32 vblank_start = mode->crtc_vblank_start; in __intel_get_crtc_scanline_from_timestamp()
185 u32 vtotal = mode->crtc_vtotal; in __intel_get_crtc_scanline_from_timestamp()
189 scanline = min(scanline, vtotal - 1); in __intel_get_crtc_scanline_from_timestamp()
200 * The scanline counter increments at the leading edge of hsync. in intel_crtc_scanline_offset()
202 * On most platforms it starts counting from vtotal-1 on the in intel_crtc_scanline_offset()
203 * first active line. That means the scanline counter value is in intel_crtc_scanline_offset()
206 * last active line), the scanline counter will read vblank_start-1. in intel_crtc_scanline_offset()
208 * On gen2 the scanline counter starts counting from 1 instead in intel_crtc_scanline_offset()
209 * of vtotal-1, so we have to subtract one. in intel_crtc_scanline_offset()
211 * On HSW+ the behaviour of the scanline counter depends on the output in intel_crtc_scanline_offset()
216 * On VLV/CHV DSI the scanline counter would appear to increment in intel_crtc_scanline_offset()
221 * the scanline counter from within the vblank interrupt handler. in intel_crtc_scanline_offset()
225 if (DISPLAY_VER(display) >= 20 || display->platform.battlemage) in intel_crtc_scanline_offset()
228 return -1; in intel_crtc_scanline_offset()
242 struct drm_vblank_crtc *vblank = drm_crtc_vblank_crtc(&crtc->base); in __intel_get_crtc_scanline()
243 const struct drm_display_mode *mode = &vblank->hwmode; in __intel_get_crtc_scanline()
244 enum pipe pipe = crtc->pipe; in __intel_get_crtc_scanline()
247 if (!crtc->active) in __intel_get_crtc_scanline()
250 if (crtc->mode_flags & I915_MODE_FLAG_GET_SCANLINE_FROM_TIMESTAMP) in __intel_get_crtc_scanline()
287 return (position + vtotal + crtc->scanline_offset) % vtotal; in __intel_get_crtc_scanline()
302 __acquires(i915->uncore.lock) in intel_vblank_section_enter()
304 struct drm_i915_private *i915 = to_i915(display->drm); in intel_vblank_section_enter()
305 spin_lock(&i915->uncore.lock); in intel_vblank_section_enter()
309 __releases(i915->uncore.lock) in intel_vblank_section_exit()
311 struct drm_i915_private *i915 = to_i915(display->drm); in intel_vblank_section_exit()
312 spin_unlock(&i915->uncore.lock); in intel_vblank_section_exit()
330 struct intel_display *display = to_intel_display(_crtc->dev); in i915_get_crtc_scanoutpos()
332 enum pipe pipe = crtc->pipe; in i915_get_crtc_scanoutpos()
337 display->platform.g4x || DISPLAY_VER(display) == 2 || in i915_get_crtc_scanoutpos()
338 crtc->mode_flags & I915_MODE_FLAG_USE_SCANLINE_COUNTER; in i915_get_crtc_scanoutpos()
340 if (drm_WARN_ON(display->drm, !mode->crtc_clock)) { in i915_get_crtc_scanoutpos()
341 drm_dbg(display->drm, in i915_get_crtc_scanoutpos()
347 htotal = mode->crtc_htotal; in i915_get_crtc_scanoutpos()
348 hsync_start = mode->crtc_hsync_start; in i915_get_crtc_scanoutpos()
367 if (crtc->mode_flags & I915_MODE_FLAG_VRR) { in i915_get_crtc_scanoutpos()
379 position = min(crtc->vmax_vblank_start + scanlines, vtotal - 1); in i915_get_crtc_scanoutpos()
399 * In interlaced modes, the pixel counter counts all pixels, in i915_get_crtc_scanoutpos()
402 * counter is beyond the length of the shorter field, just in i915_get_crtc_scanoutpos()
404 * matches how the scanline counter based position works since in i915_get_crtc_scanoutpos()
405 * the scanline counter doesn't count the two half lines. in i915_get_crtc_scanoutpos()
407 position = min(position, vtotal - 1); in i915_get_crtc_scanoutpos()
410 * Start of vblank interrupt is triggered at start of hsync, in i915_get_crtc_scanoutpos()
416 * always add htotal-hsync_start to the current pixel position. in i915_get_crtc_scanoutpos()
418 position = (position + htotal - hsync_start) % vtotal; in i915_get_crtc_scanoutpos()
437 position -= vbl_end; in i915_get_crtc_scanoutpos()
439 position += vtotal - vbl_end; in i915_get_crtc_scanoutpos()
446 *hpos = position - (*vpos * htotal); in i915_get_crtc_scanoutpos()
493 enum pipe pipe = crtc->pipe; in wait_for_pipe_scanline_moving()
497 drm_err(display->drm, in wait_for_pipe_scanline_moving()
516 struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc); in intel_crtc_update_active_timings()
517 u8 mode_flags = crtc_state->mode_flags; in intel_crtc_update_active_timings()
522 drm_mode_init(&adjusted_mode, &crtc_state->hw.adjusted_mode); in intel_crtc_update_active_timings()
525 drm_WARN_ON(display->drm, in intel_crtc_update_active_timings()
528 adjusted_mode.crtc_vtotal = crtc_state->vrr.vmax; in intel_crtc_update_active_timings()
529 adjusted_mode.crtc_vblank_end = crtc_state->vrr.vmax; in intel_crtc_update_active_timings()
548 spin_lock_irqsave(&display->drm->vblank_time_lock, irqflags); in intel_crtc_update_active_timings()
551 drm_calc_timestamping_constants(&crtc->base, &adjusted_mode); in intel_crtc_update_active_timings()
553 crtc->vmax_vblank_start = vmax_vblank_start; in intel_crtc_update_active_timings()
555 crtc->mode_flags = mode_flags; in intel_crtc_update_active_timings()
557 crtc->scanline_offset = intel_crtc_scanline_offset(crtc_state); in intel_crtc_update_active_timings()
559 spin_unlock_irqrestore(&display->drm->vblank_time_lock, irqflags); in intel_crtc_update_active_timings()
564 int vdisplay = mode->crtc_vdisplay; in intel_mode_vdisplay()
566 if (mode->flags & DRM_MODE_FLAG_INTERLACE) in intel_mode_vdisplay()
574 int vblank_start = mode->crtc_vblank_start; in intel_mode_vblank_start()
576 if (mode->flags & DRM_MODE_FLAG_INTERLACE) in intel_mode_vblank_start()
584 int vblank_end = mode->crtc_vblank_end; in intel_mode_vblank_end()
586 if (mode->flags & DRM_MODE_FLAG_INTERLACE) in intel_mode_vblank_end()
594 int vtotal = mode->crtc_vtotal; in intel_mode_vtotal()
596 if (mode->flags & DRM_MODE_FLAG_INTERLACE) in intel_mode_vtotal()
607 struct intel_crtc *crtc = to_intel_crtc(new_crtc_state->uapi.crtc); in intel_vblank_evade_init()
611 evade->crtc = crtc; in intel_vblank_evade_init()
613 evade->need_vlv_dsi_wa = (display->platform.valleyview || in intel_vblank_evade_init()
614 display->platform.cherryview) && in intel_vblank_evade_init()
628 adjusted_mode = &crtc_state->hw.adjusted_mode; in intel_vblank_evade_init()
630 if (crtc->mode_flags & I915_MODE_FLAG_VRR) { in intel_vblank_evade_init()
632 drm_WARN_ON(crtc->base.dev, intel_crtc_needs_modeset(new_crtc_state) || in intel_vblank_evade_init()
633 new_crtc_state->update_m_n || new_crtc_state->update_lrr); in intel_vblank_evade_init()
636 evade->vblank_start = intel_vrr_vmin_vblank_start(crtc_state); in intel_vblank_evade_init()
638 evade->vblank_start = intel_vrr_vmax_vblank_start(crtc_state); in intel_vblank_evade_init()
640 evade->vblank_start = intel_mode_vblank_start(adjusted_mode); in intel_vblank_evade_init()
644 evade->min = evade->vblank_start - intel_usecs_to_scanlines(adjusted_mode, in intel_vblank_evade_init()
646 evade->max = evade->vblank_start - 1; in intel_vblank_evade_init()
657 new_crtc_state->update_m_n || new_crtc_state->update_lrr) in intel_vblank_evade_init()
658 evade->min -= intel_mode_vblank_start(adjusted_mode) - in intel_vblank_evade_init()
662 /* must be called with vblank interrupt already enabled! */
665 struct intel_crtc *crtc = evade->crtc; in intel_vblank_evade()
668 wait_queue_head_t *wq = drm_crtc_vblank_waitqueue(&crtc->base); in intel_vblank_evade()
672 if (evade->min <= 0 || evade->max <= 0) in intel_vblank_evade()
684 if (scanline < evade->min || scanline > evade->max) in intel_vblank_evade()
688 drm_err(display->drm, in intel_vblank_evade()
690 pipe_name(crtc->pipe)); in intel_vblank_evade()
704 * On VLV/CHV DSI the scanline counter would appear to in intel_vblank_evade()
709 * vblank). And unfortunately we can't use the interrupt to in intel_vblank_evade()
711 * frame start interrupt instead since it will fire after the in intel_vblank_evade()
713 * in the interrupt code. So for now we'll just do the nasty in intel_vblank_evade()
718 while (evade->need_vlv_dsi_wa && scanline == evade->vblank_start) in intel_vblank_evade()