Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 881f47b6 authored by Xiang, Haihao's avatar Xiang, Haihao Committed by Chris Wilson
Browse files

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



This ring buffer is used for video decoding/encoding on Sandybridge.

Signed-off-by: default avatarXiang, Haihao <haihao.xiang@intel.com>
Reviewed-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: default avatarChris Wilson <chris@chris-wilson.co.uk>
parent a3f07cd5
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -157,11 +157,13 @@ static const struct intel_device_info intel_ironlake_m_info = {
static const struct intel_device_info intel_sandybridge_d_info = {
	.gen = 6,
	.need_gfx_hws = 1, .has_hotplug = 1,
	.has_bsd_ring = 1,
};

static const struct intel_device_info intel_sandybridge_m_info = {
	.gen = 6, .is_mobile = 1,
	.need_gfx_hws = 1, .has_hotplug = 1,
	.has_bsd_ring = 1,
};

static const struct pci_device_id pciidlist[] = {		/* aka */
+10 −5
Original line number Diff line number Diff line
@@ -300,6 +300,10 @@ static irqreturn_t ironlake_irq_handler(struct drm_device *dev)
	u32 de_iir, gt_iir, de_ier, pch_iir;
	struct drm_i915_master_private *master_priv;
	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  */
	de_ier = I915_READ(DEIER);
@@ -331,10 +335,9 @@ static irqreturn_t ironlake_irq_handler(struct drm_device *dev)
		mod_timer(&dev_priv->hangcheck_timer,
			  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);


	if (de_iir & DE_GSE)
		intel_opregion_gse_intr(dev);

@@ -1436,17 +1439,19 @@ static int ironlake_irq_postinstall(struct drm_device *dev)
	I915_WRITE(DEIER, dev_priv->de_irq_enable_reg);
	(void) I915_READ(DEIER);

	/* Gen6 only needs render pipe_control now */
	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_enable_reg = render_mask;

	I915_WRITE(GTIIR, I915_READ(GTIIR));
	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_BSD_IMR, ~GEN6_BSD_IMR_USER_INTERRUPT);
	}

	I915_WRITE(GTIER, dev_priv->gt_irq_enable_reg);
	(void) I915_READ(GTIER);

+24 −2
Original line number Diff line number Diff line
@@ -197,11 +197,11 @@
#define MI_STORE_DWORD_INDEX	MI_INSTR(0x21, 1)
#define   MI_STORE_DWORD_INDEX_SHIFT 2
#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_NON_SECURE	(1)
#define   MI_BATCH_NON_SECURE_I965 (1<<8)
#define MI_BATCH_BUFFER_START	MI_INSTR(0x31, 0)

/*
 * 3D instructions used by the kernel
 */
@@ -483,6 +483,28 @@
#define BSD_RING_ACTHD         0x04074
#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)
 */
@@ -2598,7 +2620,7 @@
#define GT_SYNC_STATUS          (1 << 2)
#define GT_USER_INTERRUPT       (1 << 0)
#define GT_BSD_USER_INTERRUPT   (1 << 5)

#define GT_GEN6_BSD_USER_INTERRUPT	(1 << 12)

#define GTISR   0x44010
#define GTIMR   0x44014
+123 −1
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@
#include "i915_drv.h"
#include "i915_drm.h"
#include "i915_trace.h"
#include "intel_drv.h"

static u32 i915_gem_get_seqno(struct drm_device *dev)
{
@@ -865,6 +866,124 @@ static struct intel_ring_buffer bsd_ring = {
	.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)
{
	drm_i915_private_t *dev_priv = dev->dev_private;
@@ -885,6 +1004,9 @@ int intel_init_bsd_ring_buffer(struct drm_device *dev)
{
	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;

	return intel_init_ring_buffer(dev, &dev_priv->bsd_ring);