提交 881f47b6 编写于 作者: X Xiang, Haihao 提交者: Chris Wilson

drm/i915: add a new BSD ring buffer for Sandybridge

This ring buffer is used for video decoding/encoding on Sandybridge.
Signed-off-by: NXiang, Haihao <haihao.xiang@intel.com>
Reviewed-by: NChris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: NChris Wilson <chris@chris-wilson.co.uk>
上级 a3f07cd5
...@@ -157,11 +157,13 @@ static const struct intel_device_info intel_ironlake_m_info = { ...@@ -157,11 +157,13 @@ static const struct intel_device_info intel_ironlake_m_info = {
static const struct intel_device_info intel_sandybridge_d_info = { static const struct intel_device_info intel_sandybridge_d_info = {
.gen = 6, .gen = 6,
.need_gfx_hws = 1, .has_hotplug = 1, .need_gfx_hws = 1, .has_hotplug = 1,
.has_bsd_ring = 1,
}; };
static const struct intel_device_info intel_sandybridge_m_info = { static const struct intel_device_info intel_sandybridge_m_info = {
.gen = 6, .is_mobile = 1, .gen = 6, .is_mobile = 1,
.need_gfx_hws = 1, .has_hotplug = 1, .need_gfx_hws = 1, .has_hotplug = 1,
.has_bsd_ring = 1,
}; };
static const struct pci_device_id pciidlist[] = { /* aka */ static const struct pci_device_id pciidlist[] = { /* aka */
......
...@@ -300,6 +300,10 @@ static irqreturn_t ironlake_irq_handler(struct drm_device *dev) ...@@ -300,6 +300,10 @@ static irqreturn_t ironlake_irq_handler(struct drm_device *dev)
u32 de_iir, gt_iir, de_ier, pch_iir; u32 de_iir, gt_iir, de_ier, pch_iir;
struct drm_i915_master_private *master_priv; struct drm_i915_master_private *master_priv;
struct intel_ring_buffer *render_ring = &dev_priv->render_ring; struct intel_ring_buffer *render_ring = &dev_priv->render_ring;
u32 bsd_usr_interrupt = GT_BSD_USER_INTERRUPT;
if (IS_GEN6(dev))
bsd_usr_interrupt = GT_GEN6_BSD_USER_INTERRUPT;
/* disable master interrupt before clearing iir */ /* disable master interrupt before clearing iir */
de_ier = I915_READ(DEIER); de_ier = I915_READ(DEIER);
...@@ -331,10 +335,9 @@ static irqreturn_t ironlake_irq_handler(struct drm_device *dev) ...@@ -331,10 +335,9 @@ static irqreturn_t ironlake_irq_handler(struct drm_device *dev)
mod_timer(&dev_priv->hangcheck_timer, mod_timer(&dev_priv->hangcheck_timer,
jiffies + msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD)); jiffies + msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD));
} }
if (gt_iir & GT_BSD_USER_INTERRUPT) if (gt_iir & bsd_usr_interrupt)
DRM_WAKEUP(&dev_priv->bsd_ring.irq_queue); DRM_WAKEUP(&dev_priv->bsd_ring.irq_queue);
if (de_iir & DE_GSE) if (de_iir & DE_GSE)
intel_opregion_gse_intr(dev); intel_opregion_gse_intr(dev);
...@@ -1436,17 +1439,19 @@ static int ironlake_irq_postinstall(struct drm_device *dev) ...@@ -1436,17 +1439,19 @@ static int ironlake_irq_postinstall(struct drm_device *dev)
I915_WRITE(DEIER, dev_priv->de_irq_enable_reg); I915_WRITE(DEIER, dev_priv->de_irq_enable_reg);
(void) I915_READ(DEIER); (void) I915_READ(DEIER);
/* Gen6 only needs render pipe_control now */
if (IS_GEN6(dev)) if (IS_GEN6(dev))
render_mask = GT_PIPE_NOTIFY; render_mask = GT_PIPE_NOTIFY | GT_GEN6_BSD_USER_INTERRUPT;
dev_priv->gt_irq_mask_reg = ~render_mask; dev_priv->gt_irq_mask_reg = ~render_mask;
dev_priv->gt_irq_enable_reg = render_mask; dev_priv->gt_irq_enable_reg = render_mask;
I915_WRITE(GTIIR, I915_READ(GTIIR)); I915_WRITE(GTIIR, I915_READ(GTIIR));
I915_WRITE(GTIMR, dev_priv->gt_irq_mask_reg); I915_WRITE(GTIMR, dev_priv->gt_irq_mask_reg);
if (IS_GEN6(dev)) if (IS_GEN6(dev)) {
I915_WRITE(GEN6_RENDER_IMR, ~GEN6_RENDER_PIPE_CONTROL_NOTIFY_INTERRUPT); I915_WRITE(GEN6_RENDER_IMR, ~GEN6_RENDER_PIPE_CONTROL_NOTIFY_INTERRUPT);
I915_WRITE(GEN6_BSD_IMR, ~GEN6_BSD_IMR_USER_INTERRUPT);
}
I915_WRITE(GTIER, dev_priv->gt_irq_enable_reg); I915_WRITE(GTIER, dev_priv->gt_irq_enable_reg);
(void) I915_READ(GTIER); (void) I915_READ(GTIER);
......
...@@ -197,11 +197,11 @@ ...@@ -197,11 +197,11 @@
#define MI_STORE_DWORD_INDEX MI_INSTR(0x21, 1) #define MI_STORE_DWORD_INDEX MI_INSTR(0x21, 1)
#define MI_STORE_DWORD_INDEX_SHIFT 2 #define MI_STORE_DWORD_INDEX_SHIFT 2
#define MI_LOAD_REGISTER_IMM MI_INSTR(0x22, 1) #define MI_LOAD_REGISTER_IMM MI_INSTR(0x22, 1)
#define MI_FLUSH_DW MI_INSTR(0x26, 2) /* for GEN6 */
#define MI_BATCH_BUFFER MI_INSTR(0x30, 1) #define MI_BATCH_BUFFER MI_INSTR(0x30, 1)
#define MI_BATCH_NON_SECURE (1) #define MI_BATCH_NON_SECURE (1)
#define MI_BATCH_NON_SECURE_I965 (1<<8) #define MI_BATCH_NON_SECURE_I965 (1<<8)
#define MI_BATCH_BUFFER_START MI_INSTR(0x31, 0) #define MI_BATCH_BUFFER_START MI_INSTR(0x31, 0)
/* /*
* 3D instructions used by the kernel * 3D instructions used by the kernel
*/ */
...@@ -483,6 +483,28 @@ ...@@ -483,6 +483,28 @@
#define BSD_RING_ACTHD 0x04074 #define BSD_RING_ACTHD 0x04074
#define BSD_HWS_PGA 0x04080 #define BSD_HWS_PGA 0x04080
/*
* video command stream instruction and interrupt control register defines
* for GEN6
*/
#define GEN6_BSD_RING_TAIL 0x12030
#define GEN6_BSD_RING_HEAD 0x12034
#define GEN6_BSD_RING_START 0x12038
#define GEN6_BSD_RING_CTL 0x1203c
#define GEN6_BSD_RING_ACTHD 0x12074
#define GEN6_BSD_HWS_PGA 0x14080
#define GEN6_BSD_SLEEP_PSMI_CONTROL 0x12050
#define GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_MODIFY_MASK (1 << 16)
#define GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_DISABLE (1 << 0)
#define GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_ENABLE 0
#define GEN6_BSD_SLEEP_PSMI_CONTROL_IDLE_INDICATOR (1 << 3)
#define GEN6_BSD_IMR 0x120a8
#define GEN6_BSD_IMR_USER_INTERRUPT (1 << 12)
#define GEN6_BSD_RNCID 0x12198
/* /*
* Framebuffer compression (915+ only) * Framebuffer compression (915+ only)
*/ */
...@@ -2598,7 +2620,7 @@ ...@@ -2598,7 +2620,7 @@
#define GT_SYNC_STATUS (1 << 2) #define GT_SYNC_STATUS (1 << 2)
#define GT_USER_INTERRUPT (1 << 0) #define GT_USER_INTERRUPT (1 << 0)
#define GT_BSD_USER_INTERRUPT (1 << 5) #define GT_BSD_USER_INTERRUPT (1 << 5)
#define GT_GEN6_BSD_USER_INTERRUPT (1 << 12)
#define GTISR 0x44010 #define GTISR 0x44010
#define GTIMR 0x44014 #define GTIMR 0x44014
......
...@@ -32,6 +32,7 @@ ...@@ -32,6 +32,7 @@
#include "i915_drv.h" #include "i915_drv.h"
#include "i915_drm.h" #include "i915_drm.h"
#include "i915_trace.h" #include "i915_trace.h"
#include "intel_drv.h"
static u32 i915_gem_get_seqno(struct drm_device *dev) static u32 i915_gem_get_seqno(struct drm_device *dev)
{ {
...@@ -865,6 +866,124 @@ static struct intel_ring_buffer bsd_ring = { ...@@ -865,6 +866,124 @@ static struct intel_ring_buffer bsd_ring = {
.map = {0,} .map = {0,}
}; };
static void gen6_bsd_setup_status_page(struct drm_device *dev,
struct intel_ring_buffer *ring)
{
drm_i915_private_t *dev_priv = dev->dev_private;
I915_WRITE(GEN6_BSD_HWS_PGA, ring->status_page.gfx_addr);
I915_READ(GEN6_BSD_HWS_PGA);
}
static inline unsigned int gen6_bsd_ring_get_head(struct drm_device *dev,
struct intel_ring_buffer *ring)
{
drm_i915_private_t *dev_priv = dev->dev_private;
return I915_READ(GEN6_BSD_RING_HEAD) & HEAD_ADDR;
}
static inline unsigned int gen6_bsd_ring_get_tail(struct drm_device *dev,
struct intel_ring_buffer *ring)
{
drm_i915_private_t *dev_priv = dev->dev_private;
return I915_READ(GEN6_BSD_RING_TAIL) & TAIL_ADDR;
}
static inline void gen6_bsd_ring_set_tail(struct drm_device *dev,
u32 value)
{
drm_i915_private_t *dev_priv = dev->dev_private;
/* Every tail move must follow the sequence below */
I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL,
GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_MODIFY_MASK |
GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_DISABLE);
I915_WRITE(GEN6_BSD_RNCID, 0x0);
if (wait_for((I915_READ(GEN6_BSD_SLEEP_PSMI_CONTROL) &
GEN6_BSD_SLEEP_PSMI_CONTROL_IDLE_INDICATOR) == 0,
50))
DRM_ERROR("timed out waiting for IDLE Indicator\n");
I915_WRITE(GEN6_BSD_RING_TAIL, value);
I915_WRITE(GEN6_BSD_SLEEP_PSMI_CONTROL,
GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_MODIFY_MASK |
GEN6_BSD_SLEEP_PSMI_CONTROL_RC_ILDL_MESSAGE_ENABLE);
}
static inline unsigned int gen6_bsd_ring_get_active_head(struct drm_device *dev,
struct intel_ring_buffer *ring)
{
drm_i915_private_t *dev_priv = dev->dev_private;
return I915_READ(GEN6_BSD_RING_ACTHD);
}
static void gen6_bsd_ring_flush(struct drm_device *dev,
struct intel_ring_buffer *ring,
u32 invalidate_domains,
u32 flush_domains)
{
intel_ring_begin(dev, ring, 4);
intel_ring_emit(dev, ring, MI_FLUSH_DW);
intel_ring_emit(dev, ring, 0);
intel_ring_emit(dev, ring, 0);
intel_ring_emit(dev, ring, 0);
intel_ring_advance(dev, ring);
}
static int
gen6_bsd_ring_dispatch_gem_execbuffer(struct drm_device *dev,
struct intel_ring_buffer *ring,
struct drm_i915_gem_execbuffer2 *exec,
struct drm_clip_rect *cliprects,
uint64_t exec_offset)
{
uint32_t exec_start;
exec_start = (uint32_t) exec_offset + exec->batch_start_offset;
intel_ring_begin(dev, ring, 2);
intel_ring_emit(dev, ring, MI_BATCH_BUFFER_START | MI_BATCH_NON_SECURE_I965); /* bit0-7 is the length on GEN6+ */
intel_ring_emit(dev, ring, exec_start);
intel_ring_advance(dev, ring);
return 0;
}
/* ring buffer for Video Codec for Gen6+ */
static struct intel_ring_buffer gen6_bsd_ring = {
.name = "gen6 bsd ring",
.id = RING_BSD,
.regs = {
.ctl = GEN6_BSD_RING_CTL,
.head = GEN6_BSD_RING_HEAD,
.tail = GEN6_BSD_RING_TAIL,
.start = GEN6_BSD_RING_START
},
.size = 32 * PAGE_SIZE,
.alignment = PAGE_SIZE,
.virtual_start = NULL,
.dev = NULL,
.gem_object = NULL,
.head = 0,
.tail = 0,
.space = 0,
.user_irq_refcount = 0,
.irq_gem_seqno = 0,
.waiting_gem_seqno = 0,
.setup_status_page = gen6_bsd_setup_status_page,
.init = init_bsd_ring,
.get_head = gen6_bsd_ring_get_head,
.get_tail = gen6_bsd_ring_get_tail,
.set_tail = gen6_bsd_ring_set_tail,
.get_active_head = gen6_bsd_ring_get_active_head,
.flush = gen6_bsd_ring_flush,
.add_request = bsd_ring_add_request,
.get_gem_seqno = bsd_ring_get_gem_seqno,
.user_irq_get = bsd_ring_get_user_irq,
.user_irq_put = bsd_ring_put_user_irq,
.dispatch_gem_execbuffer = gen6_bsd_ring_dispatch_gem_execbuffer,
.status_page = {NULL, 0, NULL},
.map = {0,}
};
int intel_init_render_ring_buffer(struct drm_device *dev) int intel_init_render_ring_buffer(struct drm_device *dev)
{ {
drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_private_t *dev_priv = dev->dev_private;
...@@ -885,6 +1004,9 @@ int intel_init_bsd_ring_buffer(struct drm_device *dev) ...@@ -885,6 +1004,9 @@ int intel_init_bsd_ring_buffer(struct drm_device *dev)
{ {
drm_i915_private_t *dev_priv = dev->dev_private; drm_i915_private_t *dev_priv = dev->dev_private;
if (IS_GEN6(dev))
dev_priv->bsd_ring = gen6_bsd_ring;
else
dev_priv->bsd_ring = bsd_ring; dev_priv->bsd_ring = bsd_ring;
return intel_init_ring_buffer(dev, &dev_priv->bsd_ring); return intel_init_ring_buffer(dev, &dev_priv->bsd_ring);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册