From patchwork Thu Mar 3 01:07:34 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alex Deucher X-Patchwork-Id: 604651 Received: from gabe.freedesktop.org (gabe.freedesktop.org [131.252.210.177]) by demeter1.kernel.org (8.14.4/8.14.3) with ESMTP id p231CveY024307 for ; Thu, 3 Mar 2011 01:13:18 GMT Received: from gabe.freedesktop.org (localhost [127.0.0.1]) by gabe.freedesktop.org (Postfix) with ESMTP id 91F989F0EE for ; Wed, 2 Mar 2011 17:12:57 -0800 (PST) X-Original-To: dri-devel@lists.freedesktop.org Delivered-To: dri-devel@lists.freedesktop.org Received: from mail-qy0-f177.google.com (mail-qy0-f177.google.com [209.85.216.177]) by gabe.freedesktop.org (Postfix) with ESMTP id 2F1C29E969 for ; Wed, 2 Mar 2011 17:08:07 -0800 (PST) Received: by mail-qy0-f177.google.com with SMTP id 38so576600qyl.15 for ; Wed, 02 Mar 2011 17:08:07 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:from:to:cc:subject:date:message-id:x-mailer :in-reply-to:references; bh=Iy0foKj/QRbx2yEAaTySam8Szt1k6YLl/d4nY/Hk7lk=; b=XJ3MDFdsTyUNnY2GGkjgS/19xRPCW7+zFOf+x15Bdoz/PKdKJhXwFJUu/8u29FuoW9 UZYxAJUJbxulEbPgoWMyoeBaPOZG1UneeD0FOw29XUeoBld6FVtv8XtPLhx+e6a/mSMa oLv4jDODW19nA3KXci23ceSApvUef5ZgmS09M= DomainKey-Signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; b=Rm6OiWM8LdX8q7D6DOChb9onkZOYByWvq6N2mPq1ofSv4E+y46NyqkNZvRRJGY6xVG GTvTL7T5QtHJwkX2vhvsvgMzcwo7olLTGMO5gYLlEA8P2BsCPn4e6zimbjCcXmsHmXz8 p/Qkm0TMw+cUG+5IoAc3lsQz+slfdiTWTuCL4= Received: by 10.224.140.4 with SMTP id g4mr471276qau.334.1299114486857; Wed, 02 Mar 2011 17:08:06 -0800 (PST) Received: from localhost.localdomain (static-74-96-105-7.washdc.fios.verizon.net [74.96.105.7]) by mx.google.com with ESMTPS id p13sm409704qcu.29.2011.03.02.17.08.00 (version=SSLv3 cipher=OTHER); Wed, 02 Mar 2011 17:08:01 -0800 (PST) From: Alex Deucher To: airlied@gmail.com, dri-devel@lists.freedesktop.org Subject: [PATCH 08/15] drm/radeon/kms/cayman: add asic init/startup/fini/suspend/resume functions Date: Wed, 2 Mar 2011 20:07:34 -0500 Message-Id: <1299114461-4289-8-git-send-email-alexdeucher@gmail.com> X-Mailer: git-send-email 1.7.1.1 In-Reply-To: <1299114461-4289-1-git-send-email-alexdeucher@gmail.com> References: <1299114461-4289-1-git-send-email-alexdeucher@gmail.com> X-BeenThere: dri-devel@lists.freedesktop.org X-Mailman-Version: 2.1.11 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 X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.6 (demeter1.kernel.org [140.211.167.41]); Thu, 03 Mar 2011 01:13:20 +0000 (UTC) diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c index 91c0204..9ecb2b6 100644 --- a/drivers/gpu/drm/radeon/evergreen.c +++ b/drivers/gpu/drm/radeon/evergreen.c @@ -1108,7 +1108,7 @@ void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *s WREG32(VGA_RENDER_CONTROL, save->vga_render_control); } -static void evergreen_mc_program(struct radeon_device *rdev) +void evergreen_mc_program(struct radeon_device *rdev) { struct evergreen_mc_save save; u32 tmp; @@ -2577,7 +2577,7 @@ void evergreen_irq_disable(struct radeon_device *rdev) evergreen_disable_interrupt_state(rdev); } -static void evergreen_irq_suspend(struct radeon_device *rdev) +void evergreen_irq_suspend(struct radeon_device *rdev) { evergreen_irq_disable(rdev); r600_rlc_stop(rdev); @@ -2900,7 +2900,7 @@ static int evergreen_startup(struct radeon_device *rdev) return r; } } - r = btc_mc_load_microcode(rdev); + r = ni_mc_load_microcode(rdev); if (r) { DRM_ERROR("Failed to load MC firmware!\n"); return r; @@ -2982,7 +2982,7 @@ int evergreen_resume(struct radeon_device *rdev) r = evergreen_startup(rdev); if (r) { - DRM_ERROR("r600 startup failed on resume\n"); + DRM_ERROR("evergreen startup failed on resume\n"); return r; } @@ -3059,7 +3059,7 @@ int evergreen_init(struct radeon_device *rdev) } /* Must be an ATOMBIOS */ if (!rdev->is_atom_bios) { - dev_err(rdev->dev, "Expecting atombios for R600 GPU\n"); + dev_err(rdev->dev, "Expecting atombios for evergreen GPU\n"); return -EINVAL; } r = radeon_atombios_init(rdev); diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c index 3a3fdf5..227173b 100644 --- a/drivers/gpu/drm/radeon/ni.c +++ b/drivers/gpu/drm/radeon/ni.c @@ -36,6 +36,9 @@ extern void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save); extern void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save); extern int evergreen_mc_wait_for_idle(struct radeon_device *rdev); +extern void evergreen_mc_program(struct radeon_device *rdev); +extern void evergreen_irq_suspend(struct radeon_device *rdev); +extern int evergreen_mc_init(struct radeon_device *rdev); #define EVERGREEN_PFP_UCODE_SIZE 1120 #define EVERGREEN_PM4_UCODE_SIZE 1376 @@ -193,7 +196,7 @@ static const u32 cayman_io_mc_regs[BTC_IO_MC_REGS_SIZE][2] = { {0x0000009f, 0x00976b00} }; -int btc_mc_load_microcode(struct radeon_device *rdev) +int ni_mc_load_microcode(struct radeon_device *rdev) { const __be32 *fw_data; u32 mem_type, running, blackout = 0; @@ -1129,6 +1132,12 @@ static int cayman_cp_start(struct radeon_device *rdev) return 0; } +static void cayman_cp_fini(struct radeon_device *rdev) +{ + cayman_cp_enable(rdev, false); + radeon_ring_fini(rdev); +} + int cayman_cp_resume(struct radeon_device *rdev) { u32 tmp; @@ -1346,3 +1355,233 @@ int cayman_asic_reset(struct radeon_device *rdev) return cayman_gpu_soft_reset(rdev); } +static int cayman_startup(struct radeon_device *rdev) +{ + int r; + + if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw || !rdev->mc_fw) { + r = ni_init_microcode(rdev); + if (r) { + DRM_ERROR("Failed to load firmware!\n"); + return r; + } + } + r = ni_mc_load_microcode(rdev); + if (r) { + DRM_ERROR("Failed to load MC firmware!\n"); + return r; + } + + evergreen_mc_program(rdev); + r = cayman_pcie_gart_enable(rdev); + if (r) + return r; + cayman_gpu_init(rdev); + +#if 0 + r = cayman_blit_init(rdev); + if (r) { + cayman_blit_fini(rdev); + rdev->asic->copy = NULL; + dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r); + } +#endif + + /* allocate wb buffer */ + r = radeon_wb_init(rdev); + if (r) + return r; + + /* Enable IRQ */ + r = r600_irq_init(rdev); + if (r) { + DRM_ERROR("radeon: IH init failed (%d).\n", r); + radeon_irq_kms_fini(rdev); + return r; + } + evergreen_irq_set(rdev); + + r = radeon_ring_init(rdev, rdev->cp.ring_size); + if (r) + return r; + r = cayman_cp_load_microcode(rdev); + if (r) + return r; + r = cayman_cp_resume(rdev); + if (r) + return r; + + return 0; +} + +int cayman_resume(struct radeon_device *rdev) +{ + int r; + + /* Do not reset GPU before posting, on rv770 hw unlike on r500 hw, + * posting will perform necessary task to bring back GPU into good + * shape. + */ + /* post card */ + atom_asic_init(rdev->mode_info.atom_context); + + r = cayman_startup(rdev); + if (r) { + DRM_ERROR("cayman startup failed on resume\n"); + return r; + } + + r = r600_ib_test(rdev); + if (r) { + DRM_ERROR("radeon: failled testing IB (%d).\n", r); + return r; + } + + return r; + +} + +int cayman_suspend(struct radeon_device *rdev) +{ + /* int r; */ + + /* FIXME: we should wait for ring to be empty */ + cayman_cp_enable(rdev, false); + rdev->cp.ready = false; + evergreen_irq_suspend(rdev); + radeon_wb_disable(rdev); + cayman_pcie_gart_disable(rdev); + +#if 0 + /* unpin shaders bo */ + r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); + if (likely(r == 0)) { + radeon_bo_unpin(rdev->r600_blit.shader_obj); + radeon_bo_unreserve(rdev->r600_blit.shader_obj); + } +#endif + return 0; +} + +/* Plan is to move initialization in that function and use + * helper function so that radeon_device_init pretty much + * do nothing more than calling asic specific function. This + * should also allow to remove a bunch of callback function + * like vram_info. + */ +int cayman_init(struct radeon_device *rdev) +{ + int r; + + /* This don't do much */ + r = radeon_gem_init(rdev); + if (r) + return r; + /* Read BIOS */ + if (!radeon_get_bios(rdev)) { + if (ASIC_IS_AVIVO(rdev)) + return -EINVAL; + } + /* Must be an ATOMBIOS */ + if (!rdev->is_atom_bios) { + dev_err(rdev->dev, "Expecting atombios for cayman GPU\n"); + return -EINVAL; + } + r = radeon_atombios_init(rdev); + if (r) + return r; + + /* Post card if necessary */ + if (!radeon_card_posted(rdev)) { + if (!rdev->bios) { + dev_err(rdev->dev, "Card not posted and no BIOS - ignoring\n"); + return -EINVAL; + } + DRM_INFO("GPU not posted. posting now...\n"); + atom_asic_init(rdev->mode_info.atom_context); + } + /* Initialize scratch registers */ + r600_scratch_init(rdev); + /* Initialize surface registers */ + radeon_surface_init(rdev); + /* Initialize clocks */ + radeon_get_clock_info(rdev->ddev); + /* Fence driver */ + r = radeon_fence_driver_init(rdev); + if (r) + return r; + /* initialize memory controller */ + r = evergreen_mc_init(rdev); + if (r) + return r; + /* Memory manager */ + r = radeon_bo_init(rdev); + if (r) + return r; + + r = radeon_irq_kms_init(rdev); + if (r) + return r; + + rdev->cp.ring_obj = NULL; + r600_ring_init(rdev, 1024 * 1024); + + rdev->ih.ring_obj = NULL; + r600_ih_ring_init(rdev, 64 * 1024); + + r = r600_pcie_gart_init(rdev); + if (r) + return r; + + rdev->accel_working = true; + r = cayman_startup(rdev); + if (r) { + dev_err(rdev->dev, "disabling GPU acceleration\n"); + cayman_cp_fini(rdev); + r600_irq_fini(rdev); + radeon_wb_fini(rdev); + radeon_irq_kms_fini(rdev); + cayman_pcie_gart_fini(rdev); + rdev->accel_working = false; + } + if (rdev->accel_working) { + r = radeon_ib_pool_init(rdev); + if (r) { + DRM_ERROR("radeon: failed initializing IB pool (%d).\n", r); + rdev->accel_working = false; + } + r = r600_ib_test(rdev); + if (r) { + DRM_ERROR("radeon: failed testing IB (%d).\n", r); + rdev->accel_working = false; + } + } + + /* Don't start up if the MC ucode is missing. + * The default clocks and voltages before the MC ucode + * is loaded are not suffient for advanced operations. + */ + if (!rdev->mc_fw) { + DRM_ERROR("radeon: MC ucode required for NI+.\n"); + return -EINVAL; + } + + return 0; +} + +void cayman_fini(struct radeon_device *rdev) +{ + /* cayman_blit_fini(rdev); */ + cayman_cp_fini(rdev); + r600_irq_fini(rdev); + radeon_wb_fini(rdev); + radeon_irq_kms_fini(rdev); + cayman_pcie_gart_fini(rdev); + radeon_gem_fini(rdev); + radeon_fence_driver_fini(rdev); + radeon_bo_fini(rdev); + radeon_atombios_fini(rdev); + kfree(rdev->bios); + rdev->bios = NULL; +} + diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 3dbe63a..9ce54e3 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -1549,7 +1549,7 @@ extern int evergreen_blit_init(struct radeon_device *rdev); extern void evergreen_blit_fini(struct radeon_device *rdev); extern int ni_init_microcode(struct radeon_device *rdev); -extern int btc_mc_load_microcode(struct radeon_device *rdev); +extern int ni_mc_load_microcode(struct radeon_device *rdev); /* radeon_acpi.c */ #if defined(CONFIG_ACPI)