drm/i915: Refactor gen2 to gen4 vblank interrupt handling
The indentation is getting way too deep. Pull the vblank interupt handling out to separate functions. v2: Keep flip_mask handling in the main irq handler and flatten {i8xx,i915}_handle_vblank() even further. Signed-off-by: Ville Syrjälä <ville.syrjala@linux.intel.com> Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
This commit is contained in:
parent
21ad833075
commit
90a72f8774
@ -2226,6 +2226,37 @@ static int i8xx_irq_postinstall(struct drm_device *dev)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns true when a page flip has completed.
|
||||||
|
*/
|
||||||
|
static bool i8xx_handle_vblank(struct drm_device *dev,
|
||||||
|
int pipe, u16 iir)
|
||||||
|
{
|
||||||
|
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||||
|
u16 flip_pending = DISPLAY_PLANE_FLIP_PENDING(pipe);
|
||||||
|
|
||||||
|
if (!drm_handle_vblank(dev, pipe))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if ((iir & flip_pending) == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
intel_prepare_page_flip(dev, pipe);
|
||||||
|
|
||||||
|
/* We detect FlipDone by looking for the change in PendingFlip from '1'
|
||||||
|
* to '0' on the following vblank, i.e. IIR has the Pendingflip
|
||||||
|
* asserted following the MI_DISPLAY_FLIP, but ISR is deasserted, hence
|
||||||
|
* the flip is completed (no longer pending). Since this doesn't raise
|
||||||
|
* an interrupt per se, we watch for the change at vblank.
|
||||||
|
*/
|
||||||
|
if (I915_READ16(ISR) & flip_pending)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
intel_finish_page_flip(dev, pipe);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static irqreturn_t i8xx_irq_handler(int irq, void *arg)
|
static irqreturn_t i8xx_irq_handler(int irq, void *arg)
|
||||||
{
|
{
|
||||||
struct drm_device *dev = (struct drm_device *) arg;
|
struct drm_device *dev = (struct drm_device *) arg;
|
||||||
@ -2281,28 +2312,12 @@ static irqreturn_t i8xx_irq_handler(int irq, void *arg)
|
|||||||
notify_ring(dev, &dev_priv->ring[RCS]);
|
notify_ring(dev, &dev_priv->ring[RCS]);
|
||||||
|
|
||||||
if (pipe_stats[0] & PIPE_VBLANK_INTERRUPT_STATUS &&
|
if (pipe_stats[0] & PIPE_VBLANK_INTERRUPT_STATUS &&
|
||||||
drm_handle_vblank(dev, 0)) {
|
i8xx_handle_vblank(dev, 0, iir))
|
||||||
if (iir & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT) {
|
flip_mask &= ~DISPLAY_PLANE_FLIP_PENDING(0);
|
||||||
intel_prepare_page_flip(dev, 0);
|
|
||||||
|
|
||||||
if ((I915_READ16(ISR) & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT) == 0) {
|
|
||||||
intel_finish_page_flip(dev, 0);
|
|
||||||
flip_mask &= ~I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pipe_stats[1] & PIPE_VBLANK_INTERRUPT_STATUS &&
|
if (pipe_stats[1] & PIPE_VBLANK_INTERRUPT_STATUS &&
|
||||||
drm_handle_vblank(dev, 1)) {
|
i8xx_handle_vblank(dev, 1, iir))
|
||||||
if (iir & I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT) {
|
flip_mask &= ~DISPLAY_PLANE_FLIP_PENDING(1);
|
||||||
intel_prepare_page_flip(dev, 1);
|
|
||||||
|
|
||||||
if ((I915_READ16(ISR) & I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT) == 0) {
|
|
||||||
intel_finish_page_flip(dev, 1);
|
|
||||||
flip_mask &= ~I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
iir = new_iir;
|
iir = new_iir;
|
||||||
}
|
}
|
||||||
@ -2419,6 +2434,37 @@ static void i915_hpd_irq_setup(struct drm_device *dev)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Returns true when a page flip has completed.
|
||||||
|
*/
|
||||||
|
static bool i915_handle_vblank(struct drm_device *dev,
|
||||||
|
int plane, int pipe, u32 iir)
|
||||||
|
{
|
||||||
|
drm_i915_private_t *dev_priv = dev->dev_private;
|
||||||
|
u32 flip_pending = DISPLAY_PLANE_FLIP_PENDING(plane);
|
||||||
|
|
||||||
|
if (!drm_handle_vblank(dev, pipe))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if ((iir & flip_pending) == 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
intel_prepare_page_flip(dev, plane);
|
||||||
|
|
||||||
|
/* We detect FlipDone by looking for the change in PendingFlip from '1'
|
||||||
|
* to '0' on the following vblank, i.e. IIR has the Pendingflip
|
||||||
|
* asserted following the MI_DISPLAY_FLIP, but ISR is deasserted, hence
|
||||||
|
* the flip is completed (no longer pending). Since this doesn't raise
|
||||||
|
* an interrupt per se, we watch for the change at vblank.
|
||||||
|
*/
|
||||||
|
if (I915_READ(ISR) & flip_pending)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
intel_finish_page_flip(dev, pipe);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static irqreturn_t i915_irq_handler(int irq, void *arg)
|
static irqreturn_t i915_irq_handler(int irq, void *arg)
|
||||||
{
|
{
|
||||||
struct drm_device *dev = (struct drm_device *) arg;
|
struct drm_device *dev = (struct drm_device *) arg;
|
||||||
@ -2428,10 +2474,6 @@ static irqreturn_t i915_irq_handler(int irq, void *arg)
|
|||||||
u32 flip_mask =
|
u32 flip_mask =
|
||||||
I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT |
|
I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT |
|
||||||
I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT;
|
I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT;
|
||||||
u32 flip[2] = {
|
|
||||||
I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT,
|
|
||||||
I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT
|
|
||||||
};
|
|
||||||
int pipe, ret = IRQ_NONE;
|
int pipe, ret = IRQ_NONE;
|
||||||
|
|
||||||
atomic_inc(&dev_priv->irq_received);
|
atomic_inc(&dev_priv->irq_received);
|
||||||
@ -2493,23 +2535,10 @@ static irqreturn_t i915_irq_handler(int irq, void *arg)
|
|||||||
int plane = pipe;
|
int plane = pipe;
|
||||||
if (IS_MOBILE(dev))
|
if (IS_MOBILE(dev))
|
||||||
plane = !plane;
|
plane = !plane;
|
||||||
if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS &&
|
|
||||||
drm_handle_vblank(dev, pipe)) {
|
|
||||||
if (iir & flip[plane]) {
|
|
||||||
intel_prepare_page_flip(dev, plane);
|
|
||||||
|
|
||||||
/* We detect FlipDone by looking for the change in PendingFlip from '1'
|
if (pipe_stats[pipe] & PIPE_VBLANK_INTERRUPT_STATUS &&
|
||||||
* to '0' on the following vblank, i.e. IIR has the Pendingflip
|
i915_handle_vblank(dev, plane, pipe, iir))
|
||||||
* asserted following the MI_DISPLAY_FLIP, but ISR is deasserted, hence
|
flip_mask &= ~DISPLAY_PLANE_FLIP_PENDING(plane);
|
||||||
* the flip is completed (no longer pending). Since this doesn't raise an
|
|
||||||
* interrupt per se, we watch for the change at vblank.
|
|
||||||
*/
|
|
||||||
if ((I915_READ(ISR) & flip[plane]) == 0) {
|
|
||||||
intel_finish_page_flip(dev, pipe);
|
|
||||||
flip_mask &= ~flip[plane];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS)
|
if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS)
|
||||||
blc_event = true;
|
blc_event = true;
|
||||||
@ -2686,10 +2715,6 @@ static irqreturn_t i965_irq_handler(int irq, void *arg)
|
|||||||
unsigned long irqflags;
|
unsigned long irqflags;
|
||||||
int irq_received;
|
int irq_received;
|
||||||
int ret = IRQ_NONE, pipe;
|
int ret = IRQ_NONE, pipe;
|
||||||
u32 flip[2] = {
|
|
||||||
I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT,
|
|
||||||
I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT
|
|
||||||
};
|
|
||||||
u32 flip_mask =
|
u32 flip_mask =
|
||||||
I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT |
|
I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT |
|
||||||
I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT;
|
I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT;
|
||||||
@ -2758,16 +2783,8 @@ static irqreturn_t i965_irq_handler(int irq, void *arg)
|
|||||||
|
|
||||||
for_each_pipe(pipe) {
|
for_each_pipe(pipe) {
|
||||||
if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS &&
|
if (pipe_stats[pipe] & PIPE_START_VBLANK_INTERRUPT_STATUS &&
|
||||||
drm_handle_vblank(dev, pipe)) {
|
i915_handle_vblank(dev, pipe, pipe, iir))
|
||||||
if (iir & flip[pipe]) {
|
flip_mask &= ~DISPLAY_PLANE_FLIP_PENDING(pipe);
|
||||||
intel_prepare_page_flip(dev, pipe);
|
|
||||||
|
|
||||||
if ((I915_READ(ISR) & flip[pipe]) == 0) {
|
|
||||||
intel_finish_page_flip(dev, pipe);
|
|
||||||
flip_mask &= ~flip[pipe];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS)
|
if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS)
|
||||||
blc_event = true;
|
blc_event = true;
|
||||||
|
@ -594,6 +594,7 @@
|
|||||||
#define I915_USER_INTERRUPT (1<<1)
|
#define I915_USER_INTERRUPT (1<<1)
|
||||||
#define I915_ASLE_INTERRUPT (1<<0)
|
#define I915_ASLE_INTERRUPT (1<<0)
|
||||||
#define I915_BSD_USER_INTERRUPT (1<<25)
|
#define I915_BSD_USER_INTERRUPT (1<<25)
|
||||||
|
#define DISPLAY_PLANE_FLIP_PENDING(plane) (1<<(11-(plane))) /* A and B only */
|
||||||
#define EIR 0x020b0
|
#define EIR 0x020b0
|
||||||
#define EMR 0x020b4
|
#define EMR 0x020b4
|
||||||
#define ESR 0x020b8
|
#define ESR 0x020b8
|
||||||
|
Loading…
Reference in New Issue
Block a user