diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/r100.c')
| -rw-r--r-- | drivers/gpu/drm/radeon/r100.c | 168 | 
1 files changed, 95 insertions, 73 deletions
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 9fc61dd68bc..1544efcf1c3 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c @@ -142,36 +142,6 @@ void r100_wait_for_vblank(struct radeon_device *rdev, int crtc)  }  /** - * r100_pre_page_flip - pre-pageflip callback. - * - * @rdev: radeon_device pointer - * @crtc: crtc to prepare for pageflip on - * - * Pre-pageflip callback (r1xx-r4xx). - * Enables the pageflip irq (vblank irq). - */ -void r100_pre_page_flip(struct radeon_device *rdev, int crtc) -{ -	/* enable the pflip int */ -	radeon_irq_kms_pflip_irq_get(rdev, crtc); -} - -/** - * r100_post_page_flip - pos-pageflip callback. - * - * @rdev: radeon_device pointer - * @crtc: crtc to cleanup pageflip on - * - * Post-pageflip callback (r1xx-r4xx). - * Disables the pageflip irq (vblank irq). - */ -void r100_post_page_flip(struct radeon_device *rdev, int crtc) -{ -	/* disable the pflip int */ -	radeon_irq_kms_pflip_irq_put(rdev, crtc); -} - -/**   * r100_page_flip - pageflip callback.   *   * @rdev: radeon_device pointer @@ -182,9 +152,8 @@ void r100_post_page_flip(struct radeon_device *rdev, int crtc)   * During vblank we take the crtc lock and wait for the update_pending   * bit to go high, when it does, we release the lock, and allow the   * double buffered update to take place. - * Returns the current update pending status.   */ -u32 r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) +void r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)  {  	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];  	u32 tmp = ((u32)crtc_base) | RADEON_CRTC_OFFSET__OFFSET_LOCK; @@ -206,8 +175,24 @@ u32 r100_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)  	tmp &= ~RADEON_CRTC_OFFSET__OFFSET_LOCK;  	WREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset, tmp); +} + +/** + * r100_page_flip_pending - check if page flip is still pending + * + * @rdev: radeon_device pointer + * @crtc_id: crtc to check + * + * Check if the last pagefilp is still pending (r1xx-r4xx). + * Returns the current update pending status. + */ +bool r100_page_flip_pending(struct radeon_device *rdev, int crtc_id) +{ +	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; +  	/* Return current update_pending status: */ -	return RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) & RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET; +	return !!(RREG32(RADEON_CRTC_OFFSET + radeon_crtc->crtc_offset) & +		RADEON_CRTC_OFFSET__GUI_TRIG_OFFSET);  }  /** @@ -697,15 +682,11 @@ void r100_pci_gart_disable(struct radeon_device *rdev)  	WREG32(RADEON_AIC_HI_ADDR, 0);  } -int r100_pci_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr) +void r100_pci_gart_set_page(struct radeon_device *rdev, unsigned i, +			    uint64_t addr)  {  	u32 *gtt = rdev->gart.ptr; - -	if (i < 0 || i > rdev->gart.num_gpu_pages) { -		return -EINVAL; -	}  	gtt[i] = cpu_to_le32(lower_32_bits(addr)); -	return 0;  }  void r100_pci_gart_fini(struct radeon_device *rdev) @@ -794,7 +775,7 @@ int r100_irq_process(struct radeon_device *rdev)  				wake_up(&rdev->irq.vblank_queue);  			}  			if (atomic_read(&rdev->irq.pflip[0])) -				radeon_crtc_handle_flip(rdev, 0); +				radeon_crtc_handle_vblank(rdev, 0);  		}  		if (status & RADEON_CRTC2_VBLANK_STAT) {  			if (rdev->irq.crtc_vblank_int[1]) { @@ -803,7 +784,7 @@ int r100_irq_process(struct radeon_device *rdev)  				wake_up(&rdev->irq.vblank_queue);  			}  			if (atomic_read(&rdev->irq.pflip[1])) -				radeon_crtc_handle_flip(rdev, 1); +				radeon_crtc_handle_vblank(rdev, 1);  		}  		if (status & RADEON_FP_DETECT_STAT) {  			queue_hotplug = true; @@ -869,13 +850,14 @@ void r100_fence_ring_emit(struct radeon_device *rdev,  	radeon_ring_write(ring, RADEON_SW_INT_FIRE);  } -void r100_semaphore_ring_emit(struct radeon_device *rdev, +bool r100_semaphore_ring_emit(struct radeon_device *rdev,  			      struct radeon_ring *ring,  			      struct radeon_semaphore *semaphore,  			      bool emit_wait)  {  	/* Unused on older asics, since we don't have semaphores or multiple rings */  	BUG(); +	return false;  }  int r100_copy_blit(struct radeon_device *rdev, @@ -1049,6 +1031,36 @@ static int r100_cp_init_microcode(struct radeon_device *rdev)  	return err;  } +u32 r100_gfx_get_rptr(struct radeon_device *rdev, +		      struct radeon_ring *ring) +{ +	u32 rptr; + +	if (rdev->wb.enabled) +		rptr = le32_to_cpu(rdev->wb.wb[ring->rptr_offs/4]); +	else +		rptr = RREG32(RADEON_CP_RB_RPTR); + +	return rptr; +} + +u32 r100_gfx_get_wptr(struct radeon_device *rdev, +		      struct radeon_ring *ring) +{ +	u32 wptr; + +	wptr = RREG32(RADEON_CP_RB_WPTR); + +	return wptr; +} + +void r100_gfx_set_wptr(struct radeon_device *rdev, +		       struct radeon_ring *ring) +{ +	WREG32(RADEON_CP_RB_WPTR, ring->wptr); +	(void)RREG32(RADEON_CP_RB_WPTR); +} +  static void r100_cp_load_microcode(struct radeon_device *rdev)  {  	const __be32 *fw_data; @@ -1101,7 +1113,6 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size)  	ring_size = (1 << (rb_bufsz + 1)) * 4;  	r100_cp_load_microcode(rdev);  	r = radeon_ring_init(rdev, ring, ring_size, RADEON_WB_CP_RPTR_OFFSET, -			     RADEON_CP_RB_RPTR, RADEON_CP_RB_WPTR,  			     RADEON_CP_PACKET2);  	if (r) {  		return r; @@ -1163,7 +1174,6 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size)  	WREG32(RADEON_CP_RB_CNTL, tmp);  	udelay(10); -	ring->rptr = RREG32(RADEON_CP_RB_RPTR);  	/* Set cp mode to bus mastering & enable cp*/  	WREG32(RADEON_CP_CSQ_MODE,  	       REG_SET(RADEON_INDIRECT2_START, indirect2_start) | @@ -1245,12 +1255,12 @@ int r100_reloc_pitch_offset(struct radeon_cs_parser *p,  	value = radeon_get_ib_value(p, idx);  	tmp = value & 0x003fffff; -	tmp += (((u32)reloc->lobj.gpu_offset) >> 10); +	tmp += (((u32)reloc->gpu_offset) >> 10);  	if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { -		if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) +		if (reloc->tiling_flags & RADEON_TILING_MACRO)  			tile_flags |= RADEON_DST_TILE_MACRO; -		if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) { +		if (reloc->tiling_flags & RADEON_TILING_MICRO) {  			if (reg == RADEON_SRC_PITCH_OFFSET) {  				DRM_ERROR("Cannot src blit from microtiled surface\n");  				radeon_cs_dump_packet(p, pkt); @@ -1296,7 +1306,7 @@ int r100_packet3_load_vbpntr(struct radeon_cs_parser *p,  			return r;  		}  		idx_value = radeon_get_ib_value(p, idx); -		ib[idx+1] = radeon_get_ib_value(p, idx + 1) + ((u32)reloc->lobj.gpu_offset); +		ib[idx+1] = radeon_get_ib_value(p, idx + 1) + ((u32)reloc->gpu_offset);  		track->arrays[i + 0].esize = idx_value >> 8;  		track->arrays[i + 0].robj = reloc->robj; @@ -1308,7 +1318,7 @@ int r100_packet3_load_vbpntr(struct radeon_cs_parser *p,  			radeon_cs_dump_packet(p, pkt);  			return r;  		} -		ib[idx+2] = radeon_get_ib_value(p, idx + 2) + ((u32)reloc->lobj.gpu_offset); +		ib[idx+2] = radeon_get_ib_value(p, idx + 2) + ((u32)reloc->gpu_offset);  		track->arrays[i + 1].robj = reloc->robj;  		track->arrays[i + 1].esize = idx_value >> 24;  		track->arrays[i + 1].esize &= 0x7F; @@ -1322,7 +1332,7 @@ int r100_packet3_load_vbpntr(struct radeon_cs_parser *p,  			return r;  		}  		idx_value = radeon_get_ib_value(p, idx); -		ib[idx+1] = radeon_get_ib_value(p, idx + 1) + ((u32)reloc->lobj.gpu_offset); +		ib[idx+1] = radeon_get_ib_value(p, idx + 1) + ((u32)reloc->gpu_offset);  		track->arrays[i + 0].robj = reloc->robj;  		track->arrays[i + 0].esize = idx_value >> 8;  		track->arrays[i + 0].esize &= 0x7F; @@ -1434,7 +1444,7 @@ int r100_cs_packet_parse_vline(struct radeon_cs_parser *p)  	obj = drm_mode_object_find(p->rdev->ddev, crtc_id, DRM_MODE_OBJECT_CRTC);  	if (!obj) {  		DRM_ERROR("cannot find crtc %d\n", crtc_id); -		return -EINVAL; +		return -ENOENT;  	}  	crtc = obj_to_crtc(obj);  	radeon_crtc = to_radeon_crtc(crtc); @@ -1565,7 +1575,7 @@ static int r100_packet0_check(struct radeon_cs_parser *p,  		track->zb.robj = reloc->robj;  		track->zb.offset = idx_value;  		track->zb_dirty = true; -		ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset); +		ib[idx] = idx_value + ((u32)reloc->gpu_offset);  		break;  	case RADEON_RB3D_COLOROFFSET:  		r = radeon_cs_packet_next_reloc(p, &reloc, 0); @@ -1578,7 +1588,7 @@ static int r100_packet0_check(struct radeon_cs_parser *p,  		track->cb[0].robj = reloc->robj;  		track->cb[0].offset = idx_value;  		track->cb_dirty = true; -		ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset); +		ib[idx] = idx_value + ((u32)reloc->gpu_offset);  		break;  	case RADEON_PP_TXOFFSET_0:  	case RADEON_PP_TXOFFSET_1: @@ -1592,16 +1602,16 @@ static int r100_packet0_check(struct radeon_cs_parser *p,  			return r;  		}  		if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { -			if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) +			if (reloc->tiling_flags & RADEON_TILING_MACRO)  				tile_flags |= RADEON_TXO_MACRO_TILE; -			if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) +			if (reloc->tiling_flags & RADEON_TILING_MICRO)  				tile_flags |= RADEON_TXO_MICRO_TILE_X2;  			tmp = idx_value & ~(0x7 << 2);  			tmp |= tile_flags; -			ib[idx] = tmp + ((u32)reloc->lobj.gpu_offset); +			ib[idx] = tmp + ((u32)reloc->gpu_offset);  		} else -			ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset); +			ib[idx] = idx_value + ((u32)reloc->gpu_offset);  		track->textures[i].robj = reloc->robj;  		track->tex_dirty = true;  		break; @@ -1619,7 +1629,7 @@ static int r100_packet0_check(struct radeon_cs_parser *p,  			return r;  		}  		track->textures[0].cube_info[i].offset = idx_value; -		ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset); +		ib[idx] = idx_value + ((u32)reloc->gpu_offset);  		track->textures[0].cube_info[i].robj = reloc->robj;  		track->tex_dirty = true;  		break; @@ -1637,7 +1647,7 @@ static int r100_packet0_check(struct radeon_cs_parser *p,  			return r;  		}  		track->textures[1].cube_info[i].offset = idx_value; -		ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset); +		ib[idx] = idx_value + ((u32)reloc->gpu_offset);  		track->textures[1].cube_info[i].robj = reloc->robj;  		track->tex_dirty = true;  		break; @@ -1655,7 +1665,7 @@ static int r100_packet0_check(struct radeon_cs_parser *p,  			return r;  		}  		track->textures[2].cube_info[i].offset = idx_value; -		ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset); +		ib[idx] = idx_value + ((u32)reloc->gpu_offset);  		track->textures[2].cube_info[i].robj = reloc->robj;  		track->tex_dirty = true;  		break; @@ -1673,9 +1683,9 @@ static int r100_packet0_check(struct radeon_cs_parser *p,  			return r;  		}  		if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { -			if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO) +			if (reloc->tiling_flags & RADEON_TILING_MACRO)  				tile_flags |= RADEON_COLOR_TILE_ENABLE; -			if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO) +			if (reloc->tiling_flags & RADEON_TILING_MICRO)  				tile_flags |= RADEON_COLOR_MICROTILE_ENABLE;  			tmp = idx_value & ~(0x7 << 16); @@ -1743,7 +1753,7 @@ static int r100_packet0_check(struct radeon_cs_parser *p,  			radeon_cs_dump_packet(p, pkt);  			return r;  		} -		ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset); +		ib[idx] = idx_value + ((u32)reloc->gpu_offset);  		break;  	case RADEON_PP_CNTL:  		{ @@ -1903,7 +1913,7 @@ static int r100_packet3_check(struct radeon_cs_parser *p,  			radeon_cs_dump_packet(p, pkt);  			return r;  		} -		ib[idx+1] = radeon_get_ib_value(p, idx+1) + ((u32)reloc->lobj.gpu_offset); +		ib[idx+1] = radeon_get_ib_value(p, idx+1) + ((u32)reloc->gpu_offset);  		r = r100_cs_track_check_pkt3_indx_buffer(p, pkt, reloc->robj);  		if (r) {  			return r; @@ -1917,7 +1927,7 @@ static int r100_packet3_check(struct radeon_cs_parser *p,  			radeon_cs_dump_packet(p, pkt);  			return r;  		} -		ib[idx] = radeon_get_ib_value(p, idx) + ((u32)reloc->lobj.gpu_offset); +		ib[idx] = radeon_get_ib_value(p, idx) + ((u32)reloc->gpu_offset);  		track->num_arrays = 1;  		track->vtx_size = r100_get_vtx_size(radeon_get_ib_value(p, idx + 2)); @@ -2493,11 +2503,9 @@ bool r100_gpu_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring)  	rbbm_status = RREG32(R_000E40_RBBM_STATUS);  	if (!G_000E40_GUI_ACTIVE(rbbm_status)) { -		radeon_ring_lockup_update(ring); +		radeon_ring_lockup_update(rdev, ring);  		return false;  	} -	/* force CP activities */ -	radeon_ring_force_activity(rdev, ring);  	return radeon_ring_test_lockup(rdev, ring);  } @@ -2853,21 +2861,28 @@ static void r100_pll_errata_after_data(struct radeon_device *rdev)  uint32_t r100_pll_rreg(struct radeon_device *rdev, uint32_t reg)  { +	unsigned long flags;  	uint32_t data; +	spin_lock_irqsave(&rdev->pll_idx_lock, flags);  	WREG8(RADEON_CLOCK_CNTL_INDEX, reg & 0x3f);  	r100_pll_errata_after_index(rdev);  	data = RREG32(RADEON_CLOCK_CNTL_DATA);  	r100_pll_errata_after_data(rdev); +	spin_unlock_irqrestore(&rdev->pll_idx_lock, flags);  	return data;  }  void r100_pll_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)  { +	unsigned long flags; + +	spin_lock_irqsave(&rdev->pll_idx_lock, flags);  	WREG8(RADEON_CLOCK_CNTL_INDEX, ((reg & 0x3f) | RADEON_PLL_WR_EN));  	r100_pll_errata_after_index(rdev);  	WREG32(RADEON_CLOCK_CNTL_DATA, v);  	r100_pll_errata_after_data(rdev); +	spin_unlock_irqrestore(&rdev->pll_idx_lock, flags);  }  static void r100_set_safe_registers(struct radeon_device *rdev) @@ -2926,9 +2941,11 @@ static int r100_debugfs_cp_ring_info(struct seq_file *m, void *data)  	seq_printf(m, "CP_RB_RPTR 0x%08x\n", rdp);  	seq_printf(m, "%u free dwords in ring\n", ring->ring_free_dw);  	seq_printf(m, "%u dwords in ring\n", count); -	for (j = 0; j <= count; j++) { -		i = (rdp + j) & ring->ptr_mask; -		seq_printf(m, "r[%04d]=0x%08x\n", i, ring->ring[i]); +	if (ring->ready) { +		for (j = 0; j <= count; j++) { +			i = (rdp + j) & ring->ptr_mask; +			seq_printf(m, "r[%04d]=0x%08x\n", i, ring->ring[i]); +		}  	}  	return 0;  } @@ -3184,12 +3201,12 @@ void r100_bandwidth_update(struct radeon_device *rdev)  	if (rdev->mode_info.crtcs[0]->base.enabled) {  		mode1 = &rdev->mode_info.crtcs[0]->base.mode; -		pixel_bytes1 = rdev->mode_info.crtcs[0]->base.fb->bits_per_pixel / 8; +		pixel_bytes1 = rdev->mode_info.crtcs[0]->base.primary->fb->bits_per_pixel / 8;  	}  	if (!(rdev->flags & RADEON_SINGLE_CRTC)) {  		if (rdev->mode_info.crtcs[1]->base.enabled) {  			mode2 = &rdev->mode_info.crtcs[1]->base.mode; -			pixel_bytes2 = rdev->mode_info.crtcs[1]->base.fb->bits_per_pixel / 8; +			pixel_bytes2 = rdev->mode_info.crtcs[1]->base.primary->fb->bits_per_pixel / 8;  		}  	} @@ -3913,6 +3930,7 @@ int r100_resume(struct radeon_device *rdev)  int r100_suspend(struct radeon_device *rdev)  { +	radeon_pm_suspend(rdev);  	r100_cp_disable(rdev);  	radeon_wb_disable(rdev);  	r100_irq_disable(rdev); @@ -3923,6 +3941,7 @@ int r100_suspend(struct radeon_device *rdev)  void r100_fini(struct radeon_device *rdev)  { +	radeon_pm_fini(rdev);  	r100_cp_fini(rdev);  	radeon_wb_fini(rdev);  	radeon_ib_pool_fini(rdev); @@ -4029,6 +4048,9 @@ int r100_init(struct radeon_device *rdev)  	}  	r100_set_safe_registers(rdev); +	/* Initialize power management */ +	radeon_pm_init(rdev); +  	rdev->accel_working = true;  	r = r100_startup(rdev);  	if (r) {  | 
