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 > --- > 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