From cd924de02927a091c517b0ac6b9cd8f065ce448c Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 7 Mar 2008 14:38:05 +1100 Subject: nouveau: don't touch NV_USER regs on channel destroy. Not only was this entirely pointless, it actually causes my NV30GL to die randomly when channels are destroyed. --- shared-core/nouveau_fifo.c | 7 ------- 1 file changed, 7 deletions(-) (limited to 'shared-core') diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index 056cb6d0..8e93207e 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -433,13 +433,6 @@ void nouveau_fifo_free(struct nouveau_channel *chan) NV_WRITE(NV03_PFIFO_CACHE1_PUSH0, 0x00000000); NV_WRITE(NV04_PFIFO_CACHE1_PULL0, 0x00000000); - /* stop the fifo, otherwise it could be running and - * it will crash when removing gpu objects - *XXX: from real-world evidence, absolutely useless.. - */ - NV_WRITE(chan->get, chan->pushbuf_base); - NV_WRITE(chan->put, chan->pushbuf_base); - // FIXME XXX needs more code engine->fifo.destroy_context(chan); -- cgit v1.2.3 From 1ccccbd4ce3463edb459eb193feb572938fce19e Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Fri, 7 Mar 2008 15:08:59 +1100 Subject: nouveau: redo channel idle detection Will hopefully work a bit better than previous code, which depended on knowing the channel's most recent PUT value. Some chips always return 0 on reading these regs, and currently userspace is the only other entity which knows the value. --- shared-core/nouveau_fifo.c | 43 +++++++++++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 14 deletions(-) (limited to 'shared-core') diff --git a/shared-core/nouveau_fifo.c b/shared-core/nouveau_fifo.c index 8e93207e..d8fda277 100644 --- a/shared-core/nouveau_fifo.c +++ b/shared-core/nouveau_fifo.c @@ -390,6 +390,34 @@ nouveau_fifo_alloc(struct drm_device *dev, struct nouveau_channel **chan_ret, return 0; } +static int +nouveau_channel_idle(struct nouveau_channel *chan) +{ + struct drm_device *dev = chan->dev; + struct drm_nouveau_private *dev_priv = dev->dev_private; + struct nouveau_engine *engine = &dev_priv->Engine; + uint32_t caches; + int idle; + + caches = NV_READ(NV03_PFIFO_CACHES); + NV_WRITE(NV03_PFIFO_CACHES, caches & ~1); + + if (engine->fifo.channel_id(dev) != chan->id) { + struct nouveau_gpuobj *ramfc = chan->ramfc->gpuobj; + + if (INSTANCE_RD(ramfc, 0) != INSTANCE_RD(ramfc, 1)) + idle = 0; + else + idle = 1; + } else { + idle = (NV_READ(NV04_PFIFO_CACHE1_DMA_GET) == + NV_READ(NV04_PFIFO_CACHE1_DMA_PUT)); + } + + NV_WRITE(NV03_PFIFO_CACHES, caches); + return idle; +} + /* stops a fifo */ void nouveau_fifo_free(struct nouveau_channel *chan) { @@ -400,22 +428,9 @@ void nouveau_fifo_free(struct nouveau_channel *chan) DRM_INFO("%s: freeing fifo %d\n", __func__, chan->id); - /* Disable channel switching, if this channel isn't currenly - * active re-enable it if there's still pending commands. - * We really should do a manual context switch here, but I'm - * not sure I trust our ability to do this reliably yet.. - */ - NV_WRITE(NV03_PFIFO_CACHES, 0); - if (engine->fifo.channel_id(dev) != chan->id && - NV_READ(chan->get) != NV_READ(chan->put)) { - NV_WRITE(NV03_PFIFO_CACHES, 1); - } - /* Give the channel a chance to idle, wait 2s (hopefully) */ t_start = engine->timer.read(dev); - while (NV_READ(chan->get) != NV_READ(chan->put) || - NV_READ(NV03_PFIFO_CACHE1_GET) != - NV_READ(NV03_PFIFO_CACHE1_PUT)) { + while (!nouveau_channel_idle(chan)) { if (engine->timer.read(dev) - t_start > 2000000000ULL) { DRM_ERROR("Failed to idle channel %d before destroy." "Prepare for strangeness..\n", chan->id); -- cgit v1.2.3 From ce3733572e4eea6d9adb167d8fccac745455445b Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Sat, 8 Mar 2008 08:30:03 +1000 Subject: drm/radeon: check sarea_priv exists --- shared-core/radeon_state.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'shared-core') diff --git a/shared-core/radeon_state.c b/shared-core/radeon_state.c index 70651d7f..8489549c 100644 --- a/shared-core/radeon_state.c +++ b/shared-core/radeon_state.c @@ -3126,12 +3126,14 @@ static int radeon_cp_setparam(struct drm_device *dev, void *data, struct drm_fil DRM_DEBUG("color tiling disabled\n"); dev_priv->front_pitch_offset &= ~RADEON_DST_TILE_MACRO; dev_priv->back_pitch_offset &= ~RADEON_DST_TILE_MACRO; - dev_priv->sarea_priv->tiling_enabled = 0; + if (dev_priv->sarea_priv) + dev_priv->sarea_priv->tiling_enabled = 0; } else if (sp->value == 1) { DRM_DEBUG("color tiling enabled\n"); dev_priv->front_pitch_offset |= RADEON_DST_TILE_MACRO; dev_priv->back_pitch_offset |= RADEON_DST_TILE_MACRO; - dev_priv->sarea_priv->tiling_enabled = 1; + if (dev_priv->sarea_priv) + dev_priv->sarea_priv->tiling_enabled = 1; } break; case RADEON_SETPARAM_PCIGART_LOCATION: -- cgit v1.2.3 From 2848f048616c2c97f02701386ee73137a1307e2c Mon Sep 17 00:00:00 2001 From: Keith Packard Date: Thu, 24 Jan 2008 11:46:45 -0800 Subject: Switch from PIPE_VBLANK to PIPE_EVENT interrupts. My 965GM gets interrupts stuck when using the old PIPE_VBLANK interrupt. Switch to the PIPE_EVENT interrupt mechanism, and set the PIPE*STAT registers to use START_VBLANK on 965 and VBLANK on previous chips. --- shared-core/i915_drv.h | 48 ++++++++++++++-- shared-core/i915_irq.c | 152 ++++++++++++++++++++++++++++++++----------------- 2 files changed, 141 insertions(+), 59 deletions(-) (limited to 'shared-core') diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index 4d3ac0a5..570fc4d3 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -466,10 +466,23 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); /* Interrupt bits: */ -#define USER_INT_FLAG (1<<1) -#define VSYNC_PIPEB_FLAG (1<<5) -#define VSYNC_PIPEA_FLAG (1<<7) -#define HWB_OOM_FLAG (1<<13) /* binner out of memory */ +#define I915_PIPE_CONTROL_NOTIFY_INTERRUPT (1<<18) +#define I915_DISPLAY_PORT_INTERRUPT (1<<17) +#define I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT (1<<15) +#define I915_GMCH_THERMAL_SENSOR_EVENT_INTERRUPT (1<<14) +#define I915_HWB_OOM_INTERRUPT (1<<13) /* binner out of memory */ +#define I915_SYNC_STATUS_INTERRUPT (1<<12) +#define I915_DISPLAY_PLANE_A_FLIP_PENDING_INTERRUPT (1<<11) +#define I915_DISPLAY_PLANE_B_FLIP_PENDING_INTERRUPT (1<<10) +#define I915_OVERLAY_PLANE_FLIP_PENDING_INTERRUPT (1<<9) +#define I915_DISPLAY_PLANE_C_FLIP_PENDING_INTERRUPT (1<<8) +#define I915_DISPLAY_PIPE_A_VBLANK_INTERRUPT (1<<7) +#define I915_DISPLAY_PIPE_A_EVENT_INTERRUPT (1<<6) +#define I915_DISPLAY_PIPE_B_VBLANK_INTERRUPT (1<<5) +#define I915_DISPLAY_PIPE_B_EVENT_INTERRUPT (1<<4) +#define I915_DEBUG_INTERRUPT (1<<2) +#define I915_USER_INTERRUPT (1<<1) + #define I915REG_HWSTAM 0x02098 #define I915REG_INT_IDENTITY_R 0x020a4 @@ -513,8 +526,31 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); #define PIPE_PIXEL_MASK 0x00ffffff #define PIPE_PIXEL_SHIFT 0 -#define I915_VBLANK_INTERRUPT_ENABLE (1UL<<17) -#define I915_VBLANK_CLEAR (1UL<<1) +#define I915_FIFO_UNDERRUN_STATUS (1UL<<31) +#define I915_CRC_ERROR_ENABLE (1UL<<29) +#define I915_CRC_DONE_ENABLE (1UL<<28) +#define I915_GMBUS_EVENT_ENABLE (1UL<<27) +#define I915_VSYNC_INTERRUPT_ENABLE (1UL<<25) +#define I915_DISPLAY_LINE_COMPARE_ENABLE (1UL<<24) +#define I915_DPST_EVENT_ENABLE (1UL<<23) +#define I915_LEGACY_BLC_EVENT_ENABLE (1UL<<22) +#define I915_ODD_FIELD_INTERRUPT_ENABLE (1UL<<21) +#define I915_EVEN_FIELD_INTERRUPT_ENABLE (1UL<<20) +#define I915_START_VBLANK_INTERRUPT_ENABLE (1UL<<18) /* 965 or later */ +#define I915_VBLANK_INTERRUPT_ENABLE (1UL<<17) +#define I915_OVERLAY_UPDATED_ENABLE (1UL<<16) +#define I915_CRC_ERROR_INTERRUPT_STATUS (1UL<<13) +#define I915_CRC_DONE_INTERRUPT_STATUS (1UL<<12) +#define I915_GMBUS_INTERRUPT_STATUS (1UL<<11) +#define I915_VSYNC_INTERRUPT_STATUS (1UL<<9) +#define I915_DISPLAY_LINE_COMPARE_STATUS (1UL<<8) +#define I915_DPST_EVENT_STATUS (1UL<<7) +#define I915_LEGACY_BLC_EVENT_STATUS (1UL<<6) +#define I915_ODD_FIELD_INTERRUPT_STATUS (1UL<<5) +#define I915_EVEN_FIELD_INTERRUPT_STATUS (1UL<<4) +#define I915_START_VBLANK_INTERRUPT_STATUS (1UL<<2) /* 965 or later */ +#define I915_VBLANK_INTERRUPT_STATUS (1UL<<1) +#define I915_OVERLAY_UPDATED_STATUS (1UL<<0) #define SRX_INDEX 0x3c4 #define SRX_DATA 0x3c5 diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c index 126f0379..a9b67a9c 100644 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@ -31,10 +31,6 @@ #include "i915_drm.h" #include "i915_drv.h" -#define USER_INT_FLAG (1<<1) -#define VSYNC_PIPEB_FLAG (1<<5) -#define VSYNC_PIPEA_FLAG (1<<7) - #define MAX_NOPID ((u32)~0) /** @@ -420,55 +416,63 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) { struct drm_device *dev = (struct drm_device *) arg; drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - u16 temp; + u32 iir; u32 pipea_stats, pipeb_stats; + int vblank = 0; - pipea_stats = I915_READ(I915REG_PIPEASTAT); - pipeb_stats = I915_READ(I915REG_PIPEBSTAT); - - temp = I915_READ16(I915REG_INT_IDENTITY_R); - + iir = I915_READ(I915REG_INT_IDENTITY_R); #if 0 - DRM_DEBUG("flag=%08x\n", temp); + DRM_DEBUG("flag=%08x\n", iir); #endif - if (temp == 0) + if (iir == 0) { + DRM_DEBUG ("iir 0x%08x im 0x%08x ie 0x%08x pipea 0x%08x pipeb 0x%08x\n", + iir, + I915_READ(I915REG_INT_MASK_R), + I915_READ(I915REG_INT_ENABLE_R), + I915_READ(I915REG_PIPEASTAT), + I915_READ(I915REG_PIPEBSTAT)); return IRQ_NONE; + } /* * Clear the PIPE(A|B)STAT regs before the IIR otherwise * we may get extra interrupts. */ - if (temp & VSYNC_PIPEA_FLAG) { - drm_handle_vblank(dev, i915_get_plane(dev, 0)); - I915_WRITE(I915REG_PIPEASTAT, - pipea_stats | I915_VBLANK_INTERRUPT_ENABLE | - I915_VBLANK_CLEAR); - } - if (temp & VSYNC_PIPEB_FLAG) { - drm_handle_vblank(dev, i915_get_plane(dev, 1)); - I915_WRITE(I915REG_PIPEBSTAT, - pipeb_stats | I915_VBLANK_INTERRUPT_ENABLE | - I915_VBLANK_CLEAR); + if (iir & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT) { + pipea_stats = I915_READ(I915REG_PIPEASTAT); + if (pipea_stats & (I915_START_VBLANK_INTERRUPT_STATUS| + I915_VBLANK_INTERRUPT_STATUS)) + { + vblank++; + drm_handle_vblank(dev, i915_get_plane(dev, 0)); + } + I915_WRITE(I915REG_PIPEASTAT, pipea_stats); + } + if (iir & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) { + pipeb_stats = I915_READ(I915REG_PIPEBSTAT); + if (pipeb_stats & (I915_START_VBLANK_INTERRUPT_STATUS| + I915_VBLANK_INTERRUPT_STATUS)) + { + vblank++; + drm_handle_vblank(dev, i915_get_plane(dev, 1)); + } + I915_WRITE(I915REG_PIPEBSTAT, pipeb_stats); } - I915_WRITE16(I915REG_INT_IDENTITY_R, temp); - (void) I915_READ16(I915REG_INT_IDENTITY_R); /* Flush posted write */ - - temp &= (dev_priv->irq_enable_reg | USER_INT_FLAG | VSYNC_PIPEA_FLAG | - VSYNC_PIPEB_FLAG); - if (dev_priv->sarea_priv) - dev_priv->sarea_priv->last_dispatch = - READ_BREADCRUMB(dev_priv); + dev_priv->sarea_priv->last_dispatch = READ_BREADCRUMB(dev_priv); + + I915_WRITE(I915REG_INT_IDENTITY_R, iir); + (void) I915_READ(I915REG_INT_IDENTITY_R); /* Flush posted write */ - if (temp & USER_INT_FLAG) { + if (iir & I915_USER_INTERRUPT) { DRM_WAKEUP(&dev_priv->irq_queue); #ifdef I915_HAVE_FENCE i915_fence_handler(dev); #endif } - if (temp & (VSYNC_PIPEA_FLAG | VSYNC_PIPEB_FLAG)) { + if (vblank) { if (dev_priv->swaps_pending > 0) drm_locked_tasklet(dev, i915_vblank_tasklet); } @@ -499,8 +503,8 @@ void i915_user_irq_on(drm_i915_private_t *dev_priv) { DRM_SPINLOCK(&dev_priv->user_irq_lock); if (dev_priv->irq_enabled && (++dev_priv->user_irq_refcount == 1)){ - dev_priv->irq_enable_reg |= USER_INT_FLAG; - I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg); + dev_priv->irq_enable_reg |= I915_USER_INTERRUPT; + I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg); } DRM_SPINUNLOCK(&dev_priv->user_irq_lock); @@ -511,7 +515,7 @@ void i915_user_irq_off(drm_i915_private_t *dev_priv) DRM_SPINLOCK(&dev_priv->user_irq_lock); if (dev_priv->irq_enabled && (--dev_priv->user_irq_refcount == 0)) { // dev_priv->irq_enable_reg &= ~USER_INT_FLAG; - // I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg); + // I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg); } DRM_SPINUNLOCK(&dev_priv->user_irq_lock); } @@ -590,13 +594,17 @@ int i915_enable_vblank(struct drm_device *dev, int plane) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; int pipe = i915_get_pipe(dev, plane); + u32 pipestat_reg = 0; + u32 pipestat; switch (pipe) { case 0: - dev_priv->irq_enable_reg |= VSYNC_PIPEA_FLAG; + pipestat_reg = I915REG_PIPEASTAT; + dev_priv->irq_enable_reg |= I915_DISPLAY_PIPE_A_EVENT_INTERRUPT; break; case 1: - dev_priv->irq_enable_reg |= VSYNC_PIPEB_FLAG; + pipestat_reg = I915REG_PIPEBSTAT; + dev_priv->irq_enable_reg |= I915_DISPLAY_PIPE_B_EVENT_INTERRUPT; break; default: DRM_ERROR("tried to enable vblank on non-existent pipe %d\n", @@ -604,7 +612,25 @@ int i915_enable_vblank(struct drm_device *dev, int plane) break; } - I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg); + if (pipestat_reg) + { + pipestat = I915_READ (pipestat_reg); + /* + * Older chips didn't have the start vblank interrupt, + * but + */ + if (IS_I965G (dev)) + pipestat |= I915_START_VBLANK_INTERRUPT_ENABLE; + else + pipestat |= I915_VBLANK_INTERRUPT_ENABLE; + /* + * Clear any pending status + */ + pipestat |= (I915_START_VBLANK_INTERRUPT_STATUS | + I915_VBLANK_INTERRUPT_STATUS); + I915_WRITE(pipestat_reg, pipestat); + } + I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg); return 0; } @@ -613,13 +639,17 @@ void i915_disable_vblank(struct drm_device *dev, int plane) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; int pipe = i915_get_pipe(dev, plane); + u32 pipestat_reg = 0; + u32 pipestat; switch (pipe) { case 0: - dev_priv->irq_enable_reg &= ~VSYNC_PIPEA_FLAG; + pipestat_reg = I915REG_PIPEASTAT; + dev_priv->irq_enable_reg &= ~I915_DISPLAY_PIPE_A_EVENT_INTERRUPT; break; case 1: - dev_priv->irq_enable_reg &= ~VSYNC_PIPEB_FLAG; + pipestat_reg = I915REG_PIPEBSTAT; + dev_priv->irq_enable_reg &= ~I915_DISPLAY_PIPE_B_EVENT_INTERRUPT; break; default: DRM_ERROR("tried to disable vblank on non-existent pipe %d\n", @@ -627,16 +657,28 @@ void i915_disable_vblank(struct drm_device *dev, int plane) break; } - I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg); + I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg); + if (pipestat_reg) + { + pipestat = I915_READ (pipestat_reg); + pipestat &= ~(I915_START_VBLANK_INTERRUPT_ENABLE | + I915_VBLANK_INTERRUPT_ENABLE); + /* + * Clear any pending status + */ + pipestat |= (I915_START_VBLANK_INTERRUPT_STATUS | + I915_VBLANK_INTERRUPT_STATUS); + I915_WRITE(pipestat_reg, pipestat); + } } static void i915_enable_interrupt (struct drm_device *dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - dev_priv->irq_enable_reg |= USER_INT_FLAG; + dev_priv->irq_enable_reg |= I915_USER_INTERRUPT; - I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg); + I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg); dev_priv->irq_enabled = 1; } @@ -677,9 +719,9 @@ int i915_vblank_pipe_get(struct drm_device *dev, void *data, flag = I915_READ(I915REG_INT_ENABLE_R); pipe->pipe = 0; - if (flag & VSYNC_PIPEA_FLAG) + if (flag & I915_DISPLAY_PIPE_A_EVENT_INTERRUPT) pipe->pipe |= DRM_I915_VBLANK_PIPE_A; - if (flag & VSYNC_PIPEB_FLAG) + if (flag & I915_DISPLAY_PIPE_B_EVENT_INTERRUPT) pipe->pipe |= DRM_I915_VBLANK_PIPE_B; return 0; @@ -883,16 +925,20 @@ int i915_driver_irq_postinstall(struct drm_device * dev) void i915_driver_irq_uninstall(struct drm_device * dev) { drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private; - u16 temp; + u32 temp; if (!dev_priv) return; dev_priv->irq_enabled = 0; - I915_WRITE16(I915REG_HWSTAM, 0xffff); - I915_WRITE16(I915REG_INT_MASK_R, 0xffff); - I915_WRITE16(I915REG_INT_ENABLE_R, 0x0); - - temp = I915_READ16(I915REG_INT_IDENTITY_R); - I915_WRITE16(I915REG_INT_IDENTITY_R, temp); + I915_WRITE(I915REG_HWSTAM, 0xffffffff); + I915_WRITE(I915REG_INT_MASK_R, 0xffffffff); + I915_WRITE(I915REG_INT_ENABLE_R, 0x0); + + temp = I915_READ(I915REG_PIPEASTAT); + I915_WRITE(I915REG_PIPEASTAT, temp); + temp = I915_READ(I915REG_PIPEBSTAT); + I915_WRITE(I915REG_PIPEBSTAT, temp); + temp = I915_READ(I915REG_INT_IDENTITY_R); + I915_WRITE(I915REG_INT_IDENTITY_R, temp); } -- cgit v1.2.3 From 52748d17923b7e501b707b950227864c0b64d8a1 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 11 Mar 2008 11:49:27 +1000 Subject: drm: hopefully fix cursors on 965 --- shared-core/i915_drv.h | 3 ++- shared-core/i915_init.c | 8 ++++++++ 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'shared-core') diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index f6c0005d..b8dfbc34 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -139,9 +139,10 @@ struct drm_i915_private { int fence_irq_on; uint32_t irq_enable_reg; int irq_enabled; - struct workqueue_struct *wq; + bool cursor_needs_physical; + #ifdef I915_HAVE_FENCE uint32_t flush_sequence; uint32_t flush_flags; diff --git a/shared-core/i915_init.c b/shared-core/i915_init.c index 3d8a1dca..274322e1 100644 --- a/shared-core/i915_init.c +++ b/shared-core/i915_init.c @@ -130,6 +130,14 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags) dev->types[8] = _DRM_STAT_SECONDARY; dev->types[9] = _DRM_STAT_DMA; + if (IS_MOBILE(dev) || IS_I9XX(dev)) + dev_priv->cursor_needs_physical = true; + else + dev_priv->cursor_needs_physical = false; + + if (IS_I965G(dev) || IS_G33(dev)) + dev_priv->cursor_needs_physical = false; + if (IS_I9XX(dev)) { pci_read_config_dword(dev->pdev, 0x5C, &dev_priv->stolen_base); DRM_DEBUG("stolen base %p\n", (void*)dev_priv->stolen_base); -- cgit v1.2.3 From 5a7f4b3074d5cda909fc7329bc91da11d89181e1 Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Tue, 11 Mar 2008 16:05:26 +1000 Subject: drm: fix oops on unload. if we are unloading the module, there is no master so therefore no lock --- shared-core/i915_init.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'shared-core') diff --git a/shared-core/i915_init.c b/shared-core/i915_init.c index 274322e1..fa2fc3da 100644 --- a/shared-core/i915_init.c +++ b/shared-core/i915_init.c @@ -277,7 +277,6 @@ int i915_driver_unload(struct drm_device *dev) I915_WRITE(LP_RING + RING_LEN, 0); - if (drm_core_check_feature(dev, DRIVER_MODESET)) { drm_irq_uninstall(dev); intel_modeset_cleanup(dev); @@ -291,7 +290,6 @@ int i915_driver_unload(struct drm_device *dev) if (dev_priv->sarea_kmap.virtual) { drm_bo_kunmap(&dev_priv->sarea_kmap); dev_priv->sarea_kmap.virtual = NULL; - dev->primary->master->lock.hw_lock = NULL; dev->sigdata.lock = NULL; } -- cgit v1.2.3 From f13936f7fc4d4932d5c511ccec29f1c4d24dc2dc Mon Sep 17 00:00:00 2001 From: Stuart Bennett Date: Tue, 11 Mar 2008 00:33:58 +0000 Subject: nouveau: move AGP reset to mem_init_agp Also, power cycle PGRAPH when resetting AGP -- it seems to fix problems encountered by p0g on nv25 --- shared-core/nouveau_mem.c | 28 ++++++++++++++++++++++++++++ shared-core/nv04_mc.c | 13 ------------- 2 files changed, 28 insertions(+), 13 deletions(-) (limited to 'shared-core') diff --git a/shared-core/nouveau_mem.c b/shared-core/nouveau_mem.c index 80b2990d..4e80ca46 100644 --- a/shared-core/nouveau_mem.c +++ b/shared-core/nouveau_mem.c @@ -300,6 +300,32 @@ uint64_t nouveau_mem_fb_amount(struct drm_device *dev) return 0; } +static void nouveau_mem_reset_agp(struct drm_device *dev) +{ + struct drm_nouveau_private *dev_priv = dev->dev_private; + uint32_t saved_pci_nv_1, saved_pci_nv_19, pmc_enable; + + saved_pci_nv_1 = NV_READ(NV04_PBUS_PCI_NV_1); + saved_pci_nv_19 = NV_READ(NV04_PBUS_PCI_NV_19); + + /* clear busmaster bit */ + NV_WRITE(NV04_PBUS_PCI_NV_1, saved_pci_nv_1 & ~0x4); + /* clear SBA and AGP bits */ + NV_WRITE(NV04_PBUS_PCI_NV_19, saved_pci_nv_19 & 0xfffff0ff); + + /* power cycle pgraph, if enabled */ + pmc_enable = NV_READ(NV03_PMC_ENABLE); + if (pmc_enable & NV_PMC_ENABLE_PGRAPH) { + NV_WRITE(NV03_PMC_ENABLE, pmc_enable & ~NV_PMC_ENABLE_PGRAPH); + NV_WRITE(NV03_PMC_ENABLE, NV_READ(NV03_PMC_ENABLE) | + NV_PMC_ENABLE_PGRAPH); + } + + /* and restore (gives effect of resetting AGP) */ + NV_WRITE(NV04_PBUS_PCI_NV_19, saved_pci_nv_19); + NV_WRITE(NV04_PBUS_PCI_NV_1, saved_pci_nv_1); +} + static int nouveau_mem_init_agp(struct drm_device *dev, int ttm) { @@ -308,6 +334,8 @@ nouveau_mem_init_agp(struct drm_device *dev, int ttm) struct drm_agp_mode mode; int ret; + nouveau_mem_reset_agp(dev); + ret = drm_agp_acquire(dev); if (ret) { DRM_ERROR("Unable to acquire AGP: %d\n", ret); diff --git a/shared-core/nv04_mc.c b/shared-core/nv04_mc.c index 766f3a33..24c1f7b3 100644 --- a/shared-core/nv04_mc.c +++ b/shared-core/nv04_mc.c @@ -7,25 +7,12 @@ int nv04_mc_init(struct drm_device *dev) { struct drm_nouveau_private *dev_priv = dev->dev_private; - uint32_t saved_pci_nv_1, saved_pci_nv_19; - - saved_pci_nv_1 = NV_READ(NV04_PBUS_PCI_NV_1); - saved_pci_nv_19 = NV_READ(NV04_PBUS_PCI_NV_19); - - /* clear busmaster bit */ - NV_WRITE(NV04_PBUS_PCI_NV_1, saved_pci_nv_1 & ~(0x00000001 << 2)); - /* clear SBA and AGP bits */ - NV_WRITE(NV04_PBUS_PCI_NV_19, saved_pci_nv_19 & 0xfffff0ff); /* Power up everything, resetting each individual unit will * be done later if needed. */ NV_WRITE(NV03_PMC_ENABLE, 0xFFFFFFFF); - /* and restore (gives effect of resetting AGP) */ - NV_WRITE(NV04_PBUS_PCI_NV_19, saved_pci_nv_19); - NV_WRITE(NV04_PBUS_PCI_NV_1, saved_pci_nv_1); - return 0; } -- cgit v1.2.3 From 903d9231d6f998657cc80ee6f20ded4df68e691b Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Tue, 11 Mar 2008 20:29:37 +0000 Subject: Add support for monitor hotplug signals/waits Also adjust i915 irq handling as it follows the 16bit'ism's of the i8xx series. --- shared-core/drm.h | 34 +++++++ shared-core/i915_drv.h | 17 ++-- shared-core/i915_irq.c | 246 +++++++++++++++++++++++++++++++------------------ 3 files changed, 202 insertions(+), 95 deletions(-) (limited to 'shared-core') diff --git a/shared-core/drm.h b/shared-core/drm.h index 303a84b6..a1ebfb93 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h @@ -555,6 +555,39 @@ union drm_wait_vblank { struct drm_wait_vblank_reply reply; }; +/* Handle monitor hotplug. + * + * May want to extend this later to pass reply information which + * details the outputs which generated the hotplug event. + * Some chipsets can't determine that though, and we'd need to leave + * it to the higher levels to determine exactly what changed. + */ +enum drm_hotplug_seq_type { + _DRM_HOTPLUG_SIGNAL = 0x00000001, /**< Send signal instead of blocking */ +}; + +struct drm_wait_hotplug_request { + enum drm_hotplug_seq_type type; + unsigned long signal; +}; + +struct drm_wait_hotplug_reply { + enum drm_hotplug_seq_type type; + unsigned int counter; + long tval_sec; + long tval_usec; +}; + +/** + * DRM_IOCTL_WAIT_HOTPLUG ioctl argument type. + * + * \sa drmWaitHotplug(). + */ +union drm_wait_hotplug { + struct drm_wait_hotplug_request request; + struct drm_wait_hotplug_reply reply; +}; + enum drm_modeset_ctl_cmd { _DRM_PRE_MODESET = 1, _DRM_POST_MODESET = 2, @@ -1238,6 +1271,7 @@ struct drm_mode_hotplug { #define DRM_IOCTL_MODE_GETPROPERTY DRM_IOWR(0xAB, struct drm_mode_get_property) #define DRM_IOCTL_MODE_CURSOR DRM_IOWR(0xAC, struct drm_mode_cursor) #define DRM_IOCTL_MODE_HOTPLUG DRM_IOWR(0xAD, struct drm_mode_hotplug) +#define DRM_IOCTL_WAIT_HOTPLUG DRM_IOWR(0xAE, union drm_wait_hotplug) /*@}*/ diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index b8dfbc34..fb855933 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -307,8 +307,8 @@ extern void i915_disable_vblank(struct drm_device *dev, int crtc); extern u32 i915_get_vblank_counter(struct drm_device *dev, int crtc); extern int i915_vblank_swap(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern void i915_user_irq_on(struct drm_i915_private *dev_priv); -extern void i915_user_irq_off(struct drm_i915_private *dev_priv); +extern void i915_user_irq_on(struct drm_device *dev); +extern void i915_user_irq_off(struct drm_device *dev); /* i915_mem.c */ extern int i915_mem_alloc(struct drm_device *dev, void *data, @@ -536,6 +536,12 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); #define I915REG_PIPEASTAT 0x70024 #define I915REG_PIPEBSTAT 0x71024 + +#define I915_VBLANK_INTERRUPT_ENABLE (1UL<<17) +#define I915_HOTPLUG_INTERRUPT_ENABLE (1UL<<26) +#define I915_HOTPLUG_CLEAR (1UL<<10) +#define I915_VBLANK_CLEAR (1UL<<1) + /* * The two pipe frame counter registers are not synchronized, so * reading a stable value is somewhat tricky. The following code @@ -567,9 +573,6 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); #define PIPE_PIXEL_MASK 0x00ffffff #define PIPE_PIXEL_SHIFT 0 -#define I915_VBLANK_INTERRUPT_ENABLE (1UL<<17) -#define I915_VBLANK_CLEAR (1UL<<1) - #define GPIOA 0x5010 #define GPIOB 0x5014 #define GPIOC 0x5018 @@ -1153,8 +1156,8 @@ extern int i915_wait_ring(struct drm_device * dev, int n, const char *caller); #define SDVOB_PCIE_CONCURRENCY (1 << 3) #define SDVO_DETECTED (1 << 2) /* Bits to be preserved when writing */ -#define SDVOB_PRESERVE_MASK ((1 << 17) | (1 << 16) | (1 << 14)) -#define SDVOC_PRESERVE_MASK (1 << 17) +#define SDVOB_PRESERVE_MASK ((1 << 17) | (1 << 16) | (1 << 14) | (1 << 26)) +#define SDVOC_PRESERVE_MASK ((1 << 17) | (1 << 26)) /** @defgroup LVDS * @{ diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c index b9d137f4..4127383a 100644 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@ -34,7 +34,9 @@ #include "intel_drv.h" #define USER_INT_FLAG (1<<1) +#define EVENT_PIPEB_FLAG (1<<4) #define VSYNC_PIPEB_FLAG (1<<5) +#define EVENT_PIPEA_FLAG (1<<6) #define VSYNC_PIPEA_FLAG (1<<7) #define HOTPLUG_FLAG (1 << 17) @@ -158,13 +160,14 @@ static void i915_vblank_tasklet(struct drm_device *dev) int nhits, nrects, slice[2], upper[2], lower[2], i, num_pages; unsigned counter[2]; struct drm_drawable_info *drw; - struct drm_i915_sarea *sarea_priv; + struct drm_i915_sarea *sarea_priv = master_priv->sarea_priv; u32 cpp = dev_priv->cpp, offsets[3]; u32 cmd = (cpp == 4) ? (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA | XY_SRC_COPY_BLT_WRITE_RGB) : XY_SRC_COPY_BLT_CMD; - u32 pitchropcpp; + u32 pitchropcpp = (sarea_priv->pitch * cpp) | (0xcc << 16) | + (cpp << 23) | (1 << 24); RING_LOCALS; counter[0] = drm_vblank_count(dev, 0); @@ -434,7 +437,7 @@ static struct drm_device *hotplug_dev; static int hotplug_cmd = 0; static spinlock_t hotplug_lock = SPIN_LOCK_UNLOCKED; -static void i915_hotplug_crt(struct drm_device *dev, bool connected) +static void i915_hotplug_crt(struct drm_device *dev, bool isconnected) { struct drm_output *output; struct intel_output *iout; @@ -453,7 +456,7 @@ static void i915_hotplug_crt(struct drm_device *dev, bool connected) if (iout == 0) goto unlock; - drm_hotplug_stage_two(dev, output, connected); + drm_hotplug_stage_two(dev, output, isconnected); unlock: mutex_unlock(&dev->mode_config.mutex); @@ -468,10 +471,8 @@ static void i915_hotplug_sdvo(struct drm_device *dev, int sdvoB) output = intel_sdvo_find(dev, sdvoB); - if (!output) { - DRM_ERROR("could not find sdvo%s output\n", sdvoB ? "B" : "C"); + if (!output) goto unlock; - } status = output->funcs->detect(output); @@ -480,7 +481,6 @@ static void i915_hotplug_sdvo(struct drm_device *dev, int sdvoB) else drm_hotplug_stage_two(dev, output, true); - /* wierd hw bug, sdvo stop sending interupts */ intel_sdvo_set_hotplug(output, 1); unlock: @@ -521,6 +521,7 @@ static void i915_hotplug_work_func(struct work_struct *work) if (sdvoC) i915_hotplug_sdvo(dev, 0); + drm_handle_hotplug(dev); } static int i915_run_hotplug_tasklet(struct drm_device *dev, uint32_t stat) @@ -575,45 +576,21 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) struct drm_i915_master_private *master_priv; struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; u32 temp = 0; - u32 temp2; u32 pipea_stats, pipeb_stats; - pipea_stats = I915_READ(I915REG_PIPEASTAT); - pipeb_stats = I915_READ(I915REG_PIPEBSTAT); - - /* On i8xx hw the IIR and IER are 16bit on i9xx its 32bit */ - if (IS_I9XX(dev)) + /* On i8xx/i915 hw the IIR and IER are 16bit on i9xx its 32bit */ + if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) temp = I915_READ(I915REG_INT_IDENTITY_R); else temp = I915_READ16(I915REG_INT_IDENTITY_R); - temp2 = temp; temp &= (dev_priv->irq_enable_reg | USER_INT_FLAG); -#if 0 - /* ugly despamification of pipeb event irq */ - if (temp & (0xFFFFFFF ^ ((1 << 5) | (1 << 7)))) { - DRM_DEBUG("IIR %08x\n", temp2); - DRM_DEBUG("MSK %08x\n", dev_priv->irq_enable_reg | USER_INT_FLAG); - DRM_DEBUG("M&I %08x\n", temp); - DRM_DEBUG("HOT %08x\n", I915_READ(PORT_HOTPLUG_STAT)); - } -#else -#if 0 - DRM_DEBUG("flag=%08x\n", temp); -#endif -#endif - if (temp == 0) return IRQ_NONE; - if (IS_I9XX(dev)) { - I915_WRITE(I915REG_INT_IDENTITY_R, temp); - (void) I915_READ(I915REG_INT_IDENTITY_R); - } else { - I915_WRITE16(I915REG_INT_IDENTITY_R, temp); - (void) I915_READ16(I915REG_INT_IDENTITY_R); - } + pipea_stats = I915_READ(I915REG_PIPEASTAT); + pipeb_stats = I915_READ(I915REG_PIPEBSTAT); /* * Clear the PIPE(A|B)STAT regs before the IIR otherwise @@ -621,25 +598,40 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) */ if (temp & VSYNC_PIPEA_FLAG) { drm_handle_vblank(dev, i915_get_plane(dev, 0)); - I915_WRITE(I915REG_PIPEASTAT, - pipea_stats | I915_VBLANK_INTERRUPT_ENABLE | - I915_VBLANK_CLEAR); + + pipea_stats |= I915_VBLANK_INTERRUPT_ENABLE | + I915_VBLANK_CLEAR; } if (temp & VSYNC_PIPEB_FLAG) { drm_handle_vblank(dev, i915_get_plane(dev, 1)); - I915_WRITE(I915REG_PIPEBSTAT, - pipeb_stats | I915_VBLANK_INTERRUPT_ENABLE | - I915_VBLANK_CLEAR); + + pipeb_stats |= I915_VBLANK_INTERRUPT_ENABLE | + I915_VBLANK_CLEAR; } - I915_WRITE16(I915REG_INT_IDENTITY_R, temp); - (void) I915_READ16(I915REG_INT_IDENTITY_R); /* Flush posted write */ + if (temp & EVENT_PIPEA_FLAG) + pipea_stats |= I915_HOTPLUG_INTERRUPT_ENABLE | + I915_HOTPLUG_CLEAR; - DRM_READMEMORYBARRIER(); + if (temp & EVENT_PIPEB_FLAG) + pipeb_stats |= I915_HOTPLUG_INTERRUPT_ENABLE | + I915_HOTPLUG_CLEAR; + + I915_WRITE(I915REG_PIPEASTAT, pipea_stats); + (void) I915_READ(I915REG_PIPEASTAT); + I915_WRITE(I915REG_PIPEBSTAT, pipeb_stats); + (void) I915_READ(I915REG_PIPEBSTAT); + + /* Clear the generated interrupt */ + if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) { + I915_WRITE(I915REG_INT_IDENTITY_R, temp); + (void) I915_READ(I915REG_INT_IDENTITY_R); + } else { + I915_WRITE16(I915REG_INT_IDENTITY_R, temp); + (void) I915_READ16(I915REG_INT_IDENTITY_R); + } - temp &= (dev_priv->irq_enable_reg | USER_INT_FLAG | VSYNC_PIPEA_FLAG | - VSYNC_PIPEB_FLAG); if (dev->primary->master) { master_priv = dev->primary->master->driver_priv; @@ -658,15 +650,43 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) drm_locked_tasklet(dev, i915_vblank_tasklet); } - /* for now lest just ack it */ - if (temp & (1 << 17)) { - DRM_DEBUG("Hotplug event received\n"); + if (temp & (HOTPLUG_FLAG | EVENT_PIPEA_FLAG | EVENT_PIPEB_FLAG)) { + u32 temp2 = 0; - temp2 = I915_READ(PORT_HOTPLUG_STAT); + DRM_INFO("Hotplug event received\n"); - i915_run_hotplug_tasklet(dev, temp2); + if (!IS_I9XX(dev) || IS_I915G(dev) || IS_I915GM(dev)) { +#if 0 + u32 b,c; + + b = I915_READ(SDVOB) & SDVO_PIPE_B_SELECT; + c = I915_READ(SDVOC) & SDVO_PIPE_B_SELECT; + + if (temp & EVENT_PIPEA_FLAG) { + if (!b) + temp2 |= SDVOB_HOTPLUG_INT_STATUS; + if (!c) + temp2 |= SDVOC_HOTPLUG_INT_STATUS; + + } + + if (temp & EVENT_PIPEB_FLAG) { + if (b) + temp2 |= SDVOB_HOTPLUG_INT_STATUS; + if (c) + temp2 |= SDVOC_HOTPLUG_INT_STATUS; + + } +#else + temp2 |= SDVOB_HOTPLUG_INT_STATUS | + SDVOC_HOTPLUG_INT_STATUS; +#endif + } else { + temp2 = I915_READ(PORT_HOTPLUG_STAT); - I915_WRITE(PORT_HOTPLUG_STAT,temp2); + I915_WRITE(PORT_HOTPLUG_STAT, temp2); + } + i915_run_hotplug_tasklet(dev, temp2); } return IRQ_HANDLED; @@ -691,23 +711,33 @@ int i915_emit_irq(struct drm_device *dev) return dev_priv->counter; } -void i915_user_irq_on(struct drm_i915_private *dev_priv) +void i915_user_irq_on(struct drm_device *dev) { + struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; + DRM_SPINLOCK(&dev_priv->user_irq_lock); if (dev_priv->irq_enabled && (++dev_priv->user_irq_refcount == 1)){ dev_priv->irq_enable_reg |= USER_INT_FLAG; - I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg); + if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) + I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg); + else + I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg); } DRM_SPINUNLOCK(&dev_priv->user_irq_lock); } -void i915_user_irq_off(struct drm_i915_private *dev_priv) +void i915_user_irq_off(struct drm_device *dev) { + struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; + DRM_SPINLOCK(&dev_priv->user_irq_lock); if (dev_priv->irq_enabled && (--dev_priv->user_irq_refcount == 0)) { // dev_priv->irq_enable_reg &= ~USER_INT_FLAG; - // I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg); + // if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) + // I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg); + // else + // I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg); } DRM_SPINUNLOCK(&dev_priv->user_irq_lock); } @@ -725,10 +755,10 @@ static int i915_wait_irq(struct drm_device * dev, int irq_nr) if (READ_BREADCRUMB(dev_priv) >= irq_nr) return 0; - i915_user_irq_on(dev_priv); + i915_user_irq_on(dev); DRM_WAIT_ON(ret, dev_priv->irq_queue, 3 * DRM_HZ, READ_BREADCRUMB(dev_priv) >= irq_nr); - i915_user_irq_off(dev_priv); + i915_user_irq_off(dev); if (ret == -EBUSY) { DRM_ERROR("EBUSY -- rec: %d emitted: %d\n", @@ -803,7 +833,10 @@ int i915_enable_vblank(struct drm_device *dev, int plane) break; } - I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg); + if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) + I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg); + else + I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg); return 0; } @@ -826,7 +859,10 @@ void i915_disable_vblank(struct drm_device *dev, int plane) break; } - I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg); + if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) + I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg); + else + I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg); } void i915_enable_interrupt (struct drm_device *dev) @@ -836,40 +872,62 @@ void i915_enable_interrupt (struct drm_device *dev) dev_priv->irq_enable_reg |= USER_INT_FLAG; - if (IS_I9XX(dev) && dev->mode_config.num_output) { - dev_priv->irq_enable_reg |= HOTPLUG_FLAG; + if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) { + if (dev->mode_config.num_output) + dev_priv->irq_enable_reg |= HOTPLUG_FLAG; + } else { + if (dev->mode_config.num_output) + dev_priv->irq_enable_reg |= EVENT_PIPEA_FLAG | EVENT_PIPEB_FLAG; + + I915_WRITE(I915REG_PIPEASTAT, I915_READ(I915REG_PIPEASTAT) | I915_HOTPLUG_INTERRUPT_ENABLE | I915_HOTPLUG_CLEAR); + I915_WRITE(I915REG_PIPEBSTAT, I915_READ(I915REG_PIPEBSTAT) | I915_HOTPLUG_INTERRUPT_ENABLE | I915_HOTPLUG_CLEAR); + } + + if (dev_priv->irq_enable_reg & (HOTPLUG_FLAG | EVENT_PIPEA_FLAG | EVENT_PIPEB_FLAG)) { + u32 temp = 0; - /* Activate the CRT */ - I915_WRITE(PORT_HOTPLUG_EN, CRT_HOTPLUG_INT_EN); + if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) { + temp = I915_READ(PORT_HOTPLUG_EN); - /* SDVOB */ - o = intel_sdvo_find(dev, 1); - if (o && intel_sdvo_supports_hotplug(o)) { - intel_sdvo_set_hotplug(o, 1); - I915_WRITE(PORT_HOTPLUG_EN, SDVOB_HOTPLUG_INT_EN); + /* Activate the CRT */ + temp |= CRT_HOTPLUG_INT_EN; } - /* SDVOC */ - o = intel_sdvo_find(dev, 0); - if (o && intel_sdvo_supports_hotplug(o)) { - intel_sdvo_set_hotplug(o, 1); - I915_WRITE(PORT_HOTPLUG_EN, SDVOC_HOTPLUG_INT_EN); + if (IS_I9XX(dev)) { + /* SDVOB */ + o = intel_sdvo_find(dev, 1); + if (o && intel_sdvo_supports_hotplug(o)) { + intel_sdvo_set_hotplug(o, 1); + temp |= SDVOB_HOTPLUG_INT_EN; + } + + /* SDVOC */ + o = intel_sdvo_find(dev, 0); + if (o && intel_sdvo_supports_hotplug(o)) { + intel_sdvo_set_hotplug(o, 1); + temp |= SDVOC_HOTPLUG_INT_EN; + } + + I915_WRITE(SDVOB, I915_READ(SDVOB) | SDVO_INTERRUPT_ENABLE); + I915_WRITE(SDVOC, I915_READ(SDVOC) | SDVO_INTERRUPT_ENABLE); + } else { + /* DVO ???? */ } + if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) { + I915_WRITE(PORT_HOTPLUG_EN, temp); + + DRM_DEBUG("HEN %08x\n",I915_READ(PORT_HOTPLUG_EN)); + DRM_DEBUG("HST %08x\n",I915_READ(PORT_HOTPLUG_STAT)); + + I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); + } } - if (IS_I9XX(dev)) { + if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) I915_WRITE(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg); - } else { + else I915_WRITE16(I915REG_INT_ENABLE_R, dev_priv->irq_enable_reg); - } - - DRM_DEBUG("HEN %08x\n",I915_READ(PORT_HOTPLUG_EN)); - DRM_DEBUG("HST %08x\n",I915_READ(PORT_HOTPLUG_STAT)); - DRM_DEBUG("IER %08x\n",I915_READ(I915REG_INT_ENABLE_R)); - DRM_DEBUG("SDB %08x\n",I915_READ(SDVOB)); - - I915_WRITE(PORT_HOTPLUG_STAT, I915_READ(PORT_HOTPLUG_STAT)); dev_priv->irq_enabled = 1; } @@ -909,7 +967,11 @@ int i915_vblank_pipe_get(struct drm_device *dev, void *data, return -EINVAL; } - flag = I915_READ(I915REG_INT_ENABLE_R); + if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) + flag = I915_READ(I915REG_INT_ENABLE_R); + else + flag = I915_READ16(I915REG_INT_ENABLE_R); + pipe->pipe = 0; if (flag & VSYNC_PIPEA_FLAG) pipe->pipe |= DRM_I915_VBLANK_PIPE_A; @@ -1086,8 +1148,10 @@ void i915_driver_irq_preinstall(struct drm_device * dev) { struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; + I915_WRITE(I915REG_PIPEASTAT, 0xffff); + I915_WRITE(I915REG_PIPEBSTAT, 0xffff); I915_WRITE16(I915REG_HWSTAM, 0xeffe); - if (IS_I9XX(dev)) { + if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) { I915_WRITE(I915REG_INT_MASK_R, 0x0); I915_WRITE(I915REG_INT_ENABLE_R, 0x0); } else { @@ -1114,6 +1178,10 @@ int i915_driver_irq_postinstall(struct drm_device * dev) if (ret) return ret; + ret = drm_hotplug_init(dev); + if (ret) + return ret; + dev->max_vblank_count = 0xffffff; /* only 24 bits of frame count */ i915_enable_interrupt(dev); @@ -1138,7 +1206,9 @@ void i915_driver_irq_uninstall(struct drm_device * dev) dev_priv->irq_enabled = 0; - if(IS_I9XX(dev)) { + I915_WRITE(I915REG_PIPEASTAT, 0xffff); + I915_WRITE(I915REG_PIPEBSTAT, 0xffff); + if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) { I915_WRITE(I915REG_HWSTAM, 0xffffffff); I915_WRITE(I915REG_INT_MASK_R, 0xffffffff); I915_WRITE(I915REG_INT_ENABLE_R, 0x0); -- cgit v1.2.3 From cf1a2499ed9a0051bcd8627136fb53b496b6484c Mon Sep 17 00:00:00 2001 From: Alan Hourihane Date: Tue, 11 Mar 2008 21:24:29 +0000 Subject: global hotplug events happen in the pipe A stat register, they are not pipe A specific. Remove pipe B code. --- shared-core/i915_irq.c | 38 +++++++++----------------------------- 1 file changed, 9 insertions(+), 29 deletions(-) (limited to 'shared-core') diff --git a/shared-core/i915_irq.c b/shared-core/i915_irq.c index 4127383a..558693f1 100644 --- a/shared-core/i915_irq.c +++ b/shared-core/i915_irq.c @@ -577,6 +577,7 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) struct drm_i915_private *dev_priv = (struct drm_i915_private *) dev->dev_private; u32 temp = 0; u32 pipea_stats, pipeb_stats; + int hotplug = 0; /* On i8xx/i915 hw the IIR and IER are 16bit on i9xx its 32bit */ if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) @@ -610,13 +611,15 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) I915_VBLANK_CLEAR; } - if (temp & EVENT_PIPEA_FLAG) + /* This is a global event, and not a pipe A event */ + if (temp & EVENT_PIPEA_FLAG) { + if (pipea_stats & I915_HOTPLUG_CLEAR) + hotplug = 1; + pipea_stats |= I915_HOTPLUG_INTERRUPT_ENABLE | I915_HOTPLUG_CLEAR; - if (temp & EVENT_PIPEB_FLAG) - pipeb_stats |= I915_HOTPLUG_INTERRUPT_ENABLE | - I915_HOTPLUG_CLEAR; + } I915_WRITE(I915REG_PIPEASTAT, pipea_stats); (void) I915_READ(I915REG_PIPEASTAT); @@ -650,37 +653,14 @@ irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS) drm_locked_tasklet(dev, i915_vblank_tasklet); } - if (temp & (HOTPLUG_FLAG | EVENT_PIPEA_FLAG | EVENT_PIPEB_FLAG)) { + if ((temp & HOTPLUG_FLAG) || hotplug) { u32 temp2 = 0; DRM_INFO("Hotplug event received\n"); if (!IS_I9XX(dev) || IS_I915G(dev) || IS_I915GM(dev)) { -#if 0 - u32 b,c; - - b = I915_READ(SDVOB) & SDVO_PIPE_B_SELECT; - c = I915_READ(SDVOC) & SDVO_PIPE_B_SELECT; - - if (temp & EVENT_PIPEA_FLAG) { - if (!b) - temp2 |= SDVOB_HOTPLUG_INT_STATUS; - if (!c) - temp2 |= SDVOC_HOTPLUG_INT_STATUS; - - } - - if (temp & EVENT_PIPEB_FLAG) { - if (b) - temp2 |= SDVOB_HOTPLUG_INT_STATUS; - if (c) - temp2 |= SDVOC_HOTPLUG_INT_STATUS; - - } -#else temp2 |= SDVOB_HOTPLUG_INT_STATUS | SDVOC_HOTPLUG_INT_STATUS; -#endif } else { temp2 = I915_READ(PORT_HOTPLUG_STAT); @@ -879,8 +859,8 @@ void i915_enable_interrupt (struct drm_device *dev) if (dev->mode_config.num_output) dev_priv->irq_enable_reg |= EVENT_PIPEA_FLAG | EVENT_PIPEB_FLAG; + /* Enable global interrupts for hotplug - not a pipeA event */ I915_WRITE(I915REG_PIPEASTAT, I915_READ(I915REG_PIPEASTAT) | I915_HOTPLUG_INTERRUPT_ENABLE | I915_HOTPLUG_CLEAR); - I915_WRITE(I915REG_PIPEBSTAT, I915_READ(I915REG_PIPEBSTAT) | I915_HOTPLUG_INTERRUPT_ENABLE | I915_HOTPLUG_CLEAR); } if (dev_priv->irq_enable_reg & (HOTPLUG_FLAG | EVENT_PIPEA_FLAG | EVENT_PIPEB_FLAG)) { -- cgit v1.2.3 From 8a18d123f55a7fb11ce333f0b1095020918b8616 Mon Sep 17 00:00:00 2001 From: Thomas Hellstrom Date: Thu, 28 Feb 2008 09:08:52 +0100 Subject: Avoid large kmallocs. --- shared-core/i915_dma.c | 28 +++++++++++++++++----------- shared-core/i915_drv.h | 2 ++ 2 files changed, 19 insertions(+), 11 deletions(-) (limited to 'shared-core') diff --git a/shared-core/i915_dma.c b/shared-core/i915_dma.c index 7d247f9c..f6df74a7 100644 --- a/shared-core/i915_dma.c +++ b/shared-core/i915_dma.c @@ -1181,7 +1181,6 @@ static int i915_handle_copyback(struct drm_device *dev, buffers++; } } - return err; } @@ -1272,7 +1271,6 @@ static int i915_execbuffer(struct drm_device *dev, void *data, struct drm_fence_arg *fence_arg = &exec_buf->fence_arg; int num_buffers; int ret; - struct drm_i915_validate_buffer *buffers; if (!dev_priv->allow_batchbuffer) { DRM_ERROR("Batchbuffer ioctl disabled\n"); @@ -1288,7 +1286,6 @@ static int i915_execbuffer(struct drm_device *dev, void *data, if (exec_buf->num_buffers > dev_priv->max_validate_buffers) return -EINVAL; - ret = drm_bo_read_lock(&dev->bm.bm_lock); if (ret) return ret; @@ -1306,8 +1303,12 @@ static int i915_execbuffer(struct drm_device *dev, void *data, num_buffers = exec_buf->num_buffers; - buffers = drm_calloc(num_buffers, sizeof(struct drm_i915_validate_buffer), DRM_MEM_DRIVER); - if (!buffers) { + if (!dev_priv->val_bufs) { + dev_priv->val_bufs = + vmalloc(sizeof(struct drm_i915_validate_buffer)* + dev_priv->max_validate_buffers); + } + if (!dev_priv->val_bufs) { drm_bo_read_unlock(&dev->bm.bm_lock); mutex_unlock(&dev_priv->cmdbuf_mutex); return -ENOMEM; @@ -1315,7 +1316,7 @@ static int i915_execbuffer(struct drm_device *dev, void *data, /* validate buffer list + fixup relocations */ ret = i915_validate_buffer_list(file_priv, 0, exec_buf->ops_list, - buffers, &num_buffers); + dev_priv->val_bufs, &num_buffers); if (ret) goto out_err0; @@ -1324,7 +1325,7 @@ static int i915_execbuffer(struct drm_device *dev, void *data, drm_agp_chipset_flush(dev); /* submit buffer */ - batch->start = buffers[num_buffers-1].buffer->offset; + batch->start = dev_priv->val_bufs[num_buffers-1].buffer->offset; DRM_DEBUG("i915 exec batchbuffer, start %x used %d cliprects %d\n", batch->start, batch->used, batch->num_cliprects); @@ -1341,13 +1342,11 @@ static int i915_execbuffer(struct drm_device *dev, void *data, out_err0: /* handle errors */ - ret = i915_handle_copyback(dev, buffers, num_buffers, ret); + ret = i915_handle_copyback(dev, dev_priv->val_bufs, num_buffers, ret); mutex_lock(&dev->struct_mutex); - i915_dereference_buffers_locked(buffers, num_buffers); + i915_dereference_buffers_locked(dev_priv->val_bufs, num_buffers); mutex_unlock(&dev->struct_mutex); - drm_free(buffers, (exec_buf->num_buffers * sizeof(struct drm_buffer_object *)), DRM_MEM_DRIVER); - mutex_unlock(&dev_priv->cmdbuf_mutex); drm_bo_read_unlock(&dev->bm.bm_lock); return ret; @@ -1618,6 +1617,13 @@ void i915_driver_lastclose(struct drm_device * dev) { drm_i915_private_t *dev_priv = dev->dev_private; +#ifdef I915_HAVE_BUFFER + if (dev_priv->val_bufs) { + vfree(dev_priv->val_bufs); + dev_priv->val_bufs = NULL; + } +#endif + if (drm_getsarea(dev) && dev_priv->sarea_priv) i915_do_cleanup_pageflip(dev); if (dev_priv->agp_heap) diff --git a/shared-core/i915_drv.h b/shared-core/i915_drv.h index 570fc4d3..3bc39e2a 100644 --- a/shared-core/i915_drv.h +++ b/shared-core/i915_drv.h @@ -69,6 +69,7 @@ #ifdef I915_HAVE_BUFFER #define I915_MAX_VALIDATE_BUFFERS 4096 +struct drm_i915_validate_buffer; #endif typedef struct _drm_i915_ring_buffer { @@ -141,6 +142,7 @@ typedef struct drm_i915_private { void *agp_iomap; unsigned int max_validate_buffers; struct mutex cmdbuf_mutex; + struct drm_i915_validate_buffer *val_bufs; #endif DRM_SPINTYPE swaps_lock; -- cgit v1.2.3 From 2d0411cb7544ea45b5879d4f454cb9ee3c9ff5fb Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 17 Mar 2008 16:34:15 +1000 Subject: i915: safety check the sarea map still exists --- shared-core/i915_init.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'shared-core') diff --git a/shared-core/i915_init.c b/shared-core/i915_init.c index fa2fc3da..a76acb4e 100644 --- a/shared-core/i915_init.c +++ b/shared-core/i915_init.c @@ -383,7 +383,9 @@ void i915_master_destroy(struct drm_device *dev, struct drm_master *master) if (!master_priv) return; - drm_rmmap(dev, master_priv->sarea); + if (master_priv->sarea) + drm_rmmap(dev, master_priv->sarea); + drm_free(master_priv, sizeof(*master_priv), DRM_MEM_DRIVER); master->driver_priv = NULL; -- cgit v1.2.3 From 607964ed9e5f6d86a0960bef2341e7f5de9c71da Mon Sep 17 00:00:00 2001 From: Dave Airlie Date: Mon, 17 Mar 2008 16:37:46 +1000 Subject: drm: add master set/drop protocol this may not survive long - just need something for testing --- shared-core/drm.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'shared-core') diff --git a/shared-core/drm.h b/shared-core/drm.h index a1ebfb93..a72263ae 100644 --- a/shared-core/drm.h +++ b/shared-core/drm.h @@ -1200,6 +1200,9 @@ struct drm_mode_hotplug { #define DRM_IOCTL_SET_SAREA_CTX DRM_IOW( 0x1c, struct drm_ctx_priv_map) #define DRM_IOCTL_GET_SAREA_CTX DRM_IOWR(0x1d, struct drm_ctx_priv_map) +#define DRM_IOCTL_SET_MASTER DRM_IO(0x1e) +#define DRM_IOCTL_DROP_MASTER DRM_IO(0x1f) + #define DRM_IOCTL_ADD_CTX DRM_IOWR(0x20, struct drm_ctx) #define DRM_IOCTL_RM_CTX DRM_IOWR(0x21, struct drm_ctx) #define DRM_IOCTL_MOD_CTX DRM_IOW( 0x22, struct drm_ctx) -- cgit v1.2.3