aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJesse Barnes <jbarnes@virtuousgeek.org>2010-03-26 13:35:20 -0400
committerEric Anholt <eric@anholt.net>2010-06-18 20:59:53 -0400
commit1afe3e9d4335bf3bc5615e37243dc8fef65dac8f (patch)
treeddf1bc38a43a1f2cd6b289efe8837173a8bdca24 /drivers
parent83f7fd055eb3f1e843803cd906179d309553967b (diff)
drm/i915: gen3 page flipping fixes
Gen3 chips have slightly different flip commands, and also contain a bit that indicates whether a "flip pending" interrupt means the flip has been queued or has been completed. So implement support for the gen3 flip command, and make sure we use the flip pending interrupt correctly depending on the value of ECOSKPD bit 0. Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Eric Anholt <eric@anholt.net>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/i915/i915_dma.c4
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h1
-rw-r--r--drivers/gpu/drm/i915/i915_irq.c16
-rw-r--r--drivers/gpu/drm/i915/i915_reg.h4
-rw-r--r--drivers/gpu/drm/i915/intel_display.c29
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h1
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
4606void intel_finish_page_flip(struct drm_device *dev, int pipe) 4606static 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
4653void 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
4661void 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
4653void intel_prepare_page_flip(struct drm_device *dev, int plane) 4669void 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
225extern void intel_prepare_page_flip(struct drm_device *dev, int plane); 225extern void intel_prepare_page_flip(struct drm_device *dev, int plane);
226extern void intel_finish_page_flip(struct drm_device *dev, int pipe); 226extern void intel_finish_page_flip(struct drm_device *dev, int pipe);
227extern void intel_finish_page_flip_plane(struct drm_device *dev, int plane);
227 228
228extern void intel_setup_overlay(struct drm_device *dev); 229extern void intel_setup_overlay(struct drm_device *dev);
229extern void intel_cleanup_overlay(struct drm_device *dev); 230extern void intel_cleanup_overlay(struct drm_device *dev);