static int radeon_do_wait_for_idle(drm_radeon_private_t * dev_priv) { int i, ret; dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; ret = radeon_do_wait_for_fifo(dev_priv, 64); if (ret) return ret; for (i = 0; i < dev_priv->usec_timeout; i++) { if (!(RADEON_READ(RADEON_RBBM_STATUS) & RADEON_RBBM_ACTIVE)) { radeon_do_pixcache_flush(dev_priv); return 0; } DRM_UDELAY(1); } DRM_DEBUG("wait idle failed status : 0x%08X 0x%08X\n", RADEON_READ(RADEON_RBBM_STATUS), RADEON_READ(R300_VAP_CNTL_STATUS)); #if RADEON_FIFO_DEBUG DRM_ERROR("failed!\n"); radeon_status(dev_priv); #endif return -EBUSY; }
static int radeon_do_pixcache_flush(drm_radeon_private_t * dev_priv) { u32 tmp; int i; dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) { tmp = RADEON_READ(RADEON_RB3D_DSTCACHE_CTLSTAT); tmp |= RADEON_RB3D_DC_FLUSH_ALL; RADEON_WRITE(RADEON_RB3D_DSTCACHE_CTLSTAT, tmp); for (i = 0; i < dev_priv->usec_timeout; i++) { if (!(RADEON_READ(RADEON_RB3D_DSTCACHE_CTLSTAT) & RADEON_RB3D_DC_BUSY)) { return 0; } DRM_UDELAY(1); } } else { /* don't flush or purge cache here or lockup */ return 0; } #if RADEON_FIFO_DEBUG DRM_ERROR("failed!\n"); radeon_status(dev_priv); #endif return -EBUSY; }
static u32 radeon_acknowledge_irqs(drm_radeon_private_t *dev_priv, u32 *r500_disp_int) { u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS); u32 irq_mask = RADEON_SW_INT_TEST; *r500_disp_int = 0; if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) { /* vbl interrupts in a different place */ if (irqs & R500_DISPLAY_INT_STATUS) { /* if a display interrupt */ u32 disp_irq; disp_irq = RADEON_READ(R500_DISP_INTERRUPT_STATUS); *r500_disp_int = disp_irq; if (disp_irq & R500_D1_VBLANK_INTERRUPT) RADEON_WRITE(R500_D1MODE_VBLANK_STATUS, R500_VBLANK_ACK); if (disp_irq & R500_D2_VBLANK_INTERRUPT) RADEON_WRITE(R500_D2MODE_VBLANK_STATUS, R500_VBLANK_ACK); } irq_mask |= R500_DISPLAY_INT_STATUS; } else irq_mask |= RADEON_CRTC_VBLANK_STAT | RADEON_CRTC2_VBLANK_STAT; irqs &= irq_mask; if (irqs) RADEON_WRITE(RADEON_GEN_INT_STATUS, irqs); return irqs; }
u32 radeon_get_vblank_counter(struct drm_device *dev, int crtc) { drm_radeon_private_t *dev_priv = dev->dev_private; if (!dev_priv) { DRM_ERROR("called with no initialization\n"); return -EINVAL; } if (crtc < 0 || crtc > 1) { DRM_ERROR("Invalid crtc %d\n", crtc); return -EINVAL; } if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) { if (crtc == 0) return RADEON_READ(R500_D1CRTC_FRAME_COUNT); else return RADEON_READ(R500_D2CRTC_FRAME_COUNT); } else { if (crtc == 0) return RADEON_READ(RADEON_CRTC_CRNT_FRAME); else return RADEON_READ(RADEON_CRTC2_CRNT_FRAME); } }
u_int32_t radeondrm_get_ring_head(struct drm_radeon_private *dev_priv) { if (dev_priv->writeback_works) { return (radeondrm_read_rptr(dev_priv, 0)); } else { if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) return (RADEON_READ(R600_CP_RB_RPTR)); else return (RADEON_READ(RADEON_CP_RB_RPTR)); } }
u_int32_t radeondrm_get_scratch(struct drm_radeon_private *dev_priv, u_int32_t off) { if (dev_priv->writeback_works) if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) return radeondrm_read_rptr(dev_priv, R600_SCRATCHOFF(off)); else return radeondrm_read_rptr(dev_priv, RADEON_SCRATCHOFF(off)); else if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) return RADEON_READ(R600_SCRATCH_REG0 + 4 * off); else return RADEON_READ(RADEON_SCRATCH_REG0 + 4 * off); }
static int RADEON_READ_PLL(struct drm_device * dev, int addr) { drm_radeon_private_t *dev_priv = dev->dev_private; RADEON_WRITE8(RADEON_CLOCK_CNTL_INDEX, addr & 0x1f); return RADEON_READ(RADEON_CLOCK_CNTL_DATA); }
static __inline__ void radeon_acknowledge_irqs(drm_radeon_private_t *dev_priv) { u32 tmp = RADEON_READ( RADEON_GEN_INT_STATUS ) & (RADEON_SW_INT_TEST_ACK | RADEON_CRTC_VBLANK_STAT); if (tmp) RADEON_WRITE( RADEON_GEN_INT_STATUS, tmp ); }
void DRM(dma_service)( DRM_IRQ_ARGS ) { drm_device_t *dev = (drm_device_t *) arg; drm_radeon_private_t *dev_priv = (drm_radeon_private_t *)dev->dev_private; u32 stat; /* Only consider the bits we're interested in - others could be used * outside the DRM */ stat = RADEON_READ(RADEON_GEN_INT_STATUS) & (RADEON_SW_INT_TEST | RADEON_CRTC_VBLANK_STAT); if (!stat) return; /* SW interrupt */ if (stat & RADEON_SW_INT_TEST) { DRM_WAKEUP( &dev_priv->swi_queue ); } /* VBLANK interrupt */ if (stat & RADEON_CRTC_VBLANK_STAT) { atomic_inc(&dev->vbl_received); DRM_WAKEUP(&dev->vbl_queue); DRM(vbl_send_signals)( dev ); } /* Acknowledge interrupts we handle */ RADEON_WRITE(RADEON_GEN_INT_STATUS, stat); }
static int radeon_wait_irq(struct drm_device * dev, int swi_nr) { drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private; int ret = 0; if (RADEON_READ(RADEON_LAST_SWI_REG) >= swi_nr) return 0; dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; DRM_WAIT_ON(ret, dev_priv->swi_queue, 3 * DRM_HZ, RADEON_READ(RADEON_LAST_SWI_REG) >= swi_nr); return ret; }
static u32 R500_READ_MCIND(drm_radeon_private_t *dev_priv, int addr) { u32 ret; RADEON_WRITE(R520_MC_IND_INDEX, 0x7f0000 | (addr & 0xff)); ret = RADEON_READ(R520_MC_IND_DATA); RADEON_WRITE(R520_MC_IND_INDEX, 0); return ret; }
static __inline__ u32 radeon_acknowledge_irqs(drm_radeon_private_t * dev_priv, u32 mask) { u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS) & mask; if (irqs) RADEON_WRITE(RADEON_GEN_INT_STATUS, irqs); return irqs; }
static u32 RS690_READ_MCIND(drm_radeon_private_t *dev_priv, int addr) { u32 ret; RADEON_WRITE(RS690_MC_INDEX, (addr & RS690_MC_INDEX_MASK)); ret = RADEON_READ(RS690_MC_DATA); RADEON_WRITE(RS690_MC_INDEX, RS690_MC_INDEX_MASK); return ret; }
static u32 RS480_READ_MCIND(drm_radeon_private_t *dev_priv, int addr) { u32 ret; RADEON_WRITE(RS480_NB_MC_INDEX, addr & 0xff); ret = RADEON_READ(RS480_NB_MC_DATA); RADEON_WRITE(RS480_NB_MC_INDEX, 0xff); return ret; }
u_int32_t radeondrm_get_ring_head(struct drm_radeon_private *dev_priv) { if (dev_priv->writeback_works) return (radeondrm_read_rptr(dev_priv, 0)); else return (RADEON_READ(RADEON_CP_RB_RPTR)); }
static void radeon_init_pipes(drm_radeon_private_t *dev_priv) { uint32_t gb_tile_config, gb_pipe_sel = 0; /* RS4xx/RS6xx/R4xx/R5xx */ if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R420) { gb_pipe_sel = RADEON_READ(R400_GB_PIPE_SELECT); dev_priv->num_gb_pipes = ((gb_pipe_sel >> 12) & 0x3) + 1; } else {
int radeon_wait_irq(drm_device_t *dev, int swi_nr) { drm_radeon_private_t *dev_priv = (drm_radeon_private_t *)dev->dev_private; int ret = 0; if (RADEON_READ( RADEON_LAST_SWI_REG ) >= swi_nr) return 0; dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; /* This is a hack to work around mysterious freezes on certain * systems: */ radeon_acknowledge_irqs( dev_priv ); DRM_WAIT_ON( ret, dev_priv->swi_queue, 3 * DRM_HZ, RADEON_READ( RADEON_LAST_SWI_REG ) >= swi_nr ); return ret; }
u32 radeon_read_fb_location(drm_radeon_private_t *dev_priv) { if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515) return R500_READ_MCIND(dev_priv, RV515_MC_FB_LOCATION); else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) return RS690_READ_MCIND(dev_priv, RS690_MC_FB_LOCATION); else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515) return R500_READ_MCIND(dev_priv, R520_MC_FB_LOCATION); else return RADEON_READ(RADEON_MC_FB_LOCATION); }
static int radeon_do_wait_for_fifo(drm_radeon_private_t * dev_priv, int entries) { int i; dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; for (i = 0; i < dev_priv->usec_timeout; i++) { int slots = (RADEON_READ(RADEON_RBBM_STATUS) & RADEON_RBBM_FIFOCNT_MASK); if (slots >= entries) return 0; DRM_UDELAY(1); } DRM_DEBUG("wait for fifo failed status : 0x%08X 0x%08X\n", RADEON_READ(RADEON_RBBM_STATUS), RADEON_READ(R300_VAP_CNTL_STATUS)); #if RADEON_FIFO_DEBUG DRM_ERROR("failed!\n"); radeon_status(dev_priv); #endif return -EBUSY; }
void radeondrm_commit_ring(struct drm_radeon_private *dev_priv) { int i, tail_aligned, num_p2; u_int32_t *ring; /* check if the ring is padded out to 16-dword alignment */ tail_aligned = dev_priv->ring.tail & (RADEON_RING_ALIGN - 1); if (tail_aligned) { num_p2 = RADEON_RING_ALIGN - tail_aligned; ring = dev_priv->ring.start; /* pad with some CP_PACKET2 */ for (i = 0; i < num_p2; i++) ring[dev_priv->ring.tail + i] = CP_PACKET2(); dev_priv->ring.tail += i; dev_priv->ring.space -= num_p2; } dev_priv->ring.tail &= dev_priv->ring.tail_mask; /* XXX 128byte aligned stuff */ /* flush write combining buffer and writes to ring */ DRM_MEMORYBARRIER(); radeondrm_get_ring_head(dev_priv); if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) { RADEON_WRITE(R600_CP_RB_WPTR, dev_priv->ring.tail); /* read from PCI bus to ensure correct posting */ RADEON_READ(R600_CP_RB_RPTR); } else { RADEON_WRITE(RADEON_CP_RB_WPTR, dev_priv->ring.tail); /* read from PCI bus to ensure correct posting */ RADEON_READ(RADEON_CP_RB_RPTR); } }
int radeon_vblank_crtc_get(struct drm_device *dev) { drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private; u32 flag; u32 value; flag = RADEON_READ(RADEON_GEN_INT_CNTL); value = 0; if (flag & RADEON_CRTC_VBLANK_MASK) value |= DRM_RADEON_VBLANK_CRTC1; if (flag & RADEON_CRTC2_VBLANK_MASK) value |= DRM_RADEON_VBLANK_CRTC2; return value; }
static void radeon_status(drm_radeon_private_t * dev_priv) { printk("%s:\n", __func__); printk("RBBM_STATUS = 0x%08x\n", (unsigned int)RADEON_READ(RADEON_RBBM_STATUS)); printk("CP_RB_RTPR = 0x%08x\n", (unsigned int)RADEON_READ(RADEON_CP_RB_RPTR)); printk("CP_RB_WTPR = 0x%08x\n", (unsigned int)RADEON_READ(RADEON_CP_RB_WPTR)); printk("AIC_CNTL = 0x%08x\n", (unsigned int)RADEON_READ(RADEON_AIC_CNTL)); printk("AIC_STAT = 0x%08x\n", (unsigned int)RADEON_READ(RADEON_AIC_STAT)); printk("AIC_PT_BASE = 0x%08x\n", (unsigned int)RADEON_READ(RADEON_AIC_PT_BASE)); printk("TLB_ADDR = 0x%08x\n", (unsigned int)RADEON_READ(RADEON_AIC_TLB_ADDR)); printk("TLB_DATA = 0x%08x\n", (unsigned int)RADEON_READ(RADEON_AIC_TLB_DATA)); }
irqreturn_t radeon_driver_irq_handler(DRM_IRQ_ARGS) { struct drm_device *dev = (struct drm_device *) arg; drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private; u32 stat; u32 r500_disp_int; u32 tmp; if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) return IRQ_NONE; /* Only consider the bits we're interested in - others could be used * outside the DRM */ stat = radeon_acknowledge_irqs(dev_priv, &r500_disp_int); if (!stat) return IRQ_NONE; stat &= dev_priv->irq_enable_reg; /* SW interrupt */ if (stat & RADEON_SW_INT_TEST) DRM_WAKEUP(&dev_priv->swi_queue); /* VBLANK interrupt */ if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) { if (r500_disp_int & R500_D1_VBLANK_INTERRUPT) drm_handle_vblank(dev, 0); if (r500_disp_int & R500_D2_VBLANK_INTERRUPT) drm_handle_vblank(dev, 1); } else { if (stat & RADEON_CRTC_VBLANK_STAT) drm_handle_vblank(dev, 0); if (stat & RADEON_CRTC2_VBLANK_STAT) drm_handle_vblank(dev, 1); } if (dev->msi_enabled) { switch(dev_priv->flags & RADEON_FAMILY_MASK) { case CHIP_RS400: case CHIP_RS480: tmp = RADEON_READ(RADEON_AIC_CNTL) & ~RS400_MSI_REARM; RADEON_WRITE(RADEON_AIC_CNTL, tmp); RADEON_WRITE(RADEON_AIC_CNTL, tmp | RS400_MSI_REARM); break; case CHIP_RS600: case CHIP_RS690: case CHIP_RS740: tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RS600_MSI_REARM; RADEON_WRITE(RADEON_BUS_CNTL, tmp); RADEON_WRITE(RADEON_BUS_CNTL, tmp | RS600_MSI_REARM); break; default: tmp = RADEON_READ(RADEON_MSI_REARM_EN) & ~RV370_MSI_REARM_EN; RADEON_WRITE(RADEON_MSI_REARM_EN, tmp); RADEON_WRITE(RADEON_MSI_REARM_EN, tmp | RV370_MSI_REARM_EN); break; } } return IRQ_HANDLED; }
static u32 RADEON_READ_PCIE(drm_radeon_private_t *dev_priv, int addr) { RADEON_WRITE8(RADEON_PCIE_INDEX, addr & 0xff); return RADEON_READ(RADEON_PCIE_DATA); }