diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/rv515.c')
| -rw-r--r-- | drivers/gpu/drm/radeon/rv515.c | 122 | 
1 files changed, 106 insertions, 16 deletions
diff --git a/drivers/gpu/drm/radeon/rv515.c b/drivers/gpu/drm/radeon/rv515.c index 785d09590b2..2bb6d0e84b3 100644 --- a/drivers/gpu/drm/radeon/rv515.c +++ b/drivers/gpu/drm/radeon/rv515.c @@ -40,6 +40,12 @@ static int rv515_debugfs_ga_info_init(struct radeon_device *rdev);  static void rv515_gpu_init(struct radeon_device *rdev);  int rv515_mc_wait_for_idle(struct radeon_device *rdev); +static const u32 crtc_offsets[2] = +{ +	0, +	AVIVO_D2CRTC_H_TOTAL - AVIVO_D1CRTC_H_TOTAL +}; +  void rv515_debugfs(struct radeon_device *rdev)  {  	if (r100_debugfs_rbbm_init(rdev)) { @@ -281,30 +287,114 @@ static int rv515_debugfs_ga_info_init(struct radeon_device *rdev)  void rv515_mc_stop(struct radeon_device *rdev, struct rv515_mc_save *save)  { +	u32 crtc_enabled, tmp, frame_count, blackout; +	int i, j; +  	save->vga_render_control = RREG32(R_000300_VGA_RENDER_CONTROL);  	save->vga_hdp_control = RREG32(R_000328_VGA_HDP_CONTROL); -	/* Stop all video */ -	WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 0); +	/* disable VGA render */  	WREG32(R_000300_VGA_RENDER_CONTROL, 0); -	WREG32(R_0060E8_D1CRTC_UPDATE_LOCK, 1); -	WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 1); -	WREG32(R_006080_D1CRTC_CONTROL, 0); -	WREG32(R_006880_D2CRTC_CONTROL, 0); -	WREG32(R_0060E8_D1CRTC_UPDATE_LOCK, 0); -	WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 0); -	WREG32(R_000330_D1VGA_CONTROL, 0); -	WREG32(R_000338_D2VGA_CONTROL, 0); +	/* blank the display controllers */ +	for (i = 0; i < rdev->num_crtc; i++) { +		crtc_enabled = RREG32(AVIVO_D1CRTC_CONTROL + crtc_offsets[i]) & AVIVO_CRTC_EN; +		if (crtc_enabled) { +			save->crtc_enabled[i] = true; +			tmp = RREG32(AVIVO_D1CRTC_CONTROL + crtc_offsets[i]); +			if (!(tmp & AVIVO_CRTC_DISP_READ_REQUEST_DISABLE)) { +				radeon_wait_for_vblank(rdev, i); +				tmp |= AVIVO_CRTC_DISP_READ_REQUEST_DISABLE; +				WREG32(AVIVO_D1CRTC_CONTROL + crtc_offsets[i], tmp); +			} +			/* wait for the next frame */ +			frame_count = radeon_get_vblank_counter(rdev, i); +			for (j = 0; j < rdev->usec_timeout; j++) { +				if (radeon_get_vblank_counter(rdev, i) != frame_count) +					break; +				udelay(1); +			} +		} else { +			save->crtc_enabled[i] = false; +		} +	} + +	radeon_mc_wait_for_idle(rdev); + +	if (rdev->family >= CHIP_R600) { +		if (rdev->family >= CHIP_RV770) +			blackout = RREG32(R700_MC_CITF_CNTL); +		else +			blackout = RREG32(R600_CITF_CNTL); +		if ((blackout & R600_BLACKOUT_MASK) != R600_BLACKOUT_MASK) { +			/* Block CPU access */ +			WREG32(R600_BIF_FB_EN, 0); +			/* blackout the MC */ +			blackout |= R600_BLACKOUT_MASK; +			if (rdev->family >= CHIP_RV770) +				WREG32(R700_MC_CITF_CNTL, blackout); +			else +				WREG32(R600_CITF_CNTL, blackout); +		} +	}  }  void rv515_mc_resume(struct radeon_device *rdev, struct rv515_mc_save *save)  { -	WREG32(R_006110_D1GRPH_PRIMARY_SURFACE_ADDRESS, rdev->mc.vram_start); -	WREG32(R_006118_D1GRPH_SECONDARY_SURFACE_ADDRESS, rdev->mc.vram_start); -	WREG32(R_006910_D2GRPH_PRIMARY_SURFACE_ADDRESS, rdev->mc.vram_start); -	WREG32(R_006918_D2GRPH_SECONDARY_SURFACE_ADDRESS, rdev->mc.vram_start); -	WREG32(R_000310_VGA_MEMORY_BASE_ADDRESS, rdev->mc.vram_start); -	/* Unlock host access */ +	u32 tmp, frame_count; +	int i, j; + +	/* update crtc base addresses */ +	for (i = 0; i < rdev->num_crtc; i++) { +		if (rdev->family >= CHIP_RV770) { +			if (i == 1) { +				WREG32(R700_D1GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, +				       upper_32_bits(rdev->mc.vram_start)); +				WREG32(R700_D1GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, +				       upper_32_bits(rdev->mc.vram_start)); +			} else { +				WREG32(R700_D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, +				       upper_32_bits(rdev->mc.vram_start)); +				WREG32(R700_D2GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, +				       upper_32_bits(rdev->mc.vram_start)); +			} +		} +		WREG32(R_006110_D1GRPH_PRIMARY_SURFACE_ADDRESS + crtc_offsets[i], +		       (u32)rdev->mc.vram_start); +		WREG32(R_006118_D1GRPH_SECONDARY_SURFACE_ADDRESS + crtc_offsets[i], +		       (u32)rdev->mc.vram_start); +	} +	WREG32(R_000310_VGA_MEMORY_BASE_ADDRESS, (u32)rdev->mc.vram_start); + +	if (rdev->family >= CHIP_R600) { +		/* unblackout the MC */ +		if (rdev->family >= CHIP_RV770) +			tmp = RREG32(R700_MC_CITF_CNTL); +		else +			tmp = RREG32(R600_CITF_CNTL); +		tmp &= ~R600_BLACKOUT_MASK; +		if (rdev->family >= CHIP_RV770) +			WREG32(R700_MC_CITF_CNTL, tmp); +		else +			WREG32(R600_CITF_CNTL, tmp); +		/* allow CPU access */ +		WREG32(R600_BIF_FB_EN, R600_FB_READ_EN | R600_FB_WRITE_EN); +	} + +	for (i = 0; i < rdev->num_crtc; i++) { +		if (save->crtc_enabled[i]) { +			tmp = RREG32(AVIVO_D1CRTC_CONTROL + crtc_offsets[i]); +			tmp &= ~AVIVO_CRTC_DISP_READ_REQUEST_DISABLE; +			WREG32(AVIVO_D1CRTC_CONTROL + crtc_offsets[i], tmp); +			/* wait for the next frame */ +			frame_count = radeon_get_vblank_counter(rdev, i); +			for (j = 0; j < rdev->usec_timeout; j++) { +				if (radeon_get_vblank_counter(rdev, i) != frame_count) +					break; +				udelay(1); +			} +		} +	} +	/* Unlock vga access */  	WREG32(R_000328_VGA_HDP_CONTROL, save->vga_hdp_control);  	mdelay(1);  	WREG32(R_000300_VGA_RENDER_CONTROL, save->vga_render_control);  |