From patchwork Mon Mar 22 18:57:39 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Matthew Garrett X-Patchwork-Id: 87487 Received: from lists.sourceforge.net (lists.sourceforge.net [216.34.181.88]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o2MIxBqF025522 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Mon, 22 Mar 2010 18:59:51 GMT Received: from localhost ([127.0.0.1] helo=sfs-ml-2.v29.ch3.sourceforge.com) by sfs-ml-2.v29.ch3.sourceforge.com with esmtp (Exim 4.69) (envelope-from ) id 1NtmpD-0002k3-FA; Mon, 22 Mar 2010 18:58:07 +0000 Received: from sfi-mx-1.v28.ch3.sourceforge.com ([172.29.28.121] helo=mx.sourceforge.net) by sfs-ml-2.v29.ch3.sourceforge.com with esmtp (Exim 4.69) (envelope-from ) id 1NtmpB-0002jk-P6 for dri-devel@lists.sourceforge.net; Mon, 22 Mar 2010 18:58:05 +0000 Received-SPF: pass (sfi-mx-1.v28.ch3.sourceforge.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=mjg@redhat.com; helo=mx1.redhat.com; Received: from mx1.redhat.com ([209.132.183.28]) by sfi-mx-1.v28.ch3.sourceforge.com with esmtp (Exim 4.69) id 1NtmpA-00056f-GJ for dri-devel@lists.sourceforge.net; Mon, 22 Mar 2010 18:58:05 +0000 Received: from int-mx08.intmail.prod.int.phx2.redhat.com (int-mx08.intmail.prod.int.phx2.redhat.com [10.5.11.21]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o2MIvnlr002775 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Mon, 22 Mar 2010 14:57:51 -0400 Received: from cavan.codon.org.uk (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) by int-mx08.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id o2MIvmnu019997 (version=TLSv1/SSLv3 cipher=AES256-SHA bits=256 verify=NO); Mon, 22 Mar 2010 14:57:49 -0400 Received: from lan-nat-pool-bos.redhat.com ([66.187.234.200] helo=localhost.localdomain) by cavan.codon.org.uk with esmtpsa (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.69) (envelope-from ) id 1Ntmos-0001yh-Ux; Mon, 22 Mar 2010 18:57:47 +0000 From: Matthew Garrett To: dri-devel@lists.sourceforge.net Subject: [PATCH 3/4] radeon: Reclock r520 memory by hand Date: Mon, 22 Mar 2010 14:57:39 -0400 Message-Id: <1269284260-12224-3-git-send-email-mjg@redhat.com> In-Reply-To: <1269284260-12224-2-git-send-email-mjg@redhat.com> References: <1269284260-12224-1-git-send-email-mjg@redhat.com> <1269284260-12224-2-git-send-email-mjg@redhat.com> X-SA-Do-Not-Run: Yes X-SA-Exim-Connect-IP: 66.187.234.200 X-SA-Exim-Mail-From: mjg@redhat.com X-SA-Exim-Scanned: No (on cavan.codon.org.uk); SAEximRunCond expanded to false X-Scanned-By: MIMEDefang 2.67 on 10.5.11.21 X-Spam-Score: -1.1 (-) X-Spam-Report: Spam Filtering performed by mx.sourceforge.net. See http://spamassassin.org/tag/ for more details. -1.5 SPF_CHECK_PASS SPF reports sender host as permitted sender for sender-domain -0.0 SPF_HELO_PASS SPF: HELO matches SPF record -0.0 SPF_PASS SPF: sender matches SPF record 0.4 AWL AWL: From: address is in the auto white-list X-Headers-End: 1NtmpA-00056f-GJ Cc: alexdeucher@gmail.com, Matthew Garrett X-BeenThere: dri-devel@lists.sourceforge.net X-Mailman-Version: 2.1.9 Precedence: list List-Id: Direct Rendering Infrastructure - Development List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: dri-devel-bounces@lists.sourceforge.net X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Mon, 22 Mar 2010 18:59:52 +0000 (UTC) diff --git a/drivers/gpu/drm/radeon/r500_reg.h b/drivers/gpu/drm/radeon/r500_reg.h index 0cf2ad2..b3e798f 100644 --- a/drivers/gpu/drm/radeon/r500_reg.h +++ b/drivers/gpu/drm/radeon/r500_reg.h @@ -258,7 +258,7 @@ #define R520_MC_AGP_TOP_SHIFT 16 #define R520_MC_AGP_BASE 0x06 #define R520_MC_AGP_BASE_2 0x07 - +#define R520_MC_ARB_RATIO_CLK_SEQ 0x16 #define AVIVO_MC_INDEX 0x0070 #define R520_MC_STATUS 0x00 @@ -279,6 +279,8 @@ # define R520_MEM_NUM_CHANNELS_SHIFT 24 # define R520_MC_CHANNEL_SIZE (1 << 23) +#define AVIVO_SPLL_FUNC_CNTL 0x0000 /* PLL */ +#define AVIVO_MPLL_FUNC_CNTL 0x0004 /* PLL */ #define AVIVO_CP_DYN_CNTL 0x000f /* PLL */ # define AVIVO_CP_FORCEON (1 << 0) #define AVIVO_E2_DYN_CNTL 0x0011 /* PLL */ diff --git a/drivers/gpu/drm/radeon/r520.c b/drivers/gpu/drm/radeon/r520.c index 870111e..fda7c11 100644 --- a/drivers/gpu/drm/radeon/r520.c +++ b/drivers/gpu/drm/radeon/r520.c @@ -26,6 +26,8 @@ * Jerome Glisse */ #include "drmP.h" +#include "radeon_drm.h" +#include "radeon_drv.h" #include "radeon.h" #include "radeon_asic.h" #include "atom.h" @@ -127,6 +129,8 @@ void r520_mc_init(struct radeon_device *rdev) radeon_vram_location(rdev, &rdev->mc, 0); if (!(rdev->flags & RADEON_IS_AGP)) radeon_gtt_location(rdev, &rdev->mc); + rdev->clock.fbdiv = + (RADEON_READ_PLL(rdev->ddev, AVIVO_MPLL_FUNC_CNTL) & 0x1fe0) >> 5; radeon_update_bandwidth_info(rdev); } @@ -303,3 +307,38 @@ int r520_init(struct radeon_device *rdev) } return 0; } + +void r520_set_memory_clock(struct radeon_device *rdev, uint32_t mem_clock) +{ + int mpll, spll, hclk, sclk, fbdiv, index, factor; + struct drm_radeon_private *dev_priv = rdev->ddev->dev_private; + + mpll = RADEON_READ_PLL(rdev->ddev, AVIVO_MPLL_FUNC_CNTL); + fbdiv = (mpll & 0x1fe0) >> 5; + + /* Set new fbdiv */ + factor = rdev->clock.default_mclk / mem_clock; + fbdiv = rdev->clock.fbdiv / factor; + + mpll &= ~0x1fe0; + mpll |= ((fbdiv << 5) | (1 << 24)); + mpll &= ~(1 << 25); + + spll = RADEON_READ_PLL(rdev->ddev, AVIVO_SPLL_FUNC_CNTL); + + hclk = fbdiv << 5; + hclk += 0x20; + hclk *= 8; + + sclk = spll * 0x1fe0; + sclk += 0x20; + sclk *= 6; + sclk = sclk >> 5; + + index = hclk/sclk; + + R500_WRITE_MCIND(R520_MC_ARB_RATIO_CLK_SEQ, + rdev->pm.mc_arb_init_values[index]); + RADEON_WRITE_PLL(AVIVO_MPLL_FUNC_CNTL, mpll); + radeon_atom_initialize_memory_controller(rdev); +} diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index ac403e4..d706974 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -163,6 +163,7 @@ struct radeon_clock { uint32_t default_sclk; uint32_t default_dispclk; uint32_t dp_extclk; + uint32_t fbdiv; }; /* @@ -728,6 +729,7 @@ struct radeon_pm { u32 current_sclk; u32 current_mclk; u32 new_mclk; + u32 *mc_arb_init_values; struct radeon_i2c_chan *i2c_bus; /* r6xx+ only */ u32 low_simd_mask; diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index 1df1e89..80487e0 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c @@ -529,7 +529,7 @@ static struct radeon_asic r520_asic = { .get_engine_clock = &radeon_atom_get_engine_clock, .set_engine_clock = &radeon_atom_set_engine_clock, .get_memory_clock = &radeon_atom_get_memory_clock, - .set_memory_clock = &radeon_atom_set_memory_clock, + .set_memory_clock = &r520_set_memory_clock, .get_pcie_lanes = &rv370_get_pcie_lanes, .set_pcie_lanes = &rv370_set_pcie_lanes, .set_clock_gating = &radeon_atom_set_clock_gating, diff --git a/drivers/gpu/drm/radeon/radeon_asic.h b/drivers/gpu/drm/radeon/radeon_asic.h index 7de4947..51ddb60 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.h +++ b/drivers/gpu/drm/radeon/radeon_asic.h @@ -36,10 +36,12 @@ void radeon_legacy_set_engine_clock(struct radeon_device *rdev, uint32_t eng_clo uint32_t radeon_legacy_get_memory_clock(struct radeon_device *rdev); void radeon_legacy_set_clock_gating(struct radeon_device *rdev, int enable); +void radeon_atom_get_mc_arb_info(struct radeon_device *rdev); uint32_t radeon_atom_get_engine_clock(struct radeon_device *rdev); void radeon_atom_set_engine_clock(struct radeon_device *rdev, uint32_t eng_clock); uint32_t radeon_atom_get_memory_clock(struct radeon_device *rdev); void radeon_atom_set_memory_clock(struct radeon_device *rdev, uint32_t mem_clock); +void radeon_atom_initialize_memory_controller(struct radeon_device *rdev); void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable); /* @@ -232,6 +234,7 @@ int rv515_suspend(struct radeon_device *rdev); */ int r520_init(struct radeon_device *rdev); int r520_resume(struct radeon_device *rdev); +void r520_set_memory_clock(struct radeon_device *rdev, uint32_t mem_clock); /* * r600,rv610,rv630,rv620,rv635,rv670,rs780,rs880 diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 0af81b7..5b964e2 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -1901,6 +1901,19 @@ void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable) atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); } +void radeon_atom_get_mc_arb_info(struct radeon_device *rdev) +{ + int index = GetIndexIntoMasterTable(DATA, MC_InitParameter); + u16 size, data_offset; + struct atom_context *ctx = rdev->mode_info.atom_context; + + if (atom_parse_data_header(ctx, index, &size, NULL, NULL, &data_offset)) { + rdev->pm.mc_arb_init_values = kmalloc(size*sizeof(u32), GFP_KERNEL); + memcpy(rdev->pm.mc_arb_init_values, ctx->bios + data_offset, + size * sizeof(u32)); + } +} + uint32_t radeon_atom_get_engine_clock(struct radeon_device *rdev) { GET_ENGINE_CLOCK_PS_ALLOCATION args; @@ -1944,6 +1957,14 @@ void radeon_atom_set_memory_clock(struct radeon_device *rdev, atom_execute_table_atomic(rdev->mode_info.atom_context, index, (uint32_t *)&args); } +void radeon_atom_initialize_memory_controller(struct radeon_device *rdev) +{ + int index = GetIndexIntoMasterTable(COMMAND, MemoryDeviceInit); + MEMORY_PLLINIT_PS_ALLOCATION args; + + atom_execute_table_atomic(rdev->mode_info.atom_context, index, (uint32_t *)&args); +} + void radeon_atom_initialize_bios_scratch_regs(struct drm_device *dev) { struct radeon_device *rdev = dev->dev_private; diff --git a/drivers/gpu/drm/radeon/radeon_cp.c b/drivers/gpu/drm/radeon/radeon_cp.c index dc6eba6..d22e832 100644 --- a/drivers/gpu/drm/radeon/radeon_cp.c +++ b/drivers/gpu/drm/radeon/radeon_cp.c @@ -292,7 +292,7 @@ void radeon_enable_bm(struct drm_radeon_private *dev_priv) } /* PCIE cards appears to not need this */ } -static int RADEON_READ_PLL(struct drm_device * dev, int addr) +int RADEON_READ_PLL(struct drm_device *dev, int addr) { drm_radeon_private_t *dev_priv = dev->dev_private; diff --git a/drivers/gpu/drm/radeon/radeon_drv.h b/drivers/gpu/drm/radeon/radeon_drv.h index ec55f2b..43fd3b9 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.h +++ b/drivers/gpu/drm/radeon/radeon_drv.h @@ -1859,6 +1859,7 @@ do { \ #define RADEON_READ8(reg) DRM_READ8( dev_priv->mmio, (reg) ) #define RADEON_WRITE8(reg,val) DRM_WRITE8( dev_priv->mmio, (reg), (val) ) +int RADEON_READ_PLL(struct drm_device *dev, int addr); #define RADEON_WRITE_PLL(addr, val) \ do { \ RADEON_WRITE8(RADEON_CLOCK_CNTL_INDEX, \ diff --git a/drivers/gpu/drm/radeon/radeon_pm.c b/drivers/gpu/drm/radeon/radeon_pm.c index 3f4beef..745475f 100644 --- a/drivers/gpu/drm/radeon/radeon_pm.c +++ b/drivers/gpu/drm/radeon/radeon_pm.c @@ -23,6 +23,7 @@ #include "drmP.h" #include "radeon.h" #include "avivod.h" +#include "radeon_asic.h" #define RADEON_IDLE_LOOP_MS 100 #define RADEON_RECLOCK_DELAY_MS 200 @@ -100,10 +101,12 @@ int radeon_pm_init(struct radeon_device *rdev) rdev->pm.can_downclock = true; if (rdev->bios) { - if (rdev->is_atom_bios) + if (rdev->is_atom_bios) { radeon_atombios_get_power_modes(rdev); - else + radeon_atom_get_mc_arb_info(rdev); + } else { radeon_combios_get_power_modes(rdev); + } radeon_print_power_mode_info(rdev); } @@ -131,6 +134,7 @@ void radeon_pm_fini(struct radeon_device *rdev) /* reset default clocks */ rdev->pm.state = PM_STATE_DISABLED; rdev->pm.planned_action = PM_ACTION_DEFAULT; + kfree(rdev->pm.mc_arb_init_values); radeon_pm_set_clocks(rdev); }