Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 148705
b: refs/heads/master
c: 036a4a7
h: refs/heads/master
i:
  148703: de005fe
v: v3
  • Loading branch information
Zhenyu Wang authored and Eric Anholt committed Jun 9, 2009
1 parent 7f132e9 commit 52e2953
Show file tree
Hide file tree
Showing 5 changed files with 191 additions and 9 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: d765898970f35acef960581f678b9da9d5c779fa
refs/heads/master: 036a4a7d9272582fc7370359515d807393e2f728
2 changes: 1 addition & 1 deletion trunk/drivers/gpu/drm/i915/i915_dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -1162,7 +1162,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)

dev->driver->get_vblank_counter = i915_get_vblank_counter;
dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */
if (IS_G4X(dev)) {
if (IS_G4X(dev) || IS_IGDNG(dev)) {
dev->max_vblank_count = 0xffffffff; /* full 32 bit counter */
dev->driver->get_vblank_counter = gm45_get_vblank_counter;
}
Expand Down
5 changes: 5 additions & 0 deletions trunk/drivers/gpu/drm/i915/i915_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,11 @@ typedef struct drm_i915_private {
/** Cached value of IMR to avoid reads in updating the bitfield */
u32 irq_mask_reg;
u32 pipestat[2];
/** splitted irq regs for graphics and display engine on IGDNG,
irq_mask_reg is still used for display irq. */
u32 gt_irq_mask_reg;
u32 gt_irq_enable_reg;
u32 de_irq_enable_reg;

u32 hotplug_supported_mask;
struct work_struct hotplug_work;
Expand Down
5 changes: 4 additions & 1 deletion trunk/drivers/gpu/drm/i915/i915_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -1714,7 +1714,10 @@ i915_wait_request(struct drm_device *dev, uint32_t seqno)
BUG_ON(seqno == 0);

if (!i915_seqno_passed(i915_get_gem_seqno(dev), seqno)) {
ier = I915_READ(IER);
if (IS_IGDNG(dev))
ier = I915_READ(DEIER) | I915_READ(GTIER);
else
ier = I915_READ(IER);
if (!ier) {
DRM_ERROR("something (likely vbetool) disabled "
"interrupts, re-enabling\n");
Expand Down
186 changes: 180 additions & 6 deletions trunk/drivers/gpu/drm/i915/i915_irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,47 @@
#define DRM_I915_VBLANK_PIPE_ALL (DRM_I915_VBLANK_PIPE_A | \
DRM_I915_VBLANK_PIPE_B)

void
igdng_enable_graphics_irq(drm_i915_private_t *dev_priv, u32 mask)
{
if ((dev_priv->gt_irq_mask_reg & mask) != 0) {
dev_priv->gt_irq_mask_reg &= ~mask;
I915_WRITE(GTIMR, dev_priv->gt_irq_mask_reg);
(void) I915_READ(GTIMR);
}
}

static inline void
igdng_disable_graphics_irq(drm_i915_private_t *dev_priv, u32 mask)
{
if ((dev_priv->gt_irq_mask_reg & mask) != mask) {
dev_priv->gt_irq_mask_reg |= mask;
I915_WRITE(GTIMR, dev_priv->gt_irq_mask_reg);
(void) I915_READ(GTIMR);
}
}

/* For display hotplug interrupt */
void
igdng_enable_display_irq(drm_i915_private_t *dev_priv, u32 mask)
{
if ((dev_priv->irq_mask_reg & mask) != 0) {
dev_priv->irq_mask_reg &= ~mask;
I915_WRITE(DEIMR, dev_priv->irq_mask_reg);
(void) I915_READ(DEIMR);
}
}

static inline void
igdng_disable_display_irq(drm_i915_private_t *dev_priv, u32 mask)
{
if ((dev_priv->irq_mask_reg & mask) != mask) {
dev_priv->irq_mask_reg |= mask;
I915_WRITE(DEIMR, dev_priv->irq_mask_reg);
(void) I915_READ(DEIMR);
}
}

void
i915_enable_irq(drm_i915_private_t *dev_priv, u32 mask)
{
Expand Down Expand Up @@ -196,6 +237,47 @@ static void i915_hotplug_work_func(struct work_struct *work)
drm_sysfs_hotplug_event(dev);
}

irqreturn_t igdng_irq_handler(struct drm_device *dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
int ret = IRQ_NONE;
u32 de_iir, gt_iir;
u32 new_de_iir, new_gt_iir;
struct drm_i915_master_private *master_priv;

de_iir = I915_READ(DEIIR);
gt_iir = I915_READ(GTIIR);

for (;;) {
if (de_iir == 0 && gt_iir == 0)
break;

ret = IRQ_HANDLED;

I915_WRITE(DEIIR, de_iir);
new_de_iir = I915_READ(DEIIR);
I915_WRITE(GTIIR, gt_iir);
new_gt_iir = I915_READ(GTIIR);

if (dev->primary->master) {
master_priv = dev->primary->master->driver_priv;
if (master_priv->sarea_priv)
master_priv->sarea_priv->last_dispatch =
READ_BREADCRUMB(dev_priv);
}

if (gt_iir & GT_USER_INTERRUPT) {
dev_priv->mm.irq_gem_seqno = i915_get_gem_seqno(dev);
DRM_WAKEUP(&dev_priv->irq_queue);
}

de_iir = new_de_iir;
gt_iir = new_gt_iir;
}

return ret;
}

irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)
{
struct drm_device *dev = (struct drm_device *) arg;
Expand All @@ -212,6 +294,9 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS)

atomic_inc(&dev_priv->irq_received);

if (IS_IGDNG(dev))
return igdng_irq_handler(dev);

iir = I915_READ(IIR);

if (IS_I965G(dev)) {
Expand Down Expand Up @@ -349,8 +434,12 @@ void i915_user_irq_get(struct drm_device *dev)
unsigned long irqflags;

spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
if (dev->irq_enabled && (++dev_priv->user_irq_refcount == 1))
i915_enable_irq(dev_priv, I915_USER_INTERRUPT);
if (dev->irq_enabled && (++dev_priv->user_irq_refcount == 1)) {
if (IS_IGDNG(dev))
igdng_enable_graphics_irq(dev_priv, GT_USER_INTERRUPT);
else
i915_enable_irq(dev_priv, I915_USER_INTERRUPT);
}
spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
}

Expand All @@ -361,8 +450,12 @@ void i915_user_irq_put(struct drm_device *dev)

spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
BUG_ON(dev->irq_enabled && dev_priv->user_irq_refcount <= 0);
if (dev->irq_enabled && (--dev_priv->user_irq_refcount == 0))
i915_disable_irq(dev_priv, I915_USER_INTERRUPT);
if (dev->irq_enabled && (--dev_priv->user_irq_refcount == 0)) {
if (IS_IGDNG(dev))
igdng_disable_graphics_irq(dev_priv, GT_USER_INTERRUPT);
else
i915_disable_irq(dev_priv, I915_USER_INTERRUPT);
}
spin_unlock_irqrestore(&dev_priv->user_irq_lock, irqflags);
}

Expand Down Expand Up @@ -455,6 +548,9 @@ int i915_enable_vblank(struct drm_device *dev, int pipe)
if (!(pipeconf & PIPEACONF_ENABLE))
return -EINVAL;

if (IS_IGDNG(dev))
return 0;

spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
if (IS_I965G(dev))
i915_enable_pipestat(dev_priv, pipe,
Expand All @@ -474,6 +570,9 @@ void i915_disable_vblank(struct drm_device *dev, int pipe)
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
unsigned long irqflags;

if (IS_IGDNG(dev))
return;

spin_lock_irqsave(&dev_priv->user_irq_lock, irqflags);
i915_disable_pipestat(dev_priv, pipe,
PIPE_VBLANK_INTERRUPT_ENABLE |
Expand Down Expand Up @@ -547,12 +646,65 @@ int i915_vblank_swap(struct drm_device *dev, void *data,

/* drm_dma.h hooks
*/
static void igdng_irq_preinstall(struct drm_device *dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;

I915_WRITE(HWSTAM, 0xeffe);

/* XXX hotplug from PCH */

I915_WRITE(DEIMR, 0xffffffff);
I915_WRITE(DEIER, 0x0);
(void) I915_READ(DEIER);

/* and GT */
I915_WRITE(GTIMR, 0xffffffff);
I915_WRITE(GTIER, 0x0);
(void) I915_READ(GTIER);
}

static int igdng_irq_postinstall(struct drm_device *dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
/* enable kind of interrupts always enabled */
u32 display_mask = DE_MASTER_IRQ_CONTROL /*| DE_PCH_EVENT */;
u32 render_mask = GT_USER_INTERRUPT;

dev_priv->irq_mask_reg = ~display_mask;
dev_priv->de_irq_enable_reg = display_mask;

/* should always can generate irq */
I915_WRITE(DEIIR, I915_READ(DEIIR));
I915_WRITE(DEIMR, dev_priv->irq_mask_reg);
I915_WRITE(DEIER, dev_priv->de_irq_enable_reg);
(void) I915_READ(DEIER);

/* user interrupt should be enabled, but masked initial */
dev_priv->gt_irq_mask_reg = 0xffffffff;
dev_priv->gt_irq_enable_reg = render_mask;

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

return 0;
}

void i915_driver_irq_preinstall(struct drm_device * dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;

atomic_set(&dev_priv->irq_received, 0);

INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func);

if (IS_IGDNG(dev)) {
igdng_irq_preinstall(dev);
return;
}

if (I915_HAS_HOTPLUG(dev)) {
I915_WRITE(PORT_HOTPLUG_EN, 0);
I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
Expand All @@ -564,16 +716,20 @@ void i915_driver_irq_preinstall(struct drm_device * dev)
I915_WRITE(IMR, 0xffffffff);
I915_WRITE(IER, 0x0);
(void) I915_READ(IER);
INIT_WORK(&dev_priv->hotplug_work, i915_hotplug_work_func);
}

int i915_driver_irq_postinstall(struct drm_device *dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
u32 enable_mask = I915_INTERRUPT_ENABLE_FIX | I915_INTERRUPT_ENABLE_VAR;

DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);

dev_priv->vblank_pipe = DRM_I915_VBLANK_PIPE_A | DRM_I915_VBLANK_PIPE_B;

if (IS_IGDNG(dev))
return igdng_irq_postinstall(dev);

/* Unmask the interrupts that we always want on. */
dev_priv->irq_mask_reg = ~I915_INTERRUPT_ENABLE_FIX;

Expand Down Expand Up @@ -613,11 +769,24 @@ int i915_driver_irq_postinstall(struct drm_device *dev)
(void) I915_READ(IER);

opregion_enable_asle(dev);
DRM_INIT_WAITQUEUE(&dev_priv->irq_queue);

return 0;
}

static void igdng_irq_uninstall(struct drm_device *dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
I915_WRITE(HWSTAM, 0xffffffff);

I915_WRITE(DEIMR, 0xffffffff);
I915_WRITE(DEIER, 0x0);
I915_WRITE(DEIIR, I915_READ(DEIIR));

I915_WRITE(GTIMR, 0xffffffff);
I915_WRITE(GTIER, 0x0);
I915_WRITE(GTIIR, I915_READ(GTIIR));
}

void i915_driver_irq_uninstall(struct drm_device * dev)
{
drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
Expand All @@ -627,6 +796,11 @@ void i915_driver_irq_uninstall(struct drm_device * dev)

dev_priv->vblank_pipe = 0;

if (IS_IGDNG(dev)) {
igdng_irq_uninstall(dev);
return;
}

if (I915_HAS_HOTPLUG(dev)) {
I915_WRITE(PORT_HOTPLUG_EN, 0);
I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT));
Expand Down

0 comments on commit 52e2953

Please sign in to comment.