On Thu, Jul 26, 2012 at 8:35 PM, Alex Deucher <alexdeucher@xxxxxxxxx> wrote: > On Thu, Jul 26, 2012 at 7:24 PM, <j.glisse@xxxxxxxxx> wrote: >> From: Jerome Glisse <jglisse@xxxxxxxxxx> >> >> When we change start address of vram for the GPU memory controller >> we need to make sure that nothing in the GPU still use the old vram >> address. This patch cleanup and fix crtc address. >> >> However there is still someissue somewhere if we reenable the crtc >> after updating the address at which they sancout. So to avoid any >> issue disable crtc. Once we want to do flicker less transition >> btw uefi and radeon we will probably want to revisit how we program >> the GPU memory controller. >> >> This probably fix : >> https://bugs.freedesktop.org/show_bug.cgi?id=52467 >> https://bugs.freedesktop.org/show_bug.cgi?id=42373 >> >> Cc: <stable@xxxxxxxxxxxxxxx> > > this should be stable@xxxxxxxxxxxxxxx > >> Signed-off-by: Jerome Glisse <jglisse@xxxxxxxxxx> > > Also, I think we probably need to poll on bit 16 > (CRTC_CURRENT_MASTER_EN_STATE) of CRTC_CONTROL to make sure the crtc > is actually disabled. Something like the following in mc_stop(): > > WREG32(CRTC_CONTROL, 0); > while (RREG32(CRTC_CONTROL & CRTC_CURRENT_MASTER_EN_STATE)) > udelay(1); > > Any chance you want to fix the rv515_mc_stop() and rv515_mc_resume() > functions as well? > > Alex I will respin with splitting out what fix and what just improve/cleanup the code. I might change rv515 but i don't think it will hit such issue, on rv515 crtc is enabled through VGA, here the issue seems to only show up with uefi, i am trying to grab some non uefi laptop with same gpu to check. Cheers, Jerome > >> --- >> drivers/gpu/drm/radeon/evergreen.c | 178 ++++++++++++++++------------------ >> drivers/gpu/drm/radeon/radeon_asic.h | 18 +++- >> 2 files changed, 99 insertions(+), 97 deletions(-) >> >> diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c >> index e585a3b..c6ede66 100644 >> --- a/drivers/gpu/drm/radeon/evergreen.c >> +++ b/drivers/gpu/drm/radeon/evergreen.c >> @@ -1227,70 +1227,94 @@ void evergreen_agp_enable(struct radeon_device *rdev) >> WREG32(VM_CONTEXT1_CNTL, 0); >> } >> >> +static void evergreen_crtc_save(struct radeon_device *rdev, struct evergreen_mc_save *save, unsigned idx) >> +{ >> + save->crtc[idx].paddress = 0; >> + save->crtc[idx].saddress = 0; >> + save->crtc[idx].crtc_control = 0; >> + >> + if (idx >= rdev->num_crtc) { >> + /* it seems accessing non existant crtc trigger high latency */ >> + return; >> + } >> + >> + save->crtc[idx].paddress = RREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + save->crtc[idx].offset); >> + save->crtc[idx].paddress |= ((uint64_t)RREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + save->crtc[idx].offset)) << 32ULL; >> + save->crtc[idx].saddress = RREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + save->crtc[idx].offset); >> + save->crtc[idx].saddress |= ((uint64_t)RREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + save->crtc[idx].offset)) << 32ULL; >> + save->crtc[idx].crtc_control = RREG32(EVERGREEN_CRTC_CONTROL + save->crtc[idx].offset); >> + /* We need to disable all crtc as for some reason crtc scanout >> + * base address does not happen properly when changing the >> + * mc vram start address. Don't remove this or you will break >> + * things on uefi system. >> + */ >> + save->crtc[idx].crtc_control = 0; >> + save->crtc[idx].vga_control = RREG32(save->crtc[idx].vga_control_offset); >> + >> + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + save->crtc[idx].offset, 1); >> + WREG32(EVERGREEN_CRTC_CONTROL + save->crtc[idx].offset, 0); >> + WREG32(save->crtc[idx].vga_control_offset, 0); >> + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + save->crtc[idx].offset, 0); >> +} >> + >> void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save) >> { >> - save->vga_control[0] = RREG32(D1VGA_CONTROL); >> - save->vga_control[1] = RREG32(D2VGA_CONTROL); >> + save->crtc[0].offset = EVERGREEN_CRTC0_REGISTER_OFFSET; >> + save->crtc[1].offset = EVERGREEN_CRTC1_REGISTER_OFFSET; >> + save->crtc[2].offset = EVERGREEN_CRTC2_REGISTER_OFFSET; >> + save->crtc[3].offset = EVERGREEN_CRTC3_REGISTER_OFFSET; >> + save->crtc[4].offset = EVERGREEN_CRTC4_REGISTER_OFFSET; >> + save->crtc[5].offset = EVERGREEN_CRTC5_REGISTER_OFFSET; >> + save->crtc[0].vga_control_offset = D1VGA_CONTROL; >> + save->crtc[1].vga_control_offset = D2VGA_CONTROL; >> + save->crtc[2].vga_control_offset = EVERGREEN_D3VGA_CONTROL; >> + save->crtc[3].vga_control_offset = EVERGREEN_D4VGA_CONTROL; >> + save->crtc[4].vga_control_offset = EVERGREEN_D5VGA_CONTROL; >> + save->crtc[5].vga_control_offset = EVERGREEN_D6VGA_CONTROL; >> + >> + save->fb_address = (uint64_t)(RREG32(MC_VM_FB_LOCATION) & 0xffff) << 24ULL; >> save->vga_render_control = RREG32(VGA_RENDER_CONTROL); >> save->vga_hdp_control = RREG32(VGA_HDP_CONTROL); >> - save->crtc_control[0] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET); >> - save->crtc_control[1] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET); >> - if (rdev->num_crtc >= 4) { >> - save->vga_control[2] = RREG32(EVERGREEN_D3VGA_CONTROL); >> - save->vga_control[3] = RREG32(EVERGREEN_D4VGA_CONTROL); >> - save->crtc_control[2] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET); >> - save->crtc_control[3] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET); >> - } >> - if (rdev->num_crtc >= 6) { >> - save->vga_control[4] = RREG32(EVERGREEN_D5VGA_CONTROL); >> - save->vga_control[5] = RREG32(EVERGREEN_D6VGA_CONTROL); >> - save->crtc_control[4] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET); >> - save->crtc_control[5] = RREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET); >> - } >> >> /* Stop all video */ >> WREG32(VGA_RENDER_CONTROL, 0); >> - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 1); >> - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 1); >> - if (rdev->num_crtc >= 4) { >> - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 1); >> - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 1); >> - } >> - if (rdev->num_crtc >= 6) { >> - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 1); >> - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 1); >> - } >> - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); >> - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); >> - if (rdev->num_crtc >= 4) { >> - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); >> - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); >> - } >> - if (rdev->num_crtc >= 6) { >> - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); >> - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); >> - } >> - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); >> - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); >> - if (rdev->num_crtc >= 4) { >> - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); >> - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); >> - } >> - if (rdev->num_crtc >= 6) { >> - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); >> - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); >> + evergreen_crtc_save(rdev, save, 0); >> + evergreen_crtc_save(rdev, save, 1); >> + evergreen_crtc_save(rdev, save, 2); >> + evergreen_crtc_save(rdev, save, 3); >> + evergreen_crtc_save(rdev, save, 4); >> + evergreen_crtc_save(rdev, save, 5); >> +} >> + >> +static void evergreen_crtc_restore(struct radeon_device *rdev, struct evergreen_mc_save *save, unsigned idx) >> +{ >> + if (idx >= rdev->num_crtc) { >> + /* it seems accessing non existant crtc trigger high latency */ >> + return; >> } >> >> - WREG32(D1VGA_CONTROL, 0); >> - WREG32(D2VGA_CONTROL, 0); >> - if (rdev->num_crtc >= 4) { >> - WREG32(EVERGREEN_D3VGA_CONTROL, 0); >> - WREG32(EVERGREEN_D4VGA_CONTROL, 0); >> + /* update new primary and secondary address */ >> + if (save->crtc[idx].paddress) { >> + save->crtc[idx].paddress -= save->fb_address; >> } >> - if (rdev->num_crtc >= 6) { >> - WREG32(EVERGREEN_D5VGA_CONTROL, 0); >> - WREG32(EVERGREEN_D6VGA_CONTROL, 0); >> + save->crtc[idx].paddress += rdev->mc.vram_start; >> + if (save->crtc[idx].saddress) { >> + save->crtc[idx].saddress -= save->fb_address; >> } >> + save->crtc[idx].saddress += rdev->mc.vram_start; >> + >> + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + save->crtc[idx].offset, 1); >> + WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + save->crtc[idx].offset, lower_32_bits(save->crtc[idx].paddress)); >> + WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + save->crtc[idx].offset, upper_32_bits(save->crtc[idx].paddress) & 0xff); >> + WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS + save->crtc[idx].offset, lower_32_bits(save->crtc[idx].saddress)); >> + WREG32(EVERGREEN_GRPH_SECONDARY_SURFACE_ADDRESS_HIGH + save->crtc[idx].offset, upper_32_bits(save->crtc[idx].saddress) & 0xff); >> + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + save->crtc[idx].offset, 0); >> + WREG32(EVERGREEN_MASTER_UPDATE_MODE + save->crtc[idx].offset, 0); >> + >> + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + save->crtc[idx].offset, 1); >> + WREG32(save->crtc[idx].vga_control_offset, save->crtc[idx].vga_control); >> + WREG32(EVERGREEN_CRTC_CONTROL + save->crtc[idx].offset, save->crtc[idx].crtc_control | EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE); >> + WREG32(EVERGREEN_CRTC_UPDATE_LOCK + save->crtc[idx].offset, 0); >> } >> >> void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save) >> @@ -1357,47 +1381,15 @@ void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *s >> /* Unlock host access */ >> WREG32(VGA_HDP_CONTROL, save->vga_hdp_control); >> mdelay(1); >> + >> /* Restore video state */ >> - WREG32(D1VGA_CONTROL, save->vga_control[0]); >> - WREG32(D2VGA_CONTROL, save->vga_control[1]); >> - if (rdev->num_crtc >= 4) { >> - WREG32(EVERGREEN_D3VGA_CONTROL, save->vga_control[2]); >> - WREG32(EVERGREEN_D4VGA_CONTROL, save->vga_control[3]); >> - } >> - if (rdev->num_crtc >= 6) { >> - WREG32(EVERGREEN_D5VGA_CONTROL, save->vga_control[4]); >> - WREG32(EVERGREEN_D6VGA_CONTROL, save->vga_control[5]); >> - } >> - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 1); >> - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 1); >> - if (rdev->num_crtc >= 4) { >> - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 1); >> - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 1); >> - } >> - if (rdev->num_crtc >= 6) { >> - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 1); >> - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 1); >> - } >> - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC0_REGISTER_OFFSET, save->crtc_control[0]); >> - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC1_REGISTER_OFFSET, save->crtc_control[1]); >> - if (rdev->num_crtc >= 4) { >> - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC2_REGISTER_OFFSET, save->crtc_control[2]); >> - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC3_REGISTER_OFFSET, save->crtc_control[3]); >> - } >> - if (rdev->num_crtc >= 6) { >> - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC4_REGISTER_OFFSET, save->crtc_control[4]); >> - WREG32(EVERGREEN_CRTC_CONTROL + EVERGREEN_CRTC5_REGISTER_OFFSET, save->crtc_control[5]); >> - } >> - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC0_REGISTER_OFFSET, 0); >> - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC1_REGISTER_OFFSET, 0); >> - if (rdev->num_crtc >= 4) { >> - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC2_REGISTER_OFFSET, 0); >> - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC3_REGISTER_OFFSET, 0); >> - } >> - if (rdev->num_crtc >= 6) { >> - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC4_REGISTER_OFFSET, 0); >> - WREG32(EVERGREEN_CRTC_UPDATE_LOCK + EVERGREEN_CRTC5_REGISTER_OFFSET, 0); >> - } >> + evergreen_crtc_restore(rdev, save, 0); >> + evergreen_crtc_restore(rdev, save, 1); >> + evergreen_crtc_restore(rdev, save, 2); >> + evergreen_crtc_restore(rdev, save, 3); >> + evergreen_crtc_restore(rdev, save, 4); >> + evergreen_crtc_restore(rdev, save, 5); >> + >> WREG32(VGA_RENDER_CONTROL, save->vga_render_control); >> } >> >> diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h >> index f4af243..d450218 100644 >> --- a/drivers/gpu/drm/radeon/radeon_asic.h >> +++ b/drivers/gpu/drm/radeon/radeon_asic.h >> @@ -388,12 +388,22 @@ void r700_cp_fini(struct radeon_device *rdev); >> /* >> * evergreen >> */ >> +struct evergreen_crtc_save { >> + uint64_t paddress; >> + uint64_t saddress; >> + uint32_t crtc_control; >> + uint32_t vga_control; >> + uint32_t offset; >> + uint32_t vga_control_offset; >> +}; >> + >> struct evergreen_mc_save { >> - u32 vga_control[6]; >> - u32 vga_render_control; >> - u32 vga_hdp_control; >> - u32 crtc_control[6]; >> + struct evergreen_crtc_save crtc[RADEON_MAX_CRTCS]; >> + uint64_t fb_address; >> + uint32_t vga_render_control; >> + uint32_t vga_hdp_control; >> }; >> + >> void evergreen_pcie_gart_tlb_flush(struct radeon_device *rdev); >> int evergreen_init(struct radeon_device *rdev); >> void evergreen_fini(struct radeon_device *rdev); >> -- >> 1.7.10.4 >> >> _______________________________________________ >> dri-devel mailing list >> dri-devel@xxxxxxxxxxxxxxxxxxxxx >> http://lists.freedesktop.org/mailman/listinfo/dri-devel _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx http://lists.freedesktop.org/mailman/listinfo/dri-devel