From patchwork Thu Jul 26 23:24:48 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jerome Glisse X-Patchwork-Id: 1246481 Return-Path: X-Original-To: patchwork-dri-devel@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by patchwork1.kernel.org (Postfix) with ESMTP id 266413FDCA for ; Thu, 26 Jul 2012 23:25:26 +0000 (UTC) Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id C4D58A0F2E for ; Thu, 26 Jul 2012 16:25:25 -0700 (PDT) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-yw0-f49.google.com (mail-yw0-f49.google.com [209.85.213.49]) by gabe.freedesktop.org (Postfix) with ESMTP id 9D5149E7EE for ; Thu, 26 Jul 2012 16:25:08 -0700 (PDT) Received: by yhjj52 with SMTP id j52so2725649yhj.36 for ; Thu, 26 Jul 2012 16:25:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer; bh=3i6TKePs8tD0Y2b4PJgn1lSk7Vo710zZ0gHh2G69oko=; b=wpaWoBI8ZbiCo/oyCpz979+eFeX4Kji6EDEoY30IdO0Z10fnHdWuMjbXdqlBHS9Rfy c/3uvoVpDxt0Tg4ZQ5sQbduw+aVZdAhaLG39gnns1W/sPQKqUBoDMHtOeGKnbB0GNkij XhPAB/BaqXOXg/GD/LRHDy2RYyY41lVrB/2oegUpJWNd0Z51PJMKGNAmt0A0XxfDF6uo /shXMVu0PV4udkPrrY/jVL9p3eXZNFW5MPu2tF+sFXUDzqBVU3wZpbWP59X8hLrL9PU5 Z+0AtyTlq0AqJiBoKNhzZ+88g1A8ejUtyepuCngwtQd85ObsMR9poZmU/pGK4vKXXSsz U/6w== Received: by 10.50.10.201 with SMTP id k9mr360438igb.28.1343345107592; Thu, 26 Jul 2012 16:25:07 -0700 (PDT) Received: from homer.localdomain.com ([66.187.233.206]) by mx.google.com with ESMTPS id qo3sm1041106igc.8.2012.07.26.16.25.06 (version=SSLv3 cipher=OTHER); Thu, 26 Jul 2012 16:25:06 -0700 (PDT) From: j.glisse@gmail.com To: dri-devel@lists.freedesktop.org Subject: [PATCH] drm/radeon: cleanup and fix crtc while programming mc Date: Thu, 26 Jul 2012 19:24:48 -0400 Message-Id: <1343345088-950-1-git-send-email-j.glisse@gmail.com> X-Mailer: git-send-email 1.7.10.4 Cc: Jerome Glisse , stable@vger.kernel.org X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: dri-devel-bounces+patchwork-dri-devel=patchwork.kernel.org@lists.freedesktop.org Errors-To: dri-devel-bounces+patchwork-dri-devel=patchwork.kernel.org@lists.freedesktop.org From: Jerome Glisse 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: Signed-off-by: Jerome Glisse --- 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);