diff options
-rw-r--r-- | drivers/gpu/drm/i915/i915_dma.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 16 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_reg.h | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_display.c | 29 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_drv.h | 1 |
6 files changed, 46 insertions, 9 deletions
diff --git a/drivers/gpu/drm/i915/i915_dma.c b/drivers/gpu/drm/i915/i915_dma.c index 84ce95602f00..4d59710c717e 100644 --- a/drivers/gpu/drm/i915/i915_dma.c +++ b/drivers/gpu/drm/i915/i915_dma.c | |||
@@ -1408,6 +1408,10 @@ static int i915_load_modeset_init(struct drm_device *dev, | |||
1408 | if (ret) | 1408 | if (ret) |
1409 | goto destroy_ringbuffer; | 1409 | goto destroy_ringbuffer; |
1410 | 1410 | ||
1411 | /* IIR "flip pending" bit means done if this bit is set */ | ||
1412 | if (IS_GEN3(dev) && (I915_READ(ECOSKPD) & ECO_FLIP_DONE)) | ||
1413 | dev_priv->flip_pending_is_done = true; | ||
1414 | |||
1411 | intel_modeset_init(dev); | 1415 | intel_modeset_init(dev); |
1412 | 1416 | ||
1413 | ret = drm_irq_install(dev); | 1417 | ret = drm_irq_install(dev); |
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h index f3f681fca76a..21e217dd48ef 100644 --- a/drivers/gpu/drm/i915/i915_drv.h +++ b/drivers/gpu/drm/i915/i915_drv.h | |||
@@ -595,6 +595,7 @@ typedef struct drm_i915_private { | |||
595 | struct drm_crtc *plane_to_crtc_mapping[2]; | 595 | struct drm_crtc *plane_to_crtc_mapping[2]; |
596 | struct drm_crtc *pipe_to_crtc_mapping[2]; | 596 | struct drm_crtc *pipe_to_crtc_mapping[2]; |
597 | wait_queue_head_t pending_flip_queue; | 597 | wait_queue_head_t pending_flip_queue; |
598 | bool flip_pending_is_done; | ||
598 | 599 | ||
599 | /* Reclocking support */ | 600 | /* Reclocking support */ |
600 | bool render_reclock_avail; | 601 | bool render_reclock_avail; |
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index e9710a7005d4..70e1e4b66744 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
@@ -940,22 +940,30 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) | |||
940 | if (HAS_BSD(dev) && (iir & I915_BSD_USER_INTERRUPT)) | 940 | if (HAS_BSD(dev) && (iir & I915_BSD_USER_INTERRUPT)) |
941 | DRM_WAKEUP(&dev_priv->bsd_ring.irq_queue); | 941 | DRM_WAKEUP(&dev_priv->bsd_ring.irq_queue); |
942 | 942 | ||
943 | if (iir & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT) | 943 | if (iir & I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT) { |
944 | intel_prepare_page_flip(dev, 0); | 944 | intel_prepare_page_flip(dev, 0); |
945 | if (dev_priv->flip_pending_is_done) | ||
946 | intel_finish_page_flip_plane(dev, 0); | ||
947 | } | ||
945 | 948 | ||
946 | if (iir & I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT) | 949 | if (iir & I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT) { |
950 | if (dev_priv->flip_pending_is_done) | ||
951 | intel_finish_page_flip_plane(dev, 1); | ||
947 | intel_prepare_page_flip(dev, 1); | 952 | intel_prepare_page_flip(dev, 1); |
953 | } | ||
948 | 954 | ||
949 | if (pipea_stats & vblank_status) { | 955 | if (pipea_stats & vblank_status) { |
950 | vblank++; | 956 | vblank++; |
951 | drm_handle_vblank(dev, 0); | 957 | drm_handle_vblank(dev, 0); |
952 | intel_finish_page_flip(dev, 0); | 958 | if (!dev_priv->flip_pending_is_done) |
959 | intel_finish_page_flip(dev, 0); | ||
953 | } | 960 | } |
954 | 961 | ||
955 | if (pipeb_stats & vblank_status) { | 962 | if (pipeb_stats & vblank_status) { |
956 | vblank++; | 963 | vblank++; |
957 | drm_handle_vblank(dev, 1); | 964 | drm_handle_vblank(dev, 1); |
958 | intel_finish_page_flip(dev, 1); | 965 | if (!dev_priv->flip_pending_is_done) |
966 | intel_finish_page_flip(dev, 1); | ||
959 | } | 967 | } |
960 | 968 | ||
961 | if ((pipea_stats & I915_LEGACY_BLC_EVENT_STATUS) || | 969 | if ((pipea_stats & I915_LEGACY_BLC_EVENT_STATUS) || |
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index 64b0a3afd92b..2cae38a57247 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
@@ -178,6 +178,7 @@ | |||
178 | #define MI_OVERLAY_OFF (0x2<<21) | 178 | #define MI_OVERLAY_OFF (0x2<<21) |
179 | #define MI_LOAD_SCAN_LINES_INCL MI_INSTR(0x12, 0) | 179 | #define MI_LOAD_SCAN_LINES_INCL MI_INSTR(0x12, 0) |
180 | #define MI_DISPLAY_FLIP MI_INSTR(0x14, 2) | 180 | #define MI_DISPLAY_FLIP MI_INSTR(0x14, 2) |
181 | #define MI_DISPLAY_FLIP_I915 MI_INSTR(0x14, 1) | ||
181 | #define MI_DISPLAY_FLIP_PLANE(n) ((n) << 20) | 182 | #define MI_DISPLAY_FLIP_PLANE(n) ((n) << 20) |
182 | #define MI_STORE_DWORD_IMM MI_INSTR(0x20, 1) | 183 | #define MI_STORE_DWORD_IMM MI_INSTR(0x20, 1) |
183 | #define MI_MEM_VIRTUAL (1 << 22) /* 965+ only */ | 184 | #define MI_MEM_VIRTUAL (1 << 22) /* 965+ only */ |
@@ -368,6 +369,9 @@ | |||
368 | #define CM0_RC_OP_FLUSH_DISABLE (1<<0) | 369 | #define CM0_RC_OP_FLUSH_DISABLE (1<<0) |
369 | #define BB_ADDR 0x02140 /* 8 bytes */ | 370 | #define BB_ADDR 0x02140 /* 8 bytes */ |
370 | #define GFX_FLSH_CNTL 0x02170 /* 915+ only */ | 371 | #define GFX_FLSH_CNTL 0x02170 /* 915+ only */ |
372 | #define ECOSKPD 0x021d0 | ||
373 | #define ECO_GATING_CX_ONLY (1<<3) | ||
374 | #define ECO_FLIP_DONE (1<<0) | ||
371 | 375 | ||
372 | /* GEN6 interrupt control */ | 376 | /* GEN6 interrupt control */ |
373 | #define GEN6_RENDER_HWSTAM 0x2098 | 377 | #define GEN6_RENDER_HWSTAM 0x2098 |
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c index dc65a1de5f02..6db778a75e42 100644 --- a/drivers/gpu/drm/i915/intel_display.c +++ b/drivers/gpu/drm/i915/intel_display.c | |||
@@ -4603,10 +4603,10 @@ static void intel_unpin_work_fn(struct work_struct *__work) | |||
4603 | kfree(work); | 4603 | kfree(work); |
4604 | } | 4604 | } |
4605 | 4605 | ||
4606 | void intel_finish_page_flip(struct drm_device *dev, int pipe) | 4606 | static void do_intel_finish_page_flip(struct drm_device *dev, |
4607 | struct drm_crtc *crtc) | ||
4607 | { | 4608 | { |
4608 | drm_i915_private_t *dev_priv = dev->dev_private; | 4609 | drm_i915_private_t *dev_priv = dev->dev_private; |
4609 | struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; | ||
4610 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 4610 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
4611 | struct intel_unpin_work *work; | 4611 | struct intel_unpin_work *work; |
4612 | struct drm_i915_gem_object *obj_priv; | 4612 | struct drm_i915_gem_object *obj_priv; |
@@ -4650,6 +4650,22 @@ void intel_finish_page_flip(struct drm_device *dev, int pipe) | |||
4650 | schedule_work(&work->work); | 4650 | schedule_work(&work->work); |
4651 | } | 4651 | } |
4652 | 4652 | ||
4653 | void intel_finish_page_flip(struct drm_device *dev, int pipe) | ||
4654 | { | ||
4655 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
4656 | struct drm_crtc *crtc = dev_priv->pipe_to_crtc_mapping[pipe]; | ||
4657 | |||
4658 | do_intel_finish_page_flip(dev, crtc); | ||
4659 | } | ||
4660 | |||
4661 | void intel_finish_page_flip_plane(struct drm_device *dev, int plane) | ||
4662 | { | ||
4663 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
4664 | struct drm_crtc *crtc = dev_priv->plane_to_crtc_mapping[plane]; | ||
4665 | |||
4666 | do_intel_finish_page_flip(dev, crtc); | ||
4667 | } | ||
4668 | |||
4653 | void intel_prepare_page_flip(struct drm_device *dev, int plane) | 4669 | void intel_prepare_page_flip(struct drm_device *dev, int plane) |
4654 | { | 4670 | { |
4655 | drm_i915_private_t *dev_priv = dev->dev_private; | 4671 | drm_i915_private_t *dev_priv = dev->dev_private; |
@@ -4745,14 +4761,17 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, | |||
4745 | ; | 4761 | ; |
4746 | 4762 | ||
4747 | BEGIN_LP_RING(4); | 4763 | BEGIN_LP_RING(4); |
4748 | OUT_RING(MI_DISPLAY_FLIP | | ||
4749 | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); | ||
4750 | OUT_RING(fb->pitch); | ||
4751 | if (IS_I965G(dev)) { | 4764 | if (IS_I965G(dev)) { |
4765 | OUT_RING(MI_DISPLAY_FLIP | | ||
4766 | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); | ||
4767 | OUT_RING(fb->pitch); | ||
4752 | OUT_RING(obj_priv->gtt_offset | obj_priv->tiling_mode); | 4768 | OUT_RING(obj_priv->gtt_offset | obj_priv->tiling_mode); |
4753 | pipesrc = I915_READ(pipesrc_reg); | 4769 | pipesrc = I915_READ(pipesrc_reg); |
4754 | OUT_RING(pipesrc & 0x0fff0fff); | 4770 | OUT_RING(pipesrc & 0x0fff0fff); |
4755 | } else { | 4771 | } else { |
4772 | OUT_RING(MI_DISPLAY_FLIP_I915 | | ||
4773 | MI_DISPLAY_FLIP_PLANE(intel_crtc->plane)); | ||
4774 | OUT_RING(fb->pitch); | ||
4756 | OUT_RING(obj_priv->gtt_offset); | 4775 | OUT_RING(obj_priv->gtt_offset); |
4757 | OUT_RING(MI_NOOP); | 4776 | OUT_RING(MI_NOOP); |
4758 | } | 4777 | } |
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h index df931f787665..72206f37c4fb 100644 --- a/drivers/gpu/drm/i915/intel_drv.h +++ b/drivers/gpu/drm/i915/intel_drv.h | |||
@@ -224,6 +224,7 @@ extern void intel_fbdev_fini(struct drm_device *dev); | |||
224 | 224 | ||
225 | extern void intel_prepare_page_flip(struct drm_device *dev, int plane); | 225 | extern void intel_prepare_page_flip(struct drm_device *dev, int plane); |
226 | extern void intel_finish_page_flip(struct drm_device *dev, int pipe); | 226 | extern void intel_finish_page_flip(struct drm_device *dev, int pipe); |
227 | extern void intel_finish_page_flip_plane(struct drm_device *dev, int plane); | ||
227 | 228 | ||
228 | extern void intel_setup_overlay(struct drm_device *dev); | 229 | extern void intel_setup_overlay(struct drm_device *dev); |
229 | extern void intel_cleanup_overlay(struct drm_device *dev); | 230 | extern void intel_cleanup_overlay(struct drm_device *dev); |