⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 radeon_cp.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 4 页
字号:
	RADEON_READ(RADEON_RBBM_SOFT_RESET);	RADEON_WRITE(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset &					      ~(RADEON_SOFT_RESET_CP |						RADEON_SOFT_RESET_HI |						RADEON_SOFT_RESET_SE |						RADEON_SOFT_RESET_RE |						RADEON_SOFT_RESET_PP |						RADEON_SOFT_RESET_E2 |						RADEON_SOFT_RESET_RB)));	RADEON_READ(RADEON_RBBM_SOFT_RESET);	RADEON_WRITE_PLL(RADEON_MCLK_CNTL, mclk_cntl);	RADEON_WRITE(RADEON_CLOCK_CNTL_INDEX, clock_cntl_index);	RADEON_WRITE(RADEON_RBBM_SOFT_RESET, rbbm_soft_reset);	/* Reset the CP ring */	radeon_do_cp_reset(dev_priv);	/* The CP is no longer running after an engine reset */	dev_priv->cp_running = 0;	/* Reset any pending vertex, indirect buffers */	radeon_freelist_reset(dev);	return 0;}static void radeon_cp_init_ring_buffer(drm_device_t * dev,				       drm_radeon_private_t * dev_priv){	u32 ring_start, cur_read_ptr;	u32 tmp;	/* Initialize the memory controller */	RADEON_WRITE(RADEON_MC_FB_LOCATION,		     ((dev_priv->gart_vm_start - 1) & 0xffff0000)		     | (dev_priv->fb_location >> 16));#if __OS_HAS_AGP	if (!dev_priv->is_pci) {		RADEON_WRITE(RADEON_MC_AGP_LOCATION,			     (((dev_priv->gart_vm_start - 1 +				dev_priv->gart_size) & 0xffff0000) |			      (dev_priv->gart_vm_start >> 16)));		ring_start = (dev_priv->cp_ring->offset			      - dev->agp->base			      + dev_priv->gart_vm_start);	} else#endif		ring_start = (dev_priv->cp_ring->offset			      - (unsigned long)dev->sg->virtual			      + dev_priv->gart_vm_start);	RADEON_WRITE(RADEON_CP_RB_BASE, ring_start);	/* Set the write pointer delay */	RADEON_WRITE(RADEON_CP_RB_WPTR_DELAY, 0);	/* Initialize the ring buffer's read and write pointers */	cur_read_ptr = RADEON_READ(RADEON_CP_RB_RPTR);	RADEON_WRITE(RADEON_CP_RB_WPTR, cur_read_ptr);	SET_RING_HEAD(dev_priv, cur_read_ptr);	dev_priv->ring.tail = cur_read_ptr;#if __OS_HAS_AGP	if (!dev_priv->is_pci) {		/* set RADEON_AGP_BASE here instead of relying on X from user space */		RADEON_WRITE(RADEON_AGP_BASE, (unsigned int)dev->agp->base);		RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR,			     dev_priv->ring_rptr->offset			     - dev->agp->base + dev_priv->gart_vm_start);	} else#endif	{		drm_sg_mem_t *entry = dev->sg;		unsigned long tmp_ofs, page_ofs;		tmp_ofs = dev_priv->ring_rptr->offset -				(unsigned long)dev->sg->virtual;		page_ofs = tmp_ofs >> PAGE_SHIFT;		RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR, entry->busaddr[page_ofs]);		DRM_DEBUG("ring rptr: offset=0x%08lx handle=0x%08lx\n",			  (unsigned long)entry->busaddr[page_ofs],			  entry->handle + tmp_ofs);	}	/* Initialize the scratch register pointer.  This will cause	 * the scratch register values to be written out to memory	 * whenever they are updated.	 *	 * We simply put this behind the ring read pointer, this works	 * with PCI GART as well as (whatever kind of) AGP GART	 */	RADEON_WRITE(RADEON_SCRATCH_ADDR, RADEON_READ(RADEON_CP_RB_RPTR_ADDR)		     + RADEON_SCRATCH_REG_OFFSET);	dev_priv->scratch = ((__volatile__ u32 *)			     dev_priv->ring_rptr->handle +			     (RADEON_SCRATCH_REG_OFFSET / sizeof(u32)));	RADEON_WRITE(RADEON_SCRATCH_UMSK, 0x7);	/* Writeback doesn't seem to work everywhere, test it first */	DRM_WRITE32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1), 0);	RADEON_WRITE(RADEON_SCRATCH_REG1, 0xdeadbeef);	for (tmp = 0; tmp < dev_priv->usec_timeout; tmp++) {		if (DRM_READ32(dev_priv->ring_rptr, RADEON_SCRATCHOFF(1)) ==		    0xdeadbeef)			break;		DRM_UDELAY(1);	}	if (tmp < dev_priv->usec_timeout) {		dev_priv->writeback_works = 1;		DRM_DEBUG("writeback test succeeded, tmp=%d\n", tmp);	} else {		dev_priv->writeback_works = 0;		DRM_DEBUG("writeback test failed\n");	}	if (radeon_no_wb == 1) {		dev_priv->writeback_works = 0;		DRM_DEBUG("writeback forced off\n");	}	dev_priv->sarea_priv->last_frame = dev_priv->scratch[0] = 0;	RADEON_WRITE(RADEON_LAST_FRAME_REG, dev_priv->sarea_priv->last_frame);	dev_priv->sarea_priv->last_dispatch = dev_priv->scratch[1] = 0;	RADEON_WRITE(RADEON_LAST_DISPATCH_REG,		     dev_priv->sarea_priv->last_dispatch);	dev_priv->sarea_priv->last_clear = dev_priv->scratch[2] = 0;	RADEON_WRITE(RADEON_LAST_CLEAR_REG, dev_priv->sarea_priv->last_clear);	/* Set ring buffer size */#ifdef __BIG_ENDIAN	RADEON_WRITE(RADEON_CP_RB_CNTL,		     dev_priv->ring.size_l2qw | RADEON_BUF_SWAP_32BIT);#else	RADEON_WRITE(RADEON_CP_RB_CNTL, dev_priv->ring.size_l2qw);#endif	radeon_do_wait_for_idle(dev_priv);	/* Turn on bus mastering */	tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS;	RADEON_WRITE(RADEON_BUS_CNTL, tmp);	/* Sync everything up */	RADEON_WRITE(RADEON_ISYNC_CNTL,		     (RADEON_ISYNC_ANY2D_IDLE3D |		      RADEON_ISYNC_ANY3D_IDLE2D |		      RADEON_ISYNC_WAIT_IDLEGUI |		      RADEON_ISYNC_CPSCRATCH_IDLEGUI));}/* Enable or disable PCI-E GART on the chip */static void radeon_set_pciegart(drm_radeon_private_t * dev_priv, int on){	u32 tmp = RADEON_READ_PCIE(dev_priv, RADEON_PCIE_TX_GART_CNTL);	if (on) {		DRM_DEBUG("programming pcie %08X %08lX %08X\n",			  dev_priv->gart_vm_start,			  (long)dev_priv->gart_info.bus_addr,			  dev_priv->gart_size);		RADEON_WRITE_PCIE(RADEON_PCIE_TX_DISCARD_RD_ADDR_LO,				  dev_priv->gart_vm_start);		RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_BASE,				  dev_priv->gart_info.bus_addr);		RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_START_LO,				  dev_priv->gart_vm_start);		RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_END_LO,				  dev_priv->gart_vm_start +				  dev_priv->gart_size - 1);		RADEON_WRITE(RADEON_MC_AGP_LOCATION, 0xffffffc0);	/* ?? */		RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_CNTL,				  RADEON_PCIE_TX_GART_EN);	} else {		RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_CNTL,				  tmp & ~RADEON_PCIE_TX_GART_EN);	}}/* Enable or disable PCI GART on the chip */static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on){	u32 tmp = RADEON_READ(RADEON_AIC_CNTL);	if (dev_priv->flags & CHIP_IS_PCIE) {		radeon_set_pciegart(dev_priv, on);		return;	}	if (on) {		RADEON_WRITE(RADEON_AIC_CNTL,			     tmp | RADEON_PCIGART_TRANSLATE_EN);		/* set PCI GART page-table base address		 */		RADEON_WRITE(RADEON_AIC_PT_BASE, dev_priv->gart_info.bus_addr);		/* set address range for PCI address translate		 */		RADEON_WRITE(RADEON_AIC_LO_ADDR, dev_priv->gart_vm_start);		RADEON_WRITE(RADEON_AIC_HI_ADDR, dev_priv->gart_vm_start			     + dev_priv->gart_size - 1);		/* Turn off AGP aperture -- is this required for PCI GART?		 */		RADEON_WRITE(RADEON_MC_AGP_LOCATION, 0xffffffc0);	/* ?? */		RADEON_WRITE(RADEON_AGP_COMMAND, 0);	/* clear AGP_COMMAND */	} else {		RADEON_WRITE(RADEON_AIC_CNTL,			     tmp & ~RADEON_PCIGART_TRANSLATE_EN);	}}static int radeon_do_init_cp(drm_device_t * dev, drm_radeon_init_t * init){	drm_radeon_private_t *dev_priv = dev->dev_private;	DRM_DEBUG("\n");	dev_priv->is_pci = init->is_pci;	if (dev_priv->is_pci && !dev->sg) {		DRM_ERROR("PCI GART memory not allocated!\n");		dev->dev_private = (void *)dev_priv;		radeon_do_cleanup_cp(dev);		return DRM_ERR(EINVAL);	}	dev_priv->usec_timeout = init->usec_timeout;	if (dev_priv->usec_timeout < 1 ||	    dev_priv->usec_timeout > RADEON_MAX_USEC_TIMEOUT) {		DRM_DEBUG("TIMEOUT problem!\n");		dev->dev_private = (void *)dev_priv;		radeon_do_cleanup_cp(dev);		return DRM_ERR(EINVAL);	}	switch (init->func) {	case RADEON_INIT_R200_CP:		dev_priv->microcode_version = UCODE_R200;		break;	case RADEON_INIT_R300_CP:		dev_priv->microcode_version = UCODE_R300;		break;	default:		dev_priv->microcode_version = UCODE_R100;	}	dev_priv->do_boxes = 0;	dev_priv->cp_mode = init->cp_mode;	/* We don't support anything other than bus-mastering ring mode,	 * but the ring can be in either AGP or PCI space for the ring	 * read pointer.	 */	if ((init->cp_mode != RADEON_CSQ_PRIBM_INDDIS) &&	    (init->cp_mode != RADEON_CSQ_PRIBM_INDBM)) {		DRM_DEBUG("BAD cp_mode (%x)!\n", init->cp_mode);		dev->dev_private = (void *)dev_priv;		radeon_do_cleanup_cp(dev);		return DRM_ERR(EINVAL);	}	switch (init->fb_bpp) {	case 16:		dev_priv->color_fmt = RADEON_COLOR_FORMAT_RGB565;		break;	case 32:	default:		dev_priv->color_fmt = RADEON_COLOR_FORMAT_ARGB8888;		break;	}	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;	switch (init->depth_bpp) {	case 16:		dev_priv->depth_fmt = RADEON_DEPTH_FORMAT_16BIT_INT_Z;		break;	case 32:	default:		dev_priv->depth_fmt = RADEON_DEPTH_FORMAT_24BIT_INT_Z;		break;	}	dev_priv->depth_offset = init->depth_offset;	dev_priv->depth_pitch = init->depth_pitch;	/* Hardware state for depth clears.  Remove this if/when we no	 * longer clear the depth buffer with a 3D rectangle.  Hard-code	 * all values to prevent unwanted 3D state from slipping through	 * and screwing with the clear operation.	 */	dev_priv->depth_clear.rb3d_cntl = (RADEON_PLANE_MASK_ENABLE |					   (dev_priv->color_fmt << 10) |					   (dev_priv->microcode_version ==					    UCODE_R100 ? RADEON_ZBLOCK16 : 0));	dev_priv->depth_clear.rb3d_zstencilcntl =	    (dev_priv->depth_fmt |	     RADEON_Z_TEST_ALWAYS |	     RADEON_STENCIL_TEST_ALWAYS |	     RADEON_STENCIL_S_FAIL_REPLACE |	     RADEON_STENCIL_ZPASS_REPLACE |	     RADEON_STENCIL_ZFAIL_REPLACE | RADEON_Z_WRITE_ENABLE);	dev_priv->depth_clear.se_cntl = (RADEON_FFACE_CULL_CW |					 RADEON_BFACE_SOLID |					 RADEON_FFACE_SOLID |					 RADEON_FLAT_SHADE_VTX_LAST |					 RADEON_DIFFUSE_SHADE_FLAT |					 RADEON_ALPHA_SHADE_FLAT |					 RADEON_SPECULAR_SHADE_FLAT |					 RADEON_FOG_SHADE_FLAT |					 RADEON_VTX_PIX_CENTER_OGL |					 RADEON_ROUND_MODE_TRUNC |					 RADEON_ROUND_PREC_8TH_PIX);	DRM_GETSAREA();	dev_priv->fb_offset = init->fb_offset;	dev_priv->mmio_offset = init->mmio_offset;	dev_priv->ring_offset = init->ring_offset;	dev_priv->ring_rptr_offset = init->ring_rptr_offset;	dev_priv->buffers_offset = init->buffers_offset;	dev_priv->gart_textures_offset = init->gart_textures_offset;	if (!dev_priv->sarea) {		DRM_ERROR("could not find sarea!\n");		dev->dev_private = (void *)dev_priv;		radeon_do_cleanup_cp(dev);		return DRM_ERR(EINVAL);	}	dev_priv->mmio = drm_core_findmap(dev, init->mmio_offset);	if (!dev_priv->mmio) {		DRM_ERROR("could not find mmio region!\n");		dev->dev_private = (void *)dev_priv;		radeon_do_cleanup_cp(dev);		return DRM_ERR(EINVAL);	}	dev_priv->cp_ring = drm_core_findmap(dev, init->ring_offset);	if (!dev_priv->cp_ring) {		DRM_ERROR("could not find cp ring region!\n");		dev->dev_private = (void *)dev_priv;		radeon_do_cleanup_cp(dev);		return DRM_ERR(EINVAL);	}	dev_priv->ring_rptr = drm_core_findmap(dev, init->ring_rptr_offset);	if (!dev_priv->ring_rptr) {		DRM_ERROR("could not find ring read pointer!\n");		dev->dev_private = (void *)dev_priv;		radeon_do_cleanup_cp(dev);		return DRM_ERR(EINVAL);	}	dev->agp_buffer_token = init->buffers_offset;	dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);	if (!dev->agp_buffer_map) {		DRM_ERROR("could not find dma buffer region!\n");		dev->dev_private = (void *)dev_priv;		radeon_do_cleanup_cp(dev);		return DRM_ERR(EINVAL);	}	if (init->gart_textures_offset) {		dev_priv->gart_textures =		    drm_core_findmap(dev, init->gart_textures_offset);		if (!dev_priv->gart_textures) {			DRM_ERROR("could not find GART texture region!\n");			dev->dev_private = (void *)dev_priv;			radeon_do_cleanup_cp(dev);			return DRM_ERR(EINVAL);		}	}	dev_priv->sarea_priv =	    (drm_radeon_sarea_t *) ((u8 *) dev_priv->sarea->handle +				    init->sarea_priv_offset);#if __OS_HAS_AGP	if (!dev_priv->is_pci) {		drm_core_ioremap(dev_priv->cp_ring, dev);		drm_core_ioremap(dev_priv->ring_rptr, dev);		drm_core_ioremap(dev->agp_buffer_map, dev);		if (!dev_priv->cp_ring->handle ||		    !dev_priv->ring_rptr->handle ||		    !dev->agp_buffer_map->handle) {			DRM_ERROR("could not find ioremap agp regions!\n");			dev->dev_private = (void *)dev_priv;			radeon_do_cleanup_cp(dev);			return DRM_ERR(EINVAL);		}	} else#endif	{		dev_priv->cp_ring->handle = (void *)dev_priv->cp_ring->offset;		dev_priv->ring_rptr->handle =		    (void *)dev_priv->ring_rptr->offset;		dev->agp_buffer_map->handle =		    (void *)dev->agp_buffer_map->offset;		DRM_DEBUG("dev_priv->cp_ring->handle %p\n",			  dev_priv->cp_ring->handle);		DRM_DEBUG("dev_priv->ring_rptr->handle %p\n",			  dev_priv->ring_rptr->handle);		DRM_DEBUG("dev->agp_buffer_map->handle %p\n",			  dev->agp_buffer_map->handle);	}	dev_priv->fb_location = (RADEON_READ(RADEON_MC_FB_LOCATION)				 & 0xffff) << 16;	dev_priv->front_pitch_offset = (((dev_priv->front_pitch / 64) << 22) |					((dev_priv->front_offset					  + dev_priv->fb_location) >> 10));	dev_priv->back_pitch_offset = (((dev_priv->back_pitch / 64) << 22) |				       ((dev_priv->back_offset					 + dev_priv->fb_location) >> 10));	dev_priv->depth_pitch_offset = (((dev_priv->depth_pitch / 64) << 22) |					((dev_priv->depth_offset					  + dev_priv->fb_location) >> 10));	dev_priv->gart_size = init->gart_size;	dev_priv->gart_vm_start = dev_priv->fb_location	    + RADEON_READ(RADEON_CONFIG_APER_SIZE);#if __OS_HAS_AGP	if (!dev_priv->is_pci)		dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset						 - dev->agp->base						 + dev_priv->gart_vm_start);	else#endif		dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset					- (unsigned long)dev->sg->virtual					+ dev_priv->gart_vm_start);	DRM_DEBUG("dev_priv->gart_size %d\n", dev_priv->gart_size);	DRM_DEBUG("dev_priv->gart_vm_start 0x%x\n", dev_priv->gart_vm_start);	DRM_DEBUG("dev_priv->gart_buffers_offset 0x%lx\n",		  dev_priv->gart_buffers_offset);	dev_priv->ring.start = (u32 *) dev_priv->cp_ring->handle;	dev_priv->ring.end = ((u32 *) dev_priv->cp_ring->handle			      + init->ring_size / sizeof(u32));	dev_priv->ring.size = init->ring_size;	dev_priv->ring.size_l2qw = drm_order(init->ring_size / 8);	dev_priv->ring.tail_mask = (dev_priv->ring.size / sizeof(u32)) - 1;	dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK;#if __OS_HAS_AGP	if (!dev_priv->is_pci) {		/* Turn off PCI GART */		radeon_set_pcigart(dev_priv, 0);	} else#endif	{		/* if we have an offset set from userspace */		if (dev_priv->pcigart_offset) {			dev_priv->gart_info.bus_addr =			    dev_priv->pcigart_offset + dev_priv->fb_location;			dev_priv->gart_info.addr =			    (unsigned long)drm_ioremap(dev_priv->gart_info.						       bus_addr,						       RADEON_PCIGART_TABLE_SIZE,						       dev);			dev_priv->gart_info.is_pcie =			    !!(dev_priv->flags & CHIP_IS_PCIE);			dev_priv->gart_info.gart_table_location =			    DRM_ATI_GART_FB;			DRM_DEBUG("Setting phys_pci_gart to %08lX %08lX\n",				  dev_priv->gart_info.addr,				  dev_priv->pcigart_offset);		} else {			dev_priv->gart_info.gart_table_location =			    DRM_ATI_GART_MAIN;			dev_priv->gart_info.addr =			    dev_priv->gart_info.bus_addr = 0;			if (dev_priv->flags & CHIP_IS_PCIE) {				DRM_ERROR				    ("Cannot use PCI Express without GART in FB memory\n");				radeon_do_cleanup_cp(dev);				return DRM_ERR(EINVAL);			}		}		if (!drm_ati_pcigart_init(dev, &dev_priv->gart_info)) {			DRM_ERROR("failed to init PCI GART!\n");			dev->dev_private = (void *)dev_priv;			radeon_do_cleanup_cp(dev);			return DRM_ERR(ENOMEM);		}		/* Turn on PCI GART */		radeon_set_pcigart(dev_priv, 1);	}	radeon_cp_load_microcode(dev_priv);	radeon_cp_init_ring_buffer(dev, dev_priv);	dev_priv->last_buf = 0;	dev->dev_private = (void *)dev_priv;	radeon_do_engine_reset(dev);	return 0;}static int radeon_do_cleanup_cp(drm_device_t * dev){	drm_radeon_private_t *dev_priv = dev->dev_private;	DRM_DEBUG("\n");	/* Make sure interrupts are disabled here because the uninstall ioctl	 * may not have been called from userspace and after dev_private	 * is freed, it's too late.	 */	if (dev->irq_enabled)		drm_irq_uninstall(dev);#if __OS_HAS_AGP	if (!dev_priv->is_pci) {		if (dev_priv->cp_ring != NULL)			drm_core_ioremapfree(dev_priv->cp_ring, dev);		if (dev_priv->ring_rptr != NULL)			drm_core_ioremapfree(dev_priv->ring_rptr, dev);		if (dev->agp_buffer_map != NULL) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -