Exemplo n.º 1
0
irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
{
	struct drm_device *dev = (struct drm_device *) arg;
	drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
	int status;
	int handled = 0;

	status = MGA_READ(MGA_STATUS);

	/* VBLANK interrupt */
	if (status & MGA_VLINEPEN) {
		MGA_WRITE(MGA_ICLEAR, MGA_VLINEICLR);
		atomic_inc(&dev_priv->vbl_received);
		drm_handle_vblank(dev, 0);
		handled = 1;
	}

	/* SOFTRAP interrupt */
	if (status & MGA_SOFTRAPEN) {
		const u32 prim_start = MGA_READ(MGA_PRIMADDRESS);
		const u32 prim_end = MGA_READ(MGA_PRIMEND);


		MGA_WRITE(MGA_ICLEAR, MGA_SOFTRAPICLR);

		/* In addition to clearing the interrupt-pending bit, we
		 * have to write to MGA_PRIMEND to re-start the DMA operation.
		 */
<<<<<<< HEAD
		if ((prim_start & ~0x03) != (prim_end & ~0x03))
			MGA_WRITE(MGA_PRIMEND, prim_end);
=======
		if ((prim_start & ~0x03) != (prim_end & ~0x03)) {
Exemplo n.º 2
0
void mga_driver_irq_preinstall(struct drm_device * dev)
{
	drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;

	/* Disable *all* interrupts */
	MGA_WRITE(MGA_IEN, 0);
	/* Clear bits if they're already high */
	MGA_WRITE(MGA_ICLEAR, ~0);
}
Exemplo n.º 3
0
void mga_driver_irq_preinstall(struct drm_device *dev)
{
	drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;

	
	MGA_WRITE(MGA_IEN, 0);
	
	MGA_WRITE(MGA_ICLEAR, ~0);
}
Exemplo n.º 4
0
int mga_warp_init(drm_mga_private_t *dev_priv)
{
	u32 wmisc;

	/* FIXME: Get rid of these damned magic numbers...
	 */
	switch (dev_priv->chipset) {
	case MGA_CARD_TYPE_G400:
	case MGA_CARD_TYPE_G550:
		MGA_WRITE(MGA_WIADDR2, MGA_WMODE_SUSPEND);
		MGA_WRITE(MGA_WGETMSB, 0x00000E00);
		MGA_WRITE(MGA_WVRTXSZ, 0x00001807);
		MGA_WRITE(MGA_WACCEPTSEQ, 0x18000000);
		break;
	case MGA_CARD_TYPE_G200:
		MGA_WRITE(MGA_WIADDR, MGA_WMODE_SUSPEND);
		MGA_WRITE(MGA_WGETMSB, 0x1606);
		MGA_WRITE(MGA_WVRTXSZ, 7);
		break;
	default:
		return -EINVAL;
	}

	MGA_WRITE(MGA_WMISC, (MGA_WUCODECACHE_ENABLE |
			      MGA_WMASTER_ENABLE | MGA_WCACHEFLUSH_ENABLE));
	wmisc = MGA_READ(MGA_WMISC);
	if (wmisc != WMISC_EXPECTED) {
		DRM_ERROR("WARP engine config failed! 0x%x != 0x%x\n",
			  wmisc, WMISC_EXPECTED);
		return -EINVAL;
	}

	return 0;
}
Exemplo n.º 5
0
void mga_driver_irq_postinstall(drm_device_t * dev)
{
	drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;

	DRM_INIT_WAITQUEUE(&dev_priv->fence_queue);

	/* Turn on vertical blank interrupt and soft trap interrupt. */
	MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN);
}
Exemplo n.º 6
0
int mga_driver_irq_postinstall(struct drm_device *dev)
{
	drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;

	DRM_INIT_WAITQUEUE(&dev_priv->fence_queue);

	MGA_WRITE(MGA_IEN, MGA_SOFTRAPEN);
	return 0;
}
Exemplo n.º 7
0
irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
{
	drm_device_t *dev = (drm_device_t *) arg;
	drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
	int status;
	int handled = 0;

	status = MGA_READ(MGA_STATUS);

	/* VBLANK interrupt */
	if (status & MGA_VLINEPEN) {
		MGA_WRITE(MGA_ICLEAR, MGA_VLINEICLR);
		atomic_inc(&dev->vbl_received);
		DRM_WAKEUP(&dev->vbl_queue);
		drm_vbl_send_signals(dev);
		handled = 1;
	}

	/* SOFTRAP interrupt */
	if (status & MGA_SOFTRAPEN) {
		const u32 prim_start = MGA_READ(MGA_PRIMADDRESS);
		const u32 prim_end   = MGA_READ(MGA_PRIMEND);


		MGA_WRITE(MGA_ICLEAR, MGA_SOFTRAPICLR);

		/* In addition to clearing the interrupt-pending bit, we
		 * have to write to MGA_PRIMEND to re-start the DMA operation.
		 */
		if ( (prim_start & ~0x03) != (prim_end & ~0x03) ) {
			MGA_WRITE(MGA_PRIMEND, prim_end);
		}

		atomic_inc(&dev_priv->last_fence_retired);
		DRM_WAKEUP(&dev_priv->fence_queue);
		handled = 1;
	}

	if ( handled ) {
		return IRQ_HANDLED;
	}
	return IRQ_NONE;
}
Exemplo n.º 8
0
void mga_do_dma_flush( drm_mga_private_t *dev_priv )
{
	drm_mga_primary_buffer_t *primary = &dev_priv->prim;
	u32 head, tail;
	u32 status = 0;
	int i;
 	DMA_LOCALS;
	DRM_DEBUG( "\n" );

        /* We need to wait so that we can do an safe flush */
	for ( i = 0 ; i < dev_priv->usec_timeout ; i++ ) {
		status = MGA_READ( MGA_STATUS ) & MGA_ENGINE_IDLE_MASK;
		if ( status == MGA_ENDPRDMASTS ) break;
		udelay( 1 );
	}

	if ( primary->tail == primary->last_flush ) {
		DRM_DEBUG( "   bailing out...\n" );
		return;
	}

	tail = primary->tail + dev_priv->primary->offset;

	/* We need to pad the stream between flushes, as the card
	 * actually (partially?) reads the first of these commands.
	 * See page 4-16 in the G400 manual, middle of the page or so.
	 */
	BEGIN_DMA( 1 );

	DMA_BLOCK( MGA_DMAPAD,  0x00000000,
		   MGA_DMAPAD,  0x00000000,
		   MGA_DMAPAD,  0x00000000,
		   MGA_DMAPAD,	0x00000000 );

	ADVANCE_DMA();

	primary->last_flush = primary->tail;

	head = MGA_READ( MGA_PRIMADDRESS );

	if ( head <= tail ) {
		primary->space = primary->size - primary->tail;
	} else {
		primary->space = head - tail;
	}

	DRM_DEBUG( "   head = 0x%06lx\n", head - dev_priv->primary->offset );
	DRM_DEBUG( "   tail = 0x%06lx\n", tail - dev_priv->primary->offset );
	DRM_DEBUG( "  space = 0x%06x\n", primary->space );

	mga_flush_write_combine();
	MGA_WRITE( MGA_PRIMEND, tail | MGA_PAGPXFER );

	DRM_DEBUG( "done.\n" );
}
Exemplo n.º 9
0
void mga_driver_irq_uninstall(struct drm_device * dev)
{
	drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
	if (!dev_priv)
		return;

	/* Disable *all* interrupts */
	MGA_WRITE(MGA_IEN, 0);

	dev->irq_enabled = 0;
}
Exemplo n.º 10
0
int mga_driver_irq_postinstall(struct drm_device *dev)
{
	drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;

	DRM_INIT_WAITQUEUE(&dev_priv->fence_queue);

	/* Turn on soft trap interrupt.  Vertical blank interrupts are enabled
	 * in mga_enable_vblank.
	 */
	MGA_WRITE(MGA_IEN, MGA_SOFTRAPEN);
	return 0;
}
Exemplo n.º 11
0
int mga_enable_vblank(struct drm_device *dev, int crtc)
{
	drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;

	if (crtc != 0) {
		DRM_ERROR("tried to enable vblank on non-existent crtc %d\n",
			  crtc);
		return 0;
	}

	MGA_WRITE(MGA_IEN, MGA_VLINEIEN | MGA_SOFTRAPEN);
	return 0;
}
Exemplo n.º 12
0
irqreturn_t mga_driver_irq_handler(DRM_IRQ_ARGS)
{
	struct drm_device *dev = (struct drm_device *) arg;
	drm_mga_private_t *dev_priv = (drm_mga_private_t *) dev->dev_private;
	int status;
	int handled = 0;

	status = MGA_READ(MGA_STATUS);

	
	if (status & MGA_VLINEPEN) {
		MGA_WRITE(MGA_ICLEAR, MGA_VLINEICLR);
		atomic_inc(&dev_priv->vbl_received);
		drm_handle_vblank(dev, 0);
		handled = 1;
	}

	
	if (status & MGA_SOFTRAPEN) {
		const u32 prim_start = MGA_READ(MGA_PRIMADDRESS);
		const u32 prim_end = MGA_READ(MGA_PRIMEND);


		MGA_WRITE(MGA_ICLEAR, MGA_SOFTRAPICLR);

		if ((prim_start & ~0x03) != (prim_end & ~0x03))
			MGA_WRITE(MGA_PRIMEND, prim_end);

		atomic_inc(&dev_priv->last_fence_retired);
		DRM_WAKEUP(&dev_priv->fence_queue);
		handled = 1;
	}

	if (handled)
		return IRQ_HANDLED;
	return IRQ_NONE;
}
Exemplo n.º 13
0
int mga_do_engine_reset( drm_mga_private_t *dev_priv )
{
	DRM_DEBUG( "\n" );

	/* Okay, so we've completely screwed up and locked the engine.
	 * How about we clean up after ourselves?
	 */
	MGA_WRITE( MGA_RST, MGA_SOFTRESET );
	udelay( 15 );				/* Wait at least 10 usecs */
	MGA_WRITE( MGA_RST, 0 );

	/* Initialize the registers that get clobbered by the soft
	 * reset.  Many of the core register values survive a reset,
	 * but the drawing registers are basically all gone.
	 *
	 * 3D clients should probably die after calling this.  The X
	 * server should reset the engine state to known values.
	 */
#if 0
	MGA_WRITE( MGA_PRIMPTR,
		   virt_to_bus((void *)dev_priv->prim.status_page) |
		   MGA_PRIMPTREN0 |
		   MGA_PRIMPTREN1 );
#endif

	MGA_WRITE( MGA_ICLEAR, MGA_SOFTRAPICLR );
	MGA_WRITE( MGA_IEN,    MGA_SOFTRAPIEN );

	/* The primary DMA stream should look like new right about now.
	 */
	mga_do_dma_reset( dev_priv );

	/* This bad boy will never fail.
	 */
	return 0;
}
Exemplo n.º 14
0
void mga_do_dma_wrap_end( drm_mga_private_t *dev_priv )
{
	drm_mga_primary_buffer_t *primary = &dev_priv->prim;
	drm_mga_sarea_t *sarea_priv = dev_priv->sarea_priv;
	u32 head = dev_priv->primary->offset;
	DRM_DEBUG( "\n" );

	sarea_priv->last_wrap++;
	DRM_DEBUG( "   wrap = %d\n", sarea_priv->last_wrap );

	mga_flush_write_combine();
	MGA_WRITE( MGA_PRIMADDRESS, head | MGA_DMA_GENERAL );

	clear_bit( 0, &primary->wrapped );
	DRM_DEBUG( "done.\n" );
}
Exemplo n.º 15
0
void mga_do_dma_wrap_start( drm_mga_private_t *dev_priv )
{
	drm_mga_primary_buffer_t *primary = &dev_priv->prim;
	u32 head, tail;
	DMA_LOCALS;
	DRM_DEBUG( "\n" );

	BEGIN_DMA_WRAP();

	DMA_BLOCK( MGA_DMAPAD,	0x00000000,
		   MGA_DMAPAD,	0x00000000,
		   MGA_DMAPAD,	0x00000000,
		   MGA_DMAPAD,	0x00000000 );

	ADVANCE_DMA();

	tail = primary->tail + dev_priv->primary->offset;

	primary->tail = 0;
	primary->last_flush = 0;
	primary->last_wrap++;

	head = MGA_READ( MGA_PRIMADDRESS );

	if ( head == dev_priv->primary->offset ) {
		primary->space = primary->size;
	} else {
		primary->space = head - dev_priv->primary->offset;
	}

	DRM_DEBUG( "   head = 0x%06lx\n",
		  head - dev_priv->primary->offset );
	DRM_DEBUG( "   tail = 0x%06x\n", primary->tail );
	DRM_DEBUG( "   wrap = %d\n", primary->last_wrap );
	DRM_DEBUG( "  space = 0x%06x\n", primary->space );

	mga_flush_write_combine();
	MGA_WRITE( MGA_PRIMEND, tail | MGA_PAGPXFER );

	set_bit( 0, &primary->wrapped );
	DRM_DEBUG( "done.\n" );
}
Exemplo n.º 16
0
static int mga_do_init_dma( drm_device_t *dev, drm_mga_init_t *init )
{
	drm_mga_private_t *dev_priv;
	int ret;
	DRM_DEBUG( "\n" );

	dev_priv = DRM(alloc)( sizeof(drm_mga_private_t), DRM_MEM_DRIVER );
	if ( !dev_priv )
		return -ENOMEM;

	memset( dev_priv, 0, sizeof(drm_mga_private_t) );

	dev_priv->chipset = init->chipset;

	dev_priv->usec_timeout = MGA_DEFAULT_USEC_TIMEOUT;

	if ( init->sgram ) {
		dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_BLK;
	} else {
		dev_priv->clear_cmd = MGA_DWGCTL_CLEAR | MGA_ATYPE_RSTR;
	}
	dev_priv->maccess	= init->maccess;

	dev_priv->fb_cpp	= init->fb_cpp;
	dev_priv->front_offset	= init->front_offset;
	dev_priv->front_pitch	= init->front_pitch;
	dev_priv->back_offset	= init->back_offset;
	dev_priv->back_pitch	= init->back_pitch;

	dev_priv->depth_cpp	= init->depth_cpp;
	dev_priv->depth_offset	= init->depth_offset;
	dev_priv->depth_pitch	= init->depth_pitch;

	/* FIXME: Need to support AGP textures...
	 */
	dev_priv->texture_offset = init->texture_offset[0];
	dev_priv->texture_size = init->texture_size[0];

	DRM_GETSAREA();

	if(!dev_priv->sarea) {
		DRM_ERROR( "failed to find sarea!\n" );
		/* Assign dev_private so we can do cleanup. */
		dev->dev_private = (void *)dev_priv;
		mga_do_cleanup_dma( dev );
		return -EINVAL;
	}

	DRM_FIND_MAP( dev_priv->fb, init->fb_offset );
	if(!dev_priv->fb) {
		DRM_ERROR( "failed to find framebuffer!\n" );
		/* Assign dev_private so we can do cleanup. */
		dev->dev_private = (void *)dev_priv;
		mga_do_cleanup_dma( dev );
		return -EINVAL;
	}
	DRM_FIND_MAP( dev_priv->mmio, init->mmio_offset );
	if(!dev_priv->mmio) {
		DRM_ERROR( "failed to find mmio region!\n" );
		/* Assign dev_private so we can do cleanup. */
		dev->dev_private = (void *)dev_priv;
		mga_do_cleanup_dma( dev );
		return -EINVAL;
	}
	DRM_FIND_MAP( dev_priv->status, init->status_offset );
	if(!dev_priv->status) {
		DRM_ERROR( "failed to find status page!\n" );
		/* Assign dev_private so we can do cleanup. */
		dev->dev_private = (void *)dev_priv;
		mga_do_cleanup_dma( dev );
		return -EINVAL;
	}

	DRM_FIND_MAP( dev_priv->warp, init->warp_offset );
	if(!dev_priv->warp) {
		DRM_ERROR( "failed to find warp microcode region!\n" );
		/* Assign dev_private so we can do cleanup. */
		dev->dev_private = (void *)dev_priv;
		mga_do_cleanup_dma( dev );
		return -EINVAL;
	}
	DRM_FIND_MAP( dev_priv->primary, init->primary_offset );
	if(!dev_priv->primary) {
		DRM_ERROR( "failed to find primary dma region!\n" );
		/* Assign dev_private so we can do cleanup. */
		dev->dev_private = (void *)dev_priv;
		mga_do_cleanup_dma( dev );
		return -EINVAL;
	}
	DRM_FIND_MAP( dev_priv->buffers, init->buffers_offset );
	if(!dev_priv->buffers) {
		DRM_ERROR( "failed to find dma buffer region!\n" );
		/* Assign dev_private so we can do cleanup. */
		dev->dev_private = (void *)dev_priv;
		mga_do_cleanup_dma( dev );
		return -EINVAL;
	}

	dev_priv->sarea_priv =
		(drm_mga_sarea_t *)((u8 *)dev_priv->sarea->handle +
				    init->sarea_priv_offset);

	DRM_IOREMAP( dev_priv->warp, dev );
	DRM_IOREMAP( dev_priv->primary, dev );
	DRM_IOREMAP( dev_priv->buffers, dev );

	if(!dev_priv->warp->handle ||
	   !dev_priv->primary->handle ||
	   !dev_priv->buffers->handle ) {
		DRM_ERROR( "failed to ioremap agp regions!\n" );
		/* Assign dev_private so we can do cleanup. */
		dev->dev_private = (void *)dev_priv;
		mga_do_cleanup_dma( dev );
		return -ENOMEM;
	}

	ret = mga_warp_install_microcode( dev_priv );
	if ( ret < 0 ) {
		DRM_ERROR( "failed to install WARP ucode!\n" );
		/* Assign dev_private so we can do cleanup. */
		dev->dev_private = (void *)dev_priv;
		mga_do_cleanup_dma( dev );
		return ret;
	}

	ret = mga_warp_init( dev_priv );
	if ( ret < 0 ) {
		DRM_ERROR( "failed to init WARP engine!\n" );
		/* Assign dev_private so we can do cleanup. */
		dev->dev_private = (void *)dev_priv;
		mga_do_cleanup_dma( dev );
		return ret;
	}

	dev_priv->prim.status = (u32 *)dev_priv->status->handle;

	mga_do_wait_for_idle( dev_priv );

	/* Init the primary DMA registers.
	 */
	MGA_WRITE( MGA_PRIMADDRESS,
		   dev_priv->primary->offset | MGA_DMA_GENERAL );
#if 0
	MGA_WRITE( MGA_PRIMPTR,
		   virt_to_bus((void *)dev_priv->prim.status) |
		   MGA_PRIMPTREN0 |	/* Soft trap, SECEND, SETUPEND */
		   MGA_PRIMPTREN1 );	/* DWGSYNC */
#endif

	dev_priv->prim.start = (u8 *)dev_priv->primary->handle;
	dev_priv->prim.end = ((u8 *)dev_priv->primary->handle
			      + dev_priv->primary->size);
	dev_priv->prim.size = dev_priv->primary->size;

	dev_priv->prim.tail = 0;
	dev_priv->prim.space = dev_priv->prim.size;
	dev_priv->prim.wrapped = 0;

	dev_priv->prim.last_flush = 0;
	dev_priv->prim.last_wrap = 0;

	dev_priv->prim.high_mark = 256 * DMA_BLOCK_SIZE;

	dev_priv->prim.status[0] = dev_priv->primary->offset;
	dev_priv->prim.status[1] = 0;

	dev_priv->sarea_priv->last_wrap = 0;
	dev_priv->sarea_priv->last_frame.head = 0;
	dev_priv->sarea_priv->last_frame.wrap = 0;

	if ( mga_freelist_init( dev, dev_priv ) < 0 ) {
		DRM_ERROR( "could not initialize freelist\n" );
		/* Assign dev_private so we can do cleanup. */
		dev->dev_private = (void *)dev_priv;
		mga_do_cleanup_dma( dev );
		return -ENOMEM;
	}

	/* Make dev_private visable to others. */
	dev->dev_private = (void *)dev_priv;
	return 0;
}