diff options
author | Xiang, Haihao <haihao.xiang@intel.com> | 2010-09-19 09:40:43 -0400 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2010-09-21 06:19:57 -0400 |
commit | 881f47b64723f4d697084533491a489e3e74b10f (patch) | |
tree | 8659b98e6dc7706af79e2d8c6894bc9dd2cb6217 /drivers | |
parent | a3f07cd53e31c1c27364e56266a541b9467c1895 (diff) |
drm/i915: add a new BSD ring buffer for Sandybridge
This ring buffer is used for video decoding/encoding on Sandybridge.
Signed-off-by: Xiang, Haihao <haihao.xiang@intel.com>
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/gpu/drm/i915/i915_drv.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_irq.c | 15 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/i915_reg.h | 26 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_ringbuffer.c | 124 |
4 files changed, 159 insertions, 8 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c index 393696cee86d..2c87f9b97b6f 100644 --- a/drivers/gpu/drm/i915/i915_drv.c +++ b/drivers/gpu/drm/i915/i915_drv.c | |||
@@ -157,11 +157,13 @@ static const struct intel_device_info intel_ironlake_m_info = { | |||
157 | static const struct intel_device_info intel_sandybridge_d_info = { | 157 | static const struct intel_device_info intel_sandybridge_d_info = { |
158 | .gen = 6, | 158 | .gen = 6, |
159 | .need_gfx_hws = 1, .has_hotplug = 1, | 159 | .need_gfx_hws = 1, .has_hotplug = 1, |
160 | .has_bsd_ring = 1, | ||
160 | }; | 161 | }; |
161 | 162 | ||
162 | static const struct intel_device_info intel_sandybridge_m_info = { | 163 | static const struct intel_device_info intel_sandybridge_m_info = { |
163 | .gen = 6, .is_mobile = 1, | 164 | .gen = 6, .is_mobile = 1, |
164 | .need_gfx_hws = 1, .has_hotplug = 1, | 165 | .need_gfx_hws = 1, .has_hotplug = 1, |
166 | .has_bsd_ring = 1, | ||
165 | }; | 167 | }; |
166 | 168 | ||
167 | static const struct pci_device_id pciidlist[] = { /* aka */ | 169 | static const struct pci_device_id pciidlist[] = { /* aka */ |
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c index b1e7655288d8..d4c053e1c376 100644 --- a/drivers/gpu/drm/i915/i915_irq.c +++ b/drivers/gpu/drm/i915/i915_irq.c | |||
@@ -300,6 +300,10 @@ static irqreturn_t ironlake_irq_handler(struct drm_device *dev) | |||
300 | u32 de_iir, gt_iir, de_ier, pch_iir; | 300 | u32 de_iir, gt_iir, de_ier, pch_iir; |
301 | struct drm_i915_master_private *master_priv; | 301 | struct drm_i915_master_private *master_priv; |
302 | struct intel_ring_buffer *render_ring = &dev_priv->render_ring; | 302 | struct intel_ring_buffer *render_ring = &dev_priv->render_ring; |
303 | u32 bsd_usr_interrupt = GT_BSD_USER_INTERRUPT; | ||
304 | |||
305 | if (IS_GEN6(dev)) | ||
306 | bsd_usr_interrupt = GT_GEN6_BSD_USER_INTERRUPT; | ||
303 | 307 | ||
304 | /* disable master interrupt before clearing iir */ | 308 | /* disable master interrupt before clearing iir */ |
305 | de_ier = I915_READ(DEIER); | 309 | de_ier = I915_READ(DEIER); |
@@ -331,10 +335,9 @@ static irqreturn_t ironlake_irq_handler(struct drm_device *dev) | |||
331 | mod_timer(&dev_priv->hangcheck_timer, | 335 | mod_timer(&dev_priv->hangcheck_timer, |
332 | jiffies + msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD)); | 336 | jiffies + msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD)); |
333 | } | 337 | } |
334 | if (gt_iir & GT_BSD_USER_INTERRUPT) | 338 | if (gt_iir & bsd_usr_interrupt) |
335 | DRM_WAKEUP(&dev_priv->bsd_ring.irq_queue); | 339 | DRM_WAKEUP(&dev_priv->bsd_ring.irq_queue); |
336 | 340 | ||
337 | |||
338 | if (de_iir & DE_GSE) | 341 | if (de_iir & DE_GSE) |
339 | intel_opregion_gse_intr(dev); | 342 | intel_opregion_gse_intr(dev); |
340 | 343 | ||
@@ -1436,17 +1439,19 @@ static int ironlake_irq_postinstall(struct drm_device *dev) | |||
1436 | I915_WRITE(DEIER, dev_priv->de_irq_enable_reg); | 1439 | I915_WRITE(DEIER, dev_priv->de_irq_enable_reg); |
1437 | (void) I915_READ(DEIER); | 1440 | (void) I915_READ(DEIER); |
1438 | 1441 | ||
1439 | /* Gen6 only needs render pipe_control now */ | ||
1440 | if (IS_GEN6(dev)) | 1442 | if (IS_GEN6(dev)) |
1441 | render_mask = GT_PIPE_NOTIFY; | 1443 | render_mask = GT_PIPE_NOTIFY | GT_GEN6_BSD_USER_INTERRUPT; |
1442 | 1444 | ||
1443 | dev_priv->gt_irq_mask_reg = ~render_mask; | 1445 | dev_priv->gt_irq_mask_reg = ~render_mask; |
1444 | dev_priv->gt_irq_enable_reg = render_mask; | 1446 | dev_priv->gt_irq_enable_reg = render_mask; |
1445 | 1447 | ||
1446 | I915_WRITE(GTIIR, I915_READ(GTIIR)); | 1448 | I915_WRITE(GTIIR, I915_READ(GTIIR)); |
1447 | I915_WRITE(GTIMR, dev_priv->gt_irq_mask_reg); | 1449 | I915_WRITE(GTIMR, dev_priv->gt_irq_mask_reg); |
1448 | if (IS_GEN6(dev)) | 1450 | if (IS_GEN6(dev)) { |
1449 | I915_WRITE(GEN6_RENDER_IMR, ~GEN6_RENDER_PIPE_CONTROL_NOTIFY_INTERRUPT); | 1451 | I915_WRITE(GEN6_RENDER_IMR, ~GEN6_RENDER_PIPE_CONTROL_NOTIFY_INTERRUPT); |
1452 | I915_WRITE(GEN6_BSD_IMR, ~GEN6_BSD_IMR_USER_INTERRUPT); | ||
1453 | } | ||
1454 | |||
1450 | I915_WRITE(GTIER, dev_priv->gt_irq_enable_reg); | 1455 | I915_WRITE(GTIER, dev_priv->gt_irq_enable_reg); |
1451 | (void) I915_READ(GTIER); | 1456 | (void) I915_READ(GTIER); |
1452 | 1457 | ||
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h index b46e580421e1..8d51de0e01f2 100644 --- a/drivers/gpu/drm/i915/i915_reg.h +++ b/drivers/gpu/drm/i915/i915_reg.h | |||
@@ -197,11 +197,11 @@ | |||
197 | #define MI_STORE_DWORD_INDEX MI_INSTR(0x21, 1) | 197 | #define MI_STORE_DWORD_INDEX MI_INSTR(0x21, 1) |
198 | #define MI_STORE_DWORD_INDEX_SHIFT 2 | 198 | #define MI_STORE_DWORD_INDEX_SHIFT 2 |
199 | #define MI_LOAD_REGISTER_IMM MI_INSTR(0x22, 1) | 199 | #define MI_LOAD_REGISTER_IMM MI_INSTR(0x22, 1) |
200 | #define MI_FLUSH_DW MI_INSTR(0x26, 2) /* for GEN6 */ | ||
200 | #define MI_BATCH_BUFFER MI_INSTR(0x30, 1) | 201 | #define MI_BATCH_BUFFER MI_INSTR(0x30, 1) |
201 | #define MI_BATCH_NON_SECURE (1) | 202 | #define MI_BATCH_NON_SECURE (1) |
202 | #define MI_BATCH_NON_SECURE_I965 (1<<8) | 203 | #define MI_BATCH_NON_SECURE_I965 (1<<8) |
203 | #define MI_BATCH_BUFFER_START MI_INSTR(0x31, 0) | 204 | #define MI_BATCH_BUFFER_START MI_INSTR(0x31, 0) |
204 | |||
205 | /* | 205 | /* |
206 | * 3D instructions used by the kernel | 206 | * 3D instructions used by the kernel |
207 | */ | 207 | */ |
@@ -484,6 +484,28 @@ | |||
484 | #define BSD_HWS_PGA 0x04080 | 484 | #define BSD_HWS_PGA 0x04080 |
485 | 485 | ||
486 | /* | 486 | /* |
487 | * video command stream instruction and interrupt control register defines | ||
488 | * for GEN6 | ||
489 | */ | ||
490 | #define GEN6_BSD_RING_TAIL 0x12030 | ||
491 | #define GEN6_BSD_RING_HEAD 0x12034 | ||
492 | #define GEN6_BSD_RING_START 0x12038 | ||
493 | #define GEN6_BSD_RING_CTL 0x1203c | ||
494 | #define GEN6_BSD_RING_ACTHD 0x12074 | ||
495 | #define GEN6_BSD_HWS_PGA 0x14080 | ||
496 | |||
497 | #define GEN6_BSD_SLEEP_PSMI_CONTROL 0x12050 | ||
498 | #define GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_MODIFY_MASK (1 << 16) | ||
499 | #define GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_DISABLE (1 << 0) | ||
500 | #define GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_ENABLE 0 | ||
501 | #define GEN6_BSD_SLEEP_PSMI_CONTROL_IDLE_INDICATOR (1 << 3) | ||
502 | |||
503 | #define GEN6_BSD_IMR 0x120a8 | ||
504 | #define GEN6_BSD_IMR_USER_INTERRUPT (1 << 12) | ||
505 | |||
506 | #define GEN6_BSD_RNCID 0x12198 | ||
507 | |||
508 | /* | ||
487 | * Framebuffer compression (915+ only) | 509 | * Framebuffer compression (915+ only) |
488 | */ | 510 | */ |
489 | 511 | ||
@@ -2598,7 +2620,7 @@ | |||
2598 | #define GT_SYNC_STATUS (1 << 2) | 2620 | #define GT_SYNC_STATUS (1 << 2) |
2599 | #define GT_USER_INTERRUPT (1 << 0) | 2621 | #define GT_USER_INTERRUPT (1 << 0) |
2600 | #define GT_BSD_USER_INTERRUPT (1 << 5) | 2622 | #define GT_BSD_USER_INTERRUPT (1 << 5) |
2601 | 2623 | #define GT_GEN6_BSD_USER_INTERRUPT (1 << 12) | |
2602 | 2624 | ||
2603 | #define GTISR 0x44010 | 2625 | #define GTISR 0x44010 |
2604 | #define GTIMR 0x44014 | 2626 | #define GTIMR 0x44014 |
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c index 3f80f18e2844..478406d1886c 100644 --- a/drivers/gpu/drm/i915/intel_ringbuffer.c +++ b/drivers/gpu/drm/i915/intel_ringbuffer.c | |||
@@ -32,6 +32,7 @@ | |||
32 | #include "i915_drv.h" | 32 | #include "i915_drv.h" |
33 | #include "i915_drm.h" | 33 | #include "i915_drm.h" |
34 | #include "i915_trace.h" | 34 | #include "i915_trace.h" |
35 | #include "intel_drv.h" | ||
35 | 36 | ||
36 | static u32 i915_gem_get_seqno(struct drm_device *dev) | 37 | static u32 i915_gem_get_seqno(struct drm_device *dev) |
37 | { | 38 | { |
@@ -865,6 +866,124 @@ static struct intel_ring_buffer bsd_ring = { | |||
865 | .map = {0,} | 866 | .map = {0,} |
866 | }; | 867 | }; |
867 | 868 | ||
869 | |||
870 | static void gen6_bsd_setup_status_page(struct drm_device *dev, | ||
871 | struct intel_ring_buffer *ring) | ||
872 | { | ||
873 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
874 | I915_WRITE(GEN6_BSD_HWS_PGA, ring->status_page.gfx_addr); | ||
875 | I915_READ(GEN6_BSD_HWS_PGA); | ||
876 | } | ||
877 | |||
878 | static inline unsigned int gen6_bsd_ring_get_head(struct drm_device *dev, | ||
879 | struct intel_ring_buffer *ring) | ||
880 | { | ||
881 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
882 | return I915_READ(GEN6_BSD_RING_HEAD) & HEAD_ADDR; | ||
883 | } | ||
884 | |||
885 | static inline unsigned int gen6_bsd_ring_get_tail(struct drm_device *dev, | ||
886 | struct intel_ring_buffer *ring) | ||
887 | { | ||
888 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
889 | return I915_READ(GEN6_BSD_RING_TAIL) & TAIL_ADDR; | ||
890 | } | ||
891 | |||
892 | static inline void gen6_bsd_ring_set_tail(struct drm_device *dev, | ||
893 | u32 value) | ||
894 | { | ||
895 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
896 | |||
897 | /* Every tail move must follow the sequence below */ | ||
898 | I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL, | ||
899 | GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_MODIFY_MASK | | ||
900 | GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_DISABLE); | ||
901 | I915_WRITE(GEN6_BSD_RNCID, 0x0); | ||
902 | |||
903 | if (wait_for((I915_READ(GEN6_BSD_SLEEP_PSMI_CONTROL) & | ||
904 | GEN6_BSD_SLEEP_PSMI_CONTROL_IDLE_INDICATOR) == 0, | ||
905 | 50)) | ||
906 | DRM_ERROR("timed out waiting for IDLE Indicator\n"); | ||
907 | |||
908 | I915_WRITE(GEN6_BSD_RING_TAIL, value); | ||
909 | I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL, | ||
910 | GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_MODIFY_MASK | | ||
911 | GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_ENABLE); | ||
912 | } | ||
913 | |||
914 | static inline unsigned int gen6_bsd_ring_get_active_head(struct drm_device *dev, | ||
915 | struct intel_ring_buffer *ring) | ||
916 | { | ||
917 | drm_i915_private_t *dev_priv = dev->dev_private; | ||
918 | return I915_READ(GEN6_BSD_RING_ACTHD); | ||
919 | } | ||
920 | |||
921 | static void gen6_bsd_ring_flush(struct drm_device *dev, | ||
922 | struct intel_ring_buffer *ring, | ||
923 | u32 invalidate_domains, | ||
924 | u32 flush_domains) | ||
925 | { | ||
926 | intel_ring_begin(dev, ring, 4); | ||
927 | intel_ring_emit(dev, ring, MI_FLUSH_DW); | ||
928 | intel_ring_emit(dev, ring, 0); | ||
929 | intel_ring_emit(dev, ring, 0); | ||
930 | intel_ring_emit(dev, ring, 0); | ||
931 | intel_ring_advance(dev, ring); | ||
932 | } | ||
933 | |||
934 | static int | ||
935 | gen6_bsd_ring_dispatch_gem_execbuffer(struct drm_device *dev, | ||
936 | struct intel_ring_buffer *ring, | ||
937 | struct drm_i915_gem_execbuffer2 *exec, | ||
938 | struct drm_clip_rect *cliprects, | ||
939 | uint64_t exec_offset) | ||
940 | { | ||
941 | uint32_t exec_start; | ||
942 | exec_start = (uint32_t) exec_offset + exec->batch_start_offset; | ||
943 | intel_ring_begin(dev, ring, 2); | ||
944 | intel_ring_emit(dev, ring, MI_BATCH_BUFFER_START | MI_BATCH_NON_SECURE_I965); /* bit0-7 is the length on GEN6+ */ | ||
945 | intel_ring_emit(dev, ring, exec_start); | ||
946 | intel_ring_advance(dev, ring); | ||
947 | return 0; | ||
948 | } | ||
949 | |||
950 | /* ring buffer for Video Codec for Gen6+ */ | ||
951 | static struct intel_ring_buffer gen6_bsd_ring = { | ||
952 | .name = "gen6 bsd ring", | ||
953 | .id = RING_BSD, | ||
954 | .regs = { | ||
955 | .ctl = GEN6_BSD_RING_CTL, | ||
956 | .head = GEN6_BSD_RING_HEAD, | ||
957 | .tail = GEN6_BSD_RING_TAIL, | ||
958 | .start = GEN6_BSD_RING_START | ||
959 | }, | ||
960 | .size = 32 * PAGE_SIZE, | ||
961 | .alignment = PAGE_SIZE, | ||
962 | .virtual_start = NULL, | ||
963 | .dev = NULL, | ||
964 | .gem_object = NULL, | ||
965 | .head = 0, | ||
966 | .tail = 0, | ||
967 | .space = 0, | ||
968 | .user_irq_refcount = 0, | ||
969 | .irq_gem_seqno = 0, | ||
970 | .waiting_gem_seqno = 0, | ||
971 | .setup_status_page = gen6_bsd_setup_status_page, | ||
972 | .init = init_bsd_ring, | ||
973 | .get_head = gen6_bsd_ring_get_head, | ||
974 | .get_tail = gen6_bsd_ring_get_tail, | ||
975 | .set_tail = gen6_bsd_ring_set_tail, | ||
976 | .get_active_head = gen6_bsd_ring_get_active_head, | ||
977 | .flush = gen6_bsd_ring_flush, | ||
978 | .add_request = bsd_ring_add_request, | ||
979 | .get_gem_seqno = bsd_ring_get_gem_seqno, | ||
980 | .user_irq_get = bsd_ring_get_user_irq, | ||
981 | .user_irq_put = bsd_ring_put_user_irq, | ||
982 | .dispatch_gem_execbuffer = gen6_bsd_ring_dispatch_gem_execbuffer, | ||
983 | .status_page = {NULL, 0, NULL}, | ||
984 | .map = {0,} | ||
985 | }; | ||
986 | |||
868 | int intel_init_render_ring_buffer(struct drm_device *dev) | 987 | int intel_init_render_ring_buffer(struct drm_device *dev) |
869 | { | 988 | { |
870 | drm_i915_private_t *dev_priv = dev->dev_private; | 989 | drm_i915_private_t *dev_priv = dev->dev_private; |
@@ -885,7 +1004,10 @@ int intel_init_bsd_ring_buffer(struct drm_device *dev) | |||
885 | { | 1004 | { |
886 | drm_i915_private_t *dev_priv = dev->dev_private; | 1005 | drm_i915_private_t *dev_priv = dev->dev_private; |
887 | 1006 | ||
888 | dev_priv->bsd_ring = bsd_ring; | 1007 | if (IS_GEN6(dev)) |
1008 | dev_priv->bsd_ring = gen6_bsd_ring; | ||
1009 | else | ||
1010 | dev_priv->bsd_ring = bsd_ring; | ||
889 | 1011 | ||
890 | return intel_init_ring_buffer(dev, &dev_priv->bsd_ring); | 1012 | return intel_init_ring_buffer(dev, &dev_priv->bsd_ring); |
891 | } | 1013 | } |