Message ID | 1343345088-950-1-git-send-email-j.glisse@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Thu, Jul 26, 2012 at 7:24 PM, <j.glisse@gmail.com> wrote: > From: Jerome Glisse <jglisse@redhat.com> > > 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@vger.kernel.org> this should be stable@vger.kernel.org > Signed-off-by: Jerome Glisse <jglisse@redhat.com> 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@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/dri-devel
On Thu, Jul 26, 2012 at 8:35 PM, Alex Deucher <alexdeucher@gmail.com> wrote: > On Thu, Jul 26, 2012 at 7:24 PM, <j.glisse@gmail.com> wrote: >> From: Jerome Glisse <jglisse@redhat.com> >> >> 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@vger.kernel.org> > > this should be stable@vger.kernel.org > >> Signed-off-by: Jerome Glisse <jglisse@redhat.com> > > 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@lists.freedesktop.org >> http://lists.freedesktop.org/mailman/listinfo/dri-devel
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);