drm/radeon: improve mc_stop/mc_resume on r5xx-r7xx
Along the same lines of what was done for evergreen+ in the last kernel. Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
bd25f0783d
commit
6253e4c75d
3 changed files with 116 additions and 16 deletions
|
@ -96,6 +96,15 @@
|
||||||
#define R600_CONFIG_F0_BASE 0x542C
|
#define R600_CONFIG_F0_BASE 0x542C
|
||||||
#define R600_CONFIG_APER_SIZE 0x5430
|
#define R600_CONFIG_APER_SIZE 0x5430
|
||||||
|
|
||||||
|
#define R600_BIF_FB_EN 0x5490
|
||||||
|
#define R600_FB_READ_EN (1 << 0)
|
||||||
|
#define R600_FB_WRITE_EN (1 << 1)
|
||||||
|
|
||||||
|
#define R600_CITF_CNTL 0x200c
|
||||||
|
#define R600_BLACKOUT_MASK 0x00000003
|
||||||
|
|
||||||
|
#define R700_MC_CITF_CNTL 0x25c0
|
||||||
|
|
||||||
#define R600_ROM_CNTL 0x1600
|
#define R600_ROM_CNTL 0x1600
|
||||||
# define R600_SCK_OVERWRITE (1 << 1)
|
# define R600_SCK_OVERWRITE (1 << 1)
|
||||||
# define R600_SCK_PRESCALE_CRYSTAL_CLK_SHIFT 28
|
# define R600_SCK_PRESCALE_CRYSTAL_CLK_SHIFT 28
|
||||||
|
|
|
@ -263,6 +263,7 @@ extern int rs690_mc_wait_for_idle(struct radeon_device *rdev);
|
||||||
struct rv515_mc_save {
|
struct rv515_mc_save {
|
||||||
u32 vga_render_control;
|
u32 vga_render_control;
|
||||||
u32 vga_hdp_control;
|
u32 vga_hdp_control;
|
||||||
|
bool crtc_enabled[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
int rv515_init(struct radeon_device *rdev);
|
int rv515_init(struct radeon_device *rdev);
|
||||||
|
|
|
@ -40,6 +40,12 @@ static int rv515_debugfs_ga_info_init(struct radeon_device *rdev);
|
||||||
static void rv515_gpu_init(struct radeon_device *rdev);
|
static void rv515_gpu_init(struct radeon_device *rdev);
|
||||||
int rv515_mc_wait_for_idle(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)
|
void rv515_debugfs(struct radeon_device *rdev)
|
||||||
{
|
{
|
||||||
if (r100_debugfs_rbbm_init(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)
|
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_render_control = RREG32(R_000300_VGA_RENDER_CONTROL);
|
||||||
save->vga_hdp_control = RREG32(R_000328_VGA_HDP_CONTROL);
|
save->vga_hdp_control = RREG32(R_000328_VGA_HDP_CONTROL);
|
||||||
|
|
||||||
/* Stop all video */
|
/* disable VGA render */
|
||||||
WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 0);
|
|
||||||
WREG32(R_000300_VGA_RENDER_CONTROL, 0);
|
WREG32(R_000300_VGA_RENDER_CONTROL, 0);
|
||||||
WREG32(R_0060E8_D1CRTC_UPDATE_LOCK, 1);
|
/* blank the display controllers */
|
||||||
WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 1);
|
for (i = 0; i < rdev->num_crtc; i++) {
|
||||||
WREG32(R_006080_D1CRTC_CONTROL, 0);
|
crtc_enabled = RREG32(AVIVO_D1CRTC_CONTROL + crtc_offsets[i]) & AVIVO_CRTC_EN;
|
||||||
WREG32(R_006880_D2CRTC_CONTROL, 0);
|
if (crtc_enabled) {
|
||||||
WREG32(R_0060E8_D1CRTC_UPDATE_LOCK, 0);
|
save->crtc_enabled[i] = true;
|
||||||
WREG32(R_0068E8_D2CRTC_UPDATE_LOCK, 0);
|
tmp = RREG32(AVIVO_D1CRTC_CONTROL + crtc_offsets[i]);
|
||||||
WREG32(R_000330_D1VGA_CONTROL, 0);
|
if (!(tmp & AVIVO_CRTC_DISP_READ_REQUEST_DISABLE)) {
|
||||||
WREG32(R_000338_D2VGA_CONTROL, 0);
|
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)
|
void rv515_mc_resume(struct radeon_device *rdev, struct rv515_mc_save *save)
|
||||||
{
|
{
|
||||||
WREG32(R_006110_D1GRPH_PRIMARY_SURFACE_ADDRESS, rdev->mc.vram_start);
|
u32 tmp, frame_count;
|
||||||
WREG32(R_006118_D1GRPH_SECONDARY_SURFACE_ADDRESS, rdev->mc.vram_start);
|
int i, j;
|
||||||
WREG32(R_006910_D2GRPH_PRIMARY_SURFACE_ADDRESS, rdev->mc.vram_start);
|
|
||||||
WREG32(R_006918_D2GRPH_SECONDARY_SURFACE_ADDRESS, rdev->mc.vram_start);
|
/* update crtc base addresses */
|
||||||
WREG32(R_000310_VGA_MEMORY_BASE_ADDRESS, rdev->mc.vram_start);
|
for (i = 0; i < rdev->num_crtc; i++) {
|
||||||
/* Unlock host access */
|
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);
|
WREG32(R_000328_VGA_HDP_CONTROL, save->vga_hdp_control);
|
||||||
mdelay(1);
|
mdelay(1);
|
||||||
WREG32(R_000300_VGA_RENDER_CONTROL, save->vga_render_control);
|
WREG32(R_000300_VGA_RENDER_CONTROL, save->vga_render_control);
|
||||||
|
|
Loading…
Reference in a new issue