162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * Copyright 2008 Advanced Micro Devices, Inc. 362306a36Sopenharmony_ci * Copyright 2008 Red Hat Inc. 462306a36Sopenharmony_ci * Copyright 2009 Jerome Glisse. 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 762306a36Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 862306a36Sopenharmony_ci * to deal in the Software without restriction, including without limitation 962306a36Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 1062306a36Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 1162306a36Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 1262306a36Sopenharmony_ci * 1362306a36Sopenharmony_ci * The above copyright notice and this permission notice shall be included in 1462306a36Sopenharmony_ci * all copies or substantial portions of the Software. 1562306a36Sopenharmony_ci * 1662306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1762306a36Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1862306a36Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1962306a36Sopenharmony_ci * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 2062306a36Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 2162306a36Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 2262306a36Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE. 2362306a36Sopenharmony_ci * 2462306a36Sopenharmony_ci * Authors: Dave Airlie 2562306a36Sopenharmony_ci * Alex Deucher 2662306a36Sopenharmony_ci * Jerome Glisse 2762306a36Sopenharmony_ci */ 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci#include <linux/firmware.h> 3062306a36Sopenharmony_ci#include <linux/module.h> 3162306a36Sopenharmony_ci#include <linux/pci.h> 3262306a36Sopenharmony_ci#include <linux/slab.h> 3362306a36Sopenharmony_ci#include <linux/seq_file.h> 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci#include <drm/drm_device.h> 3662306a36Sopenharmony_ci#include <drm/drm_vblank.h> 3762306a36Sopenharmony_ci#include <drm/radeon_drm.h> 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci#include "atom.h" 4062306a36Sopenharmony_ci#include "avivod.h" 4162306a36Sopenharmony_ci#include "evergreen.h" 4262306a36Sopenharmony_ci#include "r600.h" 4362306a36Sopenharmony_ci#include "r600d.h" 4462306a36Sopenharmony_ci#include "rv770.h" 4562306a36Sopenharmony_ci#include "radeon.h" 4662306a36Sopenharmony_ci#include "radeon_asic.h" 4762306a36Sopenharmony_ci#include "radeon_audio.h" 4862306a36Sopenharmony_ci#include "radeon_mode.h" 4962306a36Sopenharmony_ci#include "radeon_ucode.h" 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci/* Firmware Names */ 5262306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/R600_pfp.bin"); 5362306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/R600_me.bin"); 5462306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/RV610_pfp.bin"); 5562306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/RV610_me.bin"); 5662306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/RV630_pfp.bin"); 5762306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/RV630_me.bin"); 5862306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/RV620_pfp.bin"); 5962306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/RV620_me.bin"); 6062306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/RV635_pfp.bin"); 6162306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/RV635_me.bin"); 6262306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/RV670_pfp.bin"); 6362306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/RV670_me.bin"); 6462306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/RS780_pfp.bin"); 6562306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/RS780_me.bin"); 6662306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/RV770_pfp.bin"); 6762306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/RV770_me.bin"); 6862306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/RV770_smc.bin"); 6962306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/RV730_pfp.bin"); 7062306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/RV730_me.bin"); 7162306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/RV730_smc.bin"); 7262306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/RV740_smc.bin"); 7362306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/RV710_pfp.bin"); 7462306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/RV710_me.bin"); 7562306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/RV710_smc.bin"); 7662306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/R600_rlc.bin"); 7762306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/R700_rlc.bin"); 7862306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/CEDAR_pfp.bin"); 7962306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/CEDAR_me.bin"); 8062306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/CEDAR_rlc.bin"); 8162306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/CEDAR_smc.bin"); 8262306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/REDWOOD_pfp.bin"); 8362306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/REDWOOD_me.bin"); 8462306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/REDWOOD_rlc.bin"); 8562306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/REDWOOD_smc.bin"); 8662306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/JUNIPER_pfp.bin"); 8762306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/JUNIPER_me.bin"); 8862306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/JUNIPER_rlc.bin"); 8962306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/JUNIPER_smc.bin"); 9062306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/CYPRESS_pfp.bin"); 9162306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/CYPRESS_me.bin"); 9262306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/CYPRESS_rlc.bin"); 9362306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/CYPRESS_smc.bin"); 9462306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/PALM_pfp.bin"); 9562306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/PALM_me.bin"); 9662306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/SUMO_rlc.bin"); 9762306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/SUMO_pfp.bin"); 9862306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/SUMO_me.bin"); 9962306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/SUMO2_pfp.bin"); 10062306a36Sopenharmony_ciMODULE_FIRMWARE("radeon/SUMO2_me.bin"); 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_cistatic const u32 crtc_offsets[2] = 10362306a36Sopenharmony_ci{ 10462306a36Sopenharmony_ci 0, 10562306a36Sopenharmony_ci AVIVO_D2CRTC_H_TOTAL - AVIVO_D1CRTC_H_TOTAL 10662306a36Sopenharmony_ci}; 10762306a36Sopenharmony_ci 10862306a36Sopenharmony_cistatic void r600_debugfs_mc_info_init(struct radeon_device *rdev); 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci/* r600,rv610,rv630,rv620,rv635,rv670 */ 11162306a36Sopenharmony_ciint r600_mc_wait_for_idle(struct radeon_device *rdev); 11262306a36Sopenharmony_cistatic void r600_gpu_init(struct radeon_device *rdev); 11362306a36Sopenharmony_civoid r600_fini(struct radeon_device *rdev); 11462306a36Sopenharmony_civoid r600_irq_disable(struct radeon_device *rdev); 11562306a36Sopenharmony_cistatic void r600_pcie_gen2_enable(struct radeon_device *rdev); 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci/* 11862306a36Sopenharmony_ci * Indirect registers accessor 11962306a36Sopenharmony_ci */ 12062306a36Sopenharmony_ciu32 r600_rcu_rreg(struct radeon_device *rdev, u32 reg) 12162306a36Sopenharmony_ci{ 12262306a36Sopenharmony_ci unsigned long flags; 12362306a36Sopenharmony_ci u32 r; 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ci spin_lock_irqsave(&rdev->rcu_idx_lock, flags); 12662306a36Sopenharmony_ci WREG32(R600_RCU_INDEX, ((reg) & 0x1fff)); 12762306a36Sopenharmony_ci r = RREG32(R600_RCU_DATA); 12862306a36Sopenharmony_ci spin_unlock_irqrestore(&rdev->rcu_idx_lock, flags); 12962306a36Sopenharmony_ci return r; 13062306a36Sopenharmony_ci} 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_civoid r600_rcu_wreg(struct radeon_device *rdev, u32 reg, u32 v) 13362306a36Sopenharmony_ci{ 13462306a36Sopenharmony_ci unsigned long flags; 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci spin_lock_irqsave(&rdev->rcu_idx_lock, flags); 13762306a36Sopenharmony_ci WREG32(R600_RCU_INDEX, ((reg) & 0x1fff)); 13862306a36Sopenharmony_ci WREG32(R600_RCU_DATA, (v)); 13962306a36Sopenharmony_ci spin_unlock_irqrestore(&rdev->rcu_idx_lock, flags); 14062306a36Sopenharmony_ci} 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ciu32 r600_uvd_ctx_rreg(struct radeon_device *rdev, u32 reg) 14362306a36Sopenharmony_ci{ 14462306a36Sopenharmony_ci unsigned long flags; 14562306a36Sopenharmony_ci u32 r; 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci spin_lock_irqsave(&rdev->uvd_idx_lock, flags); 14862306a36Sopenharmony_ci WREG32(R600_UVD_CTX_INDEX, ((reg) & 0x1ff)); 14962306a36Sopenharmony_ci r = RREG32(R600_UVD_CTX_DATA); 15062306a36Sopenharmony_ci spin_unlock_irqrestore(&rdev->uvd_idx_lock, flags); 15162306a36Sopenharmony_ci return r; 15262306a36Sopenharmony_ci} 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_civoid r600_uvd_ctx_wreg(struct radeon_device *rdev, u32 reg, u32 v) 15562306a36Sopenharmony_ci{ 15662306a36Sopenharmony_ci unsigned long flags; 15762306a36Sopenharmony_ci 15862306a36Sopenharmony_ci spin_lock_irqsave(&rdev->uvd_idx_lock, flags); 15962306a36Sopenharmony_ci WREG32(R600_UVD_CTX_INDEX, ((reg) & 0x1ff)); 16062306a36Sopenharmony_ci WREG32(R600_UVD_CTX_DATA, (v)); 16162306a36Sopenharmony_ci spin_unlock_irqrestore(&rdev->uvd_idx_lock, flags); 16262306a36Sopenharmony_ci} 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci/** 16562306a36Sopenharmony_ci * r600_get_allowed_info_register - fetch the register for the info ioctl 16662306a36Sopenharmony_ci * 16762306a36Sopenharmony_ci * @rdev: radeon_device pointer 16862306a36Sopenharmony_ci * @reg: register offset in bytes 16962306a36Sopenharmony_ci * @val: register value 17062306a36Sopenharmony_ci * 17162306a36Sopenharmony_ci * Returns 0 for success or -EINVAL for an invalid register 17262306a36Sopenharmony_ci * 17362306a36Sopenharmony_ci */ 17462306a36Sopenharmony_ciint r600_get_allowed_info_register(struct radeon_device *rdev, 17562306a36Sopenharmony_ci u32 reg, u32 *val) 17662306a36Sopenharmony_ci{ 17762306a36Sopenharmony_ci switch (reg) { 17862306a36Sopenharmony_ci case GRBM_STATUS: 17962306a36Sopenharmony_ci case GRBM_STATUS2: 18062306a36Sopenharmony_ci case R_000E50_SRBM_STATUS: 18162306a36Sopenharmony_ci case DMA_STATUS_REG: 18262306a36Sopenharmony_ci case UVD_STATUS: 18362306a36Sopenharmony_ci *val = RREG32(reg); 18462306a36Sopenharmony_ci return 0; 18562306a36Sopenharmony_ci default: 18662306a36Sopenharmony_ci return -EINVAL; 18762306a36Sopenharmony_ci } 18862306a36Sopenharmony_ci} 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci/** 19162306a36Sopenharmony_ci * r600_get_xclk - get the xclk 19262306a36Sopenharmony_ci * 19362306a36Sopenharmony_ci * @rdev: radeon_device pointer 19462306a36Sopenharmony_ci * 19562306a36Sopenharmony_ci * Returns the reference clock used by the gfx engine 19662306a36Sopenharmony_ci * (r6xx, IGPs, APUs). 19762306a36Sopenharmony_ci */ 19862306a36Sopenharmony_ciu32 r600_get_xclk(struct radeon_device *rdev) 19962306a36Sopenharmony_ci{ 20062306a36Sopenharmony_ci return rdev->clock.spll.reference_freq; 20162306a36Sopenharmony_ci} 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ciint r600_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk) 20462306a36Sopenharmony_ci{ 20562306a36Sopenharmony_ci unsigned fb_div = 0, ref_div, vclk_div = 0, dclk_div = 0; 20662306a36Sopenharmony_ci int r; 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci /* bypass vclk and dclk with bclk */ 20962306a36Sopenharmony_ci WREG32_P(CG_UPLL_FUNC_CNTL_2, 21062306a36Sopenharmony_ci VCLK_SRC_SEL(1) | DCLK_SRC_SEL(1), 21162306a36Sopenharmony_ci ~(VCLK_SRC_SEL_MASK | DCLK_SRC_SEL_MASK)); 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci /* assert BYPASS_EN, deassert UPLL_RESET, UPLL_SLEEP and UPLL_CTLREQ */ 21462306a36Sopenharmony_ci WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_BYPASS_EN_MASK, ~( 21562306a36Sopenharmony_ci UPLL_RESET_MASK | UPLL_SLEEP_MASK | UPLL_CTLREQ_MASK)); 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci if (rdev->family >= CHIP_RS780) 21862306a36Sopenharmony_ci WREG32_P(GFX_MACRO_BYPASS_CNTL, UPLL_BYPASS_CNTL, 21962306a36Sopenharmony_ci ~UPLL_BYPASS_CNTL); 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci if (!vclk || !dclk) { 22262306a36Sopenharmony_ci /* keep the Bypass mode, put PLL to sleep */ 22362306a36Sopenharmony_ci WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_SLEEP_MASK, ~UPLL_SLEEP_MASK); 22462306a36Sopenharmony_ci return 0; 22562306a36Sopenharmony_ci } 22662306a36Sopenharmony_ci 22762306a36Sopenharmony_ci if (rdev->clock.spll.reference_freq == 10000) 22862306a36Sopenharmony_ci ref_div = 34; 22962306a36Sopenharmony_ci else 23062306a36Sopenharmony_ci ref_div = 4; 23162306a36Sopenharmony_ci 23262306a36Sopenharmony_ci r = radeon_uvd_calc_upll_dividers(rdev, vclk, dclk, 50000, 160000, 23362306a36Sopenharmony_ci ref_div + 1, 0xFFF, 2, 30, ~0, 23462306a36Sopenharmony_ci &fb_div, &vclk_div, &dclk_div); 23562306a36Sopenharmony_ci if (r) 23662306a36Sopenharmony_ci return r; 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci if (rdev->family >= CHIP_RV670 && rdev->family < CHIP_RS780) 23962306a36Sopenharmony_ci fb_div >>= 1; 24062306a36Sopenharmony_ci else 24162306a36Sopenharmony_ci fb_div |= 1; 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci r = radeon_uvd_send_upll_ctlreq(rdev, CG_UPLL_FUNC_CNTL); 24462306a36Sopenharmony_ci if (r) 24562306a36Sopenharmony_ci return r; 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci /* assert PLL_RESET */ 24862306a36Sopenharmony_ci WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_RESET_MASK, ~UPLL_RESET_MASK); 24962306a36Sopenharmony_ci 25062306a36Sopenharmony_ci /* For RS780 we have to choose ref clk */ 25162306a36Sopenharmony_ci if (rdev->family >= CHIP_RS780) 25262306a36Sopenharmony_ci WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_REFCLK_SRC_SEL_MASK, 25362306a36Sopenharmony_ci ~UPLL_REFCLK_SRC_SEL_MASK); 25462306a36Sopenharmony_ci 25562306a36Sopenharmony_ci /* set the required fb, ref and post divder values */ 25662306a36Sopenharmony_ci WREG32_P(CG_UPLL_FUNC_CNTL, 25762306a36Sopenharmony_ci UPLL_FB_DIV(fb_div) | 25862306a36Sopenharmony_ci UPLL_REF_DIV(ref_div), 25962306a36Sopenharmony_ci ~(UPLL_FB_DIV_MASK | UPLL_REF_DIV_MASK)); 26062306a36Sopenharmony_ci WREG32_P(CG_UPLL_FUNC_CNTL_2, 26162306a36Sopenharmony_ci UPLL_SW_HILEN(vclk_div >> 1) | 26262306a36Sopenharmony_ci UPLL_SW_LOLEN((vclk_div >> 1) + (vclk_div & 1)) | 26362306a36Sopenharmony_ci UPLL_SW_HILEN2(dclk_div >> 1) | 26462306a36Sopenharmony_ci UPLL_SW_LOLEN2((dclk_div >> 1) + (dclk_div & 1)) | 26562306a36Sopenharmony_ci UPLL_DIVEN_MASK | UPLL_DIVEN2_MASK, 26662306a36Sopenharmony_ci ~UPLL_SW_MASK); 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci /* give the PLL some time to settle */ 26962306a36Sopenharmony_ci mdelay(15); 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci /* deassert PLL_RESET */ 27262306a36Sopenharmony_ci WREG32_P(CG_UPLL_FUNC_CNTL, 0, ~UPLL_RESET_MASK); 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_ci mdelay(15); 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci /* deassert BYPASS EN */ 27762306a36Sopenharmony_ci WREG32_P(CG_UPLL_FUNC_CNTL, 0, ~UPLL_BYPASS_EN_MASK); 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci if (rdev->family >= CHIP_RS780) 28062306a36Sopenharmony_ci WREG32_P(GFX_MACRO_BYPASS_CNTL, 0, ~UPLL_BYPASS_CNTL); 28162306a36Sopenharmony_ci 28262306a36Sopenharmony_ci r = radeon_uvd_send_upll_ctlreq(rdev, CG_UPLL_FUNC_CNTL); 28362306a36Sopenharmony_ci if (r) 28462306a36Sopenharmony_ci return r; 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci /* switch VCLK and DCLK selection */ 28762306a36Sopenharmony_ci WREG32_P(CG_UPLL_FUNC_CNTL_2, 28862306a36Sopenharmony_ci VCLK_SRC_SEL(2) | DCLK_SRC_SEL(2), 28962306a36Sopenharmony_ci ~(VCLK_SRC_SEL_MASK | DCLK_SRC_SEL_MASK)); 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci mdelay(100); 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci return 0; 29462306a36Sopenharmony_ci} 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_civoid dce3_program_fmt(struct drm_encoder *encoder) 29762306a36Sopenharmony_ci{ 29862306a36Sopenharmony_ci struct drm_device *dev = encoder->dev; 29962306a36Sopenharmony_ci struct radeon_device *rdev = dev->dev_private; 30062306a36Sopenharmony_ci struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 30162306a36Sopenharmony_ci struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); 30262306a36Sopenharmony_ci struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); 30362306a36Sopenharmony_ci int bpc = 0; 30462306a36Sopenharmony_ci u32 tmp = 0; 30562306a36Sopenharmony_ci enum radeon_connector_dither dither = RADEON_FMT_DITHER_DISABLE; 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci if (connector) { 30862306a36Sopenharmony_ci struct radeon_connector *radeon_connector = to_radeon_connector(connector); 30962306a36Sopenharmony_ci bpc = radeon_get_monitor_bpc(connector); 31062306a36Sopenharmony_ci dither = radeon_connector->dither; 31162306a36Sopenharmony_ci } 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci /* LVDS FMT is set up by atom */ 31462306a36Sopenharmony_ci if (radeon_encoder->devices & ATOM_DEVICE_LCD_SUPPORT) 31562306a36Sopenharmony_ci return; 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci /* not needed for analog */ 31862306a36Sopenharmony_ci if ((radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1) || 31962306a36Sopenharmony_ci (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2)) 32062306a36Sopenharmony_ci return; 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci if (bpc == 0) 32362306a36Sopenharmony_ci return; 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci switch (bpc) { 32662306a36Sopenharmony_ci case 6: 32762306a36Sopenharmony_ci if (dither == RADEON_FMT_DITHER_ENABLE) 32862306a36Sopenharmony_ci /* XXX sort out optimal dither settings */ 32962306a36Sopenharmony_ci tmp |= FMT_SPATIAL_DITHER_EN; 33062306a36Sopenharmony_ci else 33162306a36Sopenharmony_ci tmp |= FMT_TRUNCATE_EN; 33262306a36Sopenharmony_ci break; 33362306a36Sopenharmony_ci case 8: 33462306a36Sopenharmony_ci if (dither == RADEON_FMT_DITHER_ENABLE) 33562306a36Sopenharmony_ci /* XXX sort out optimal dither settings */ 33662306a36Sopenharmony_ci tmp |= (FMT_SPATIAL_DITHER_EN | FMT_SPATIAL_DITHER_DEPTH); 33762306a36Sopenharmony_ci else 33862306a36Sopenharmony_ci tmp |= (FMT_TRUNCATE_EN | FMT_TRUNCATE_DEPTH); 33962306a36Sopenharmony_ci break; 34062306a36Sopenharmony_ci case 10: 34162306a36Sopenharmony_ci default: 34262306a36Sopenharmony_ci /* not needed */ 34362306a36Sopenharmony_ci break; 34462306a36Sopenharmony_ci } 34562306a36Sopenharmony_ci 34662306a36Sopenharmony_ci WREG32(FMT_BIT_DEPTH_CONTROL + radeon_crtc->crtc_offset, tmp); 34762306a36Sopenharmony_ci} 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci/* get temperature in millidegrees */ 35062306a36Sopenharmony_ciint rv6xx_get_temp(struct radeon_device *rdev) 35162306a36Sopenharmony_ci{ 35262306a36Sopenharmony_ci u32 temp = (RREG32(CG_THERMAL_STATUS) & ASIC_T_MASK) >> 35362306a36Sopenharmony_ci ASIC_T_SHIFT; 35462306a36Sopenharmony_ci int actual_temp = temp & 0xff; 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci if (temp & 0x100) 35762306a36Sopenharmony_ci actual_temp -= 256; 35862306a36Sopenharmony_ci 35962306a36Sopenharmony_ci return actual_temp * 1000; 36062306a36Sopenharmony_ci} 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_civoid r600_pm_get_dynpm_state(struct radeon_device *rdev) 36362306a36Sopenharmony_ci{ 36462306a36Sopenharmony_ci int i; 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci rdev->pm.dynpm_can_upclock = true; 36762306a36Sopenharmony_ci rdev->pm.dynpm_can_downclock = true; 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci /* power state array is low to high, default is first */ 37062306a36Sopenharmony_ci if ((rdev->flags & RADEON_IS_IGP) || (rdev->family == CHIP_R600)) { 37162306a36Sopenharmony_ci int min_power_state_index = 0; 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci if (rdev->pm.num_power_states > 2) 37462306a36Sopenharmony_ci min_power_state_index = 1; 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci switch (rdev->pm.dynpm_planned_action) { 37762306a36Sopenharmony_ci case DYNPM_ACTION_MINIMUM: 37862306a36Sopenharmony_ci rdev->pm.requested_power_state_index = min_power_state_index; 37962306a36Sopenharmony_ci rdev->pm.requested_clock_mode_index = 0; 38062306a36Sopenharmony_ci rdev->pm.dynpm_can_downclock = false; 38162306a36Sopenharmony_ci break; 38262306a36Sopenharmony_ci case DYNPM_ACTION_DOWNCLOCK: 38362306a36Sopenharmony_ci if (rdev->pm.current_power_state_index == min_power_state_index) { 38462306a36Sopenharmony_ci rdev->pm.requested_power_state_index = rdev->pm.current_power_state_index; 38562306a36Sopenharmony_ci rdev->pm.dynpm_can_downclock = false; 38662306a36Sopenharmony_ci } else { 38762306a36Sopenharmony_ci if (rdev->pm.active_crtc_count > 1) { 38862306a36Sopenharmony_ci for (i = 0; i < rdev->pm.num_power_states; i++) { 38962306a36Sopenharmony_ci if (rdev->pm.power_state[i].flags & RADEON_PM_STATE_SINGLE_DISPLAY_ONLY) 39062306a36Sopenharmony_ci continue; 39162306a36Sopenharmony_ci else if (i >= rdev->pm.current_power_state_index) { 39262306a36Sopenharmony_ci rdev->pm.requested_power_state_index = 39362306a36Sopenharmony_ci rdev->pm.current_power_state_index; 39462306a36Sopenharmony_ci break; 39562306a36Sopenharmony_ci } else { 39662306a36Sopenharmony_ci rdev->pm.requested_power_state_index = i; 39762306a36Sopenharmony_ci break; 39862306a36Sopenharmony_ci } 39962306a36Sopenharmony_ci } 40062306a36Sopenharmony_ci } else { 40162306a36Sopenharmony_ci if (rdev->pm.current_power_state_index == 0) 40262306a36Sopenharmony_ci rdev->pm.requested_power_state_index = 40362306a36Sopenharmony_ci rdev->pm.num_power_states - 1; 40462306a36Sopenharmony_ci else 40562306a36Sopenharmony_ci rdev->pm.requested_power_state_index = 40662306a36Sopenharmony_ci rdev->pm.current_power_state_index - 1; 40762306a36Sopenharmony_ci } 40862306a36Sopenharmony_ci } 40962306a36Sopenharmony_ci rdev->pm.requested_clock_mode_index = 0; 41062306a36Sopenharmony_ci /* don't use the power state if crtcs are active and no display flag is set */ 41162306a36Sopenharmony_ci if ((rdev->pm.active_crtc_count > 0) && 41262306a36Sopenharmony_ci (rdev->pm.power_state[rdev->pm.requested_power_state_index]. 41362306a36Sopenharmony_ci clock_info[rdev->pm.requested_clock_mode_index].flags & 41462306a36Sopenharmony_ci RADEON_PM_MODE_NO_DISPLAY)) { 41562306a36Sopenharmony_ci rdev->pm.requested_power_state_index++; 41662306a36Sopenharmony_ci } 41762306a36Sopenharmony_ci break; 41862306a36Sopenharmony_ci case DYNPM_ACTION_UPCLOCK: 41962306a36Sopenharmony_ci if (rdev->pm.current_power_state_index == (rdev->pm.num_power_states - 1)) { 42062306a36Sopenharmony_ci rdev->pm.requested_power_state_index = rdev->pm.current_power_state_index; 42162306a36Sopenharmony_ci rdev->pm.dynpm_can_upclock = false; 42262306a36Sopenharmony_ci } else { 42362306a36Sopenharmony_ci if (rdev->pm.active_crtc_count > 1) { 42462306a36Sopenharmony_ci for (i = (rdev->pm.num_power_states - 1); i >= 0; i--) { 42562306a36Sopenharmony_ci if (rdev->pm.power_state[i].flags & RADEON_PM_STATE_SINGLE_DISPLAY_ONLY) 42662306a36Sopenharmony_ci continue; 42762306a36Sopenharmony_ci else if (i <= rdev->pm.current_power_state_index) { 42862306a36Sopenharmony_ci rdev->pm.requested_power_state_index = 42962306a36Sopenharmony_ci rdev->pm.current_power_state_index; 43062306a36Sopenharmony_ci break; 43162306a36Sopenharmony_ci } else { 43262306a36Sopenharmony_ci rdev->pm.requested_power_state_index = i; 43362306a36Sopenharmony_ci break; 43462306a36Sopenharmony_ci } 43562306a36Sopenharmony_ci } 43662306a36Sopenharmony_ci } else 43762306a36Sopenharmony_ci rdev->pm.requested_power_state_index = 43862306a36Sopenharmony_ci rdev->pm.current_power_state_index + 1; 43962306a36Sopenharmony_ci } 44062306a36Sopenharmony_ci rdev->pm.requested_clock_mode_index = 0; 44162306a36Sopenharmony_ci break; 44262306a36Sopenharmony_ci case DYNPM_ACTION_DEFAULT: 44362306a36Sopenharmony_ci rdev->pm.requested_power_state_index = rdev->pm.default_power_state_index; 44462306a36Sopenharmony_ci rdev->pm.requested_clock_mode_index = 0; 44562306a36Sopenharmony_ci rdev->pm.dynpm_can_upclock = false; 44662306a36Sopenharmony_ci break; 44762306a36Sopenharmony_ci case DYNPM_ACTION_NONE: 44862306a36Sopenharmony_ci default: 44962306a36Sopenharmony_ci DRM_ERROR("Requested mode for not defined action\n"); 45062306a36Sopenharmony_ci return; 45162306a36Sopenharmony_ci } 45262306a36Sopenharmony_ci } else { 45362306a36Sopenharmony_ci /* XXX select a power state based on AC/DC, single/dualhead, etc. */ 45462306a36Sopenharmony_ci /* for now just select the first power state and switch between clock modes */ 45562306a36Sopenharmony_ci /* power state array is low to high, default is first (0) */ 45662306a36Sopenharmony_ci if (rdev->pm.active_crtc_count > 1) { 45762306a36Sopenharmony_ci rdev->pm.requested_power_state_index = -1; 45862306a36Sopenharmony_ci /* start at 1 as we don't want the default mode */ 45962306a36Sopenharmony_ci for (i = 1; i < rdev->pm.num_power_states; i++) { 46062306a36Sopenharmony_ci if (rdev->pm.power_state[i].flags & RADEON_PM_STATE_SINGLE_DISPLAY_ONLY) 46162306a36Sopenharmony_ci continue; 46262306a36Sopenharmony_ci else if ((rdev->pm.power_state[i].type == POWER_STATE_TYPE_PERFORMANCE) || 46362306a36Sopenharmony_ci (rdev->pm.power_state[i].type == POWER_STATE_TYPE_BATTERY)) { 46462306a36Sopenharmony_ci rdev->pm.requested_power_state_index = i; 46562306a36Sopenharmony_ci break; 46662306a36Sopenharmony_ci } 46762306a36Sopenharmony_ci } 46862306a36Sopenharmony_ci /* if nothing selected, grab the default state. */ 46962306a36Sopenharmony_ci if (rdev->pm.requested_power_state_index == -1) 47062306a36Sopenharmony_ci rdev->pm.requested_power_state_index = 0; 47162306a36Sopenharmony_ci } else 47262306a36Sopenharmony_ci rdev->pm.requested_power_state_index = 1; 47362306a36Sopenharmony_ci 47462306a36Sopenharmony_ci switch (rdev->pm.dynpm_planned_action) { 47562306a36Sopenharmony_ci case DYNPM_ACTION_MINIMUM: 47662306a36Sopenharmony_ci rdev->pm.requested_clock_mode_index = 0; 47762306a36Sopenharmony_ci rdev->pm.dynpm_can_downclock = false; 47862306a36Sopenharmony_ci break; 47962306a36Sopenharmony_ci case DYNPM_ACTION_DOWNCLOCK: 48062306a36Sopenharmony_ci if (rdev->pm.requested_power_state_index == rdev->pm.current_power_state_index) { 48162306a36Sopenharmony_ci if (rdev->pm.current_clock_mode_index == 0) { 48262306a36Sopenharmony_ci rdev->pm.requested_clock_mode_index = 0; 48362306a36Sopenharmony_ci rdev->pm.dynpm_can_downclock = false; 48462306a36Sopenharmony_ci } else 48562306a36Sopenharmony_ci rdev->pm.requested_clock_mode_index = 48662306a36Sopenharmony_ci rdev->pm.current_clock_mode_index - 1; 48762306a36Sopenharmony_ci } else { 48862306a36Sopenharmony_ci rdev->pm.requested_clock_mode_index = 0; 48962306a36Sopenharmony_ci rdev->pm.dynpm_can_downclock = false; 49062306a36Sopenharmony_ci } 49162306a36Sopenharmony_ci /* don't use the power state if crtcs are active and no display flag is set */ 49262306a36Sopenharmony_ci if ((rdev->pm.active_crtc_count > 0) && 49362306a36Sopenharmony_ci (rdev->pm.power_state[rdev->pm.requested_power_state_index]. 49462306a36Sopenharmony_ci clock_info[rdev->pm.requested_clock_mode_index].flags & 49562306a36Sopenharmony_ci RADEON_PM_MODE_NO_DISPLAY)) { 49662306a36Sopenharmony_ci rdev->pm.requested_clock_mode_index++; 49762306a36Sopenharmony_ci } 49862306a36Sopenharmony_ci break; 49962306a36Sopenharmony_ci case DYNPM_ACTION_UPCLOCK: 50062306a36Sopenharmony_ci if (rdev->pm.requested_power_state_index == rdev->pm.current_power_state_index) { 50162306a36Sopenharmony_ci if (rdev->pm.current_clock_mode_index == 50262306a36Sopenharmony_ci (rdev->pm.power_state[rdev->pm.requested_power_state_index].num_clock_modes - 1)) { 50362306a36Sopenharmony_ci rdev->pm.requested_clock_mode_index = rdev->pm.current_clock_mode_index; 50462306a36Sopenharmony_ci rdev->pm.dynpm_can_upclock = false; 50562306a36Sopenharmony_ci } else 50662306a36Sopenharmony_ci rdev->pm.requested_clock_mode_index = 50762306a36Sopenharmony_ci rdev->pm.current_clock_mode_index + 1; 50862306a36Sopenharmony_ci } else { 50962306a36Sopenharmony_ci rdev->pm.requested_clock_mode_index = 51062306a36Sopenharmony_ci rdev->pm.power_state[rdev->pm.requested_power_state_index].num_clock_modes - 1; 51162306a36Sopenharmony_ci rdev->pm.dynpm_can_upclock = false; 51262306a36Sopenharmony_ci } 51362306a36Sopenharmony_ci break; 51462306a36Sopenharmony_ci case DYNPM_ACTION_DEFAULT: 51562306a36Sopenharmony_ci rdev->pm.requested_power_state_index = rdev->pm.default_power_state_index; 51662306a36Sopenharmony_ci rdev->pm.requested_clock_mode_index = 0; 51762306a36Sopenharmony_ci rdev->pm.dynpm_can_upclock = false; 51862306a36Sopenharmony_ci break; 51962306a36Sopenharmony_ci case DYNPM_ACTION_NONE: 52062306a36Sopenharmony_ci default: 52162306a36Sopenharmony_ci DRM_ERROR("Requested mode for not defined action\n"); 52262306a36Sopenharmony_ci return; 52362306a36Sopenharmony_ci } 52462306a36Sopenharmony_ci } 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ci DRM_DEBUG_DRIVER("Requested: e: %d m: %d p: %d\n", 52762306a36Sopenharmony_ci rdev->pm.power_state[rdev->pm.requested_power_state_index]. 52862306a36Sopenharmony_ci clock_info[rdev->pm.requested_clock_mode_index].sclk, 52962306a36Sopenharmony_ci rdev->pm.power_state[rdev->pm.requested_power_state_index]. 53062306a36Sopenharmony_ci clock_info[rdev->pm.requested_clock_mode_index].mclk, 53162306a36Sopenharmony_ci rdev->pm.power_state[rdev->pm.requested_power_state_index]. 53262306a36Sopenharmony_ci pcie_lanes); 53362306a36Sopenharmony_ci} 53462306a36Sopenharmony_ci 53562306a36Sopenharmony_civoid rs780_pm_init_profile(struct radeon_device *rdev) 53662306a36Sopenharmony_ci{ 53762306a36Sopenharmony_ci if (rdev->pm.num_power_states == 2) { 53862306a36Sopenharmony_ci /* default */ 53962306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index; 54062306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; 54162306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0; 54262306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 0; 54362306a36Sopenharmony_ci /* low sh */ 54462306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = 0; 54562306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 0; 54662306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0; 54762306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0; 54862306a36Sopenharmony_ci /* mid sh */ 54962306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = 0; 55062306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = 0; 55162306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0; 55262306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 0; 55362306a36Sopenharmony_ci /* high sh */ 55462306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 0; 55562306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = 1; 55662306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0; 55762306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx = 0; 55862306a36Sopenharmony_ci /* low mh */ 55962306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = 0; 56062306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = 0; 56162306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0; 56262306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0; 56362306a36Sopenharmony_ci /* mid mh */ 56462306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = 0; 56562306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = 0; 56662306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0; 56762306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 0; 56862306a36Sopenharmony_ci /* high mh */ 56962306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 0; 57062306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = 1; 57162306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0; 57262306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 0; 57362306a36Sopenharmony_ci } else if (rdev->pm.num_power_states == 3) { 57462306a36Sopenharmony_ci /* default */ 57562306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index; 57662306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; 57762306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0; 57862306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 0; 57962306a36Sopenharmony_ci /* low sh */ 58062306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = 1; 58162306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 1; 58262306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0; 58362306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0; 58462306a36Sopenharmony_ci /* mid sh */ 58562306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = 1; 58662306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = 1; 58762306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0; 58862306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 0; 58962306a36Sopenharmony_ci /* high sh */ 59062306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 1; 59162306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = 2; 59262306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0; 59362306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx = 0; 59462306a36Sopenharmony_ci /* low mh */ 59562306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = 1; 59662306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = 1; 59762306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0; 59862306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0; 59962306a36Sopenharmony_ci /* mid mh */ 60062306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = 1; 60162306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = 1; 60262306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0; 60362306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 0; 60462306a36Sopenharmony_ci /* high mh */ 60562306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 1; 60662306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = 2; 60762306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0; 60862306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 0; 60962306a36Sopenharmony_ci } else { 61062306a36Sopenharmony_ci /* default */ 61162306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index; 61262306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; 61362306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0; 61462306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 0; 61562306a36Sopenharmony_ci /* low sh */ 61662306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = 2; 61762306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 2; 61862306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0; 61962306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0; 62062306a36Sopenharmony_ci /* mid sh */ 62162306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = 2; 62262306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = 2; 62362306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0; 62462306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 0; 62562306a36Sopenharmony_ci /* high sh */ 62662306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 2; 62762306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = 3; 62862306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0; 62962306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx = 0; 63062306a36Sopenharmony_ci /* low mh */ 63162306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = 2; 63262306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = 0; 63362306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0; 63462306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0; 63562306a36Sopenharmony_ci /* mid mh */ 63662306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = 2; 63762306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = 0; 63862306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0; 63962306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 0; 64062306a36Sopenharmony_ci /* high mh */ 64162306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 2; 64262306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = 3; 64362306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0; 64462306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 0; 64562306a36Sopenharmony_ci } 64662306a36Sopenharmony_ci} 64762306a36Sopenharmony_ci 64862306a36Sopenharmony_civoid r600_pm_init_profile(struct radeon_device *rdev) 64962306a36Sopenharmony_ci{ 65062306a36Sopenharmony_ci int idx; 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_ci if (rdev->family == CHIP_R600) { 65362306a36Sopenharmony_ci /* XXX */ 65462306a36Sopenharmony_ci /* default */ 65562306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index; 65662306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; 65762306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0; 65862306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 0; 65962306a36Sopenharmony_ci /* low sh */ 66062306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index; 66162306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; 66262306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0; 66362306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0; 66462306a36Sopenharmony_ci /* mid sh */ 66562306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index; 66662306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; 66762306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0; 66862306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 0; 66962306a36Sopenharmony_ci /* high sh */ 67062306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index; 67162306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; 67262306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0; 67362306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx = 0; 67462306a36Sopenharmony_ci /* low mh */ 67562306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index; 67662306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; 67762306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0; 67862306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0; 67962306a36Sopenharmony_ci /* mid mh */ 68062306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index; 68162306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; 68262306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0; 68362306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 0; 68462306a36Sopenharmony_ci /* high mh */ 68562306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index; 68662306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; 68762306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0; 68862306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 0; 68962306a36Sopenharmony_ci } else { 69062306a36Sopenharmony_ci if (rdev->pm.num_power_states < 4) { 69162306a36Sopenharmony_ci /* default */ 69262306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index; 69362306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; 69462306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0; 69562306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 2; 69662306a36Sopenharmony_ci /* low sh */ 69762306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = 1; 69862306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = 1; 69962306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0; 70062306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0; 70162306a36Sopenharmony_ci /* mid sh */ 70262306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = 1; 70362306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = 1; 70462306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0; 70562306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 1; 70662306a36Sopenharmony_ci /* high sh */ 70762306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = 1; 70862306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = 1; 70962306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0; 71062306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx = 2; 71162306a36Sopenharmony_ci /* low mh */ 71262306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = 2; 71362306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = 2; 71462306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0; 71562306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0; 71662306a36Sopenharmony_ci /* low mh */ 71762306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = 2; 71862306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = 2; 71962306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0; 72062306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 1; 72162306a36Sopenharmony_ci /* high mh */ 72262306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = 2; 72362306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = 2; 72462306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0; 72562306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 2; 72662306a36Sopenharmony_ci } else { 72762306a36Sopenharmony_ci /* default */ 72862306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index; 72962306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index; 73062306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0; 73162306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 2; 73262306a36Sopenharmony_ci /* low sh */ 73362306a36Sopenharmony_ci if (rdev->flags & RADEON_IS_MOBILITY) 73462306a36Sopenharmony_ci idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0); 73562306a36Sopenharmony_ci else 73662306a36Sopenharmony_ci idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0); 73762306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = idx; 73862306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = idx; 73962306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0; 74062306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0; 74162306a36Sopenharmony_ci /* mid sh */ 74262306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = idx; 74362306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = idx; 74462306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0; 74562306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 1; 74662306a36Sopenharmony_ci /* high sh */ 74762306a36Sopenharmony_ci idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0); 74862306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = idx; 74962306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = idx; 75062306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0; 75162306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx = 2; 75262306a36Sopenharmony_ci /* low mh */ 75362306a36Sopenharmony_ci if (rdev->flags & RADEON_IS_MOBILITY) 75462306a36Sopenharmony_ci idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 1); 75562306a36Sopenharmony_ci else 75662306a36Sopenharmony_ci idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1); 75762306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = idx; 75862306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = idx; 75962306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0; 76062306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0; 76162306a36Sopenharmony_ci /* mid mh */ 76262306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = idx; 76362306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = idx; 76462306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0; 76562306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 1; 76662306a36Sopenharmony_ci /* high mh */ 76762306a36Sopenharmony_ci idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 1); 76862306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = idx; 76962306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = idx; 77062306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0; 77162306a36Sopenharmony_ci rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 2; 77262306a36Sopenharmony_ci } 77362306a36Sopenharmony_ci } 77462306a36Sopenharmony_ci} 77562306a36Sopenharmony_ci 77662306a36Sopenharmony_civoid r600_pm_misc(struct radeon_device *rdev) 77762306a36Sopenharmony_ci{ 77862306a36Sopenharmony_ci int req_ps_idx = rdev->pm.requested_power_state_index; 77962306a36Sopenharmony_ci int req_cm_idx = rdev->pm.requested_clock_mode_index; 78062306a36Sopenharmony_ci struct radeon_power_state *ps = &rdev->pm.power_state[req_ps_idx]; 78162306a36Sopenharmony_ci struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage; 78262306a36Sopenharmony_ci 78362306a36Sopenharmony_ci if ((voltage->type == VOLTAGE_SW) && voltage->voltage) { 78462306a36Sopenharmony_ci /* 0xff01 is a flag rather then an actual voltage */ 78562306a36Sopenharmony_ci if (voltage->voltage == 0xff01) 78662306a36Sopenharmony_ci return; 78762306a36Sopenharmony_ci if (voltage->voltage != rdev->pm.current_vddc) { 78862306a36Sopenharmony_ci radeon_atom_set_voltage(rdev, voltage->voltage, SET_VOLTAGE_TYPE_ASIC_VDDC); 78962306a36Sopenharmony_ci rdev->pm.current_vddc = voltage->voltage; 79062306a36Sopenharmony_ci DRM_DEBUG_DRIVER("Setting: v: %d\n", voltage->voltage); 79162306a36Sopenharmony_ci } 79262306a36Sopenharmony_ci } 79362306a36Sopenharmony_ci} 79462306a36Sopenharmony_ci 79562306a36Sopenharmony_cibool r600_gui_idle(struct radeon_device *rdev) 79662306a36Sopenharmony_ci{ 79762306a36Sopenharmony_ci if (RREG32(GRBM_STATUS) & GUI_ACTIVE) 79862306a36Sopenharmony_ci return false; 79962306a36Sopenharmony_ci else 80062306a36Sopenharmony_ci return true; 80162306a36Sopenharmony_ci} 80262306a36Sopenharmony_ci 80362306a36Sopenharmony_ci/* hpd for digital panel detect/disconnect */ 80462306a36Sopenharmony_cibool r600_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd) 80562306a36Sopenharmony_ci{ 80662306a36Sopenharmony_ci bool connected = false; 80762306a36Sopenharmony_ci 80862306a36Sopenharmony_ci if (ASIC_IS_DCE3(rdev)) { 80962306a36Sopenharmony_ci switch (hpd) { 81062306a36Sopenharmony_ci case RADEON_HPD_1: 81162306a36Sopenharmony_ci if (RREG32(DC_HPD1_INT_STATUS) & DC_HPDx_SENSE) 81262306a36Sopenharmony_ci connected = true; 81362306a36Sopenharmony_ci break; 81462306a36Sopenharmony_ci case RADEON_HPD_2: 81562306a36Sopenharmony_ci if (RREG32(DC_HPD2_INT_STATUS) & DC_HPDx_SENSE) 81662306a36Sopenharmony_ci connected = true; 81762306a36Sopenharmony_ci break; 81862306a36Sopenharmony_ci case RADEON_HPD_3: 81962306a36Sopenharmony_ci if (RREG32(DC_HPD3_INT_STATUS) & DC_HPDx_SENSE) 82062306a36Sopenharmony_ci connected = true; 82162306a36Sopenharmony_ci break; 82262306a36Sopenharmony_ci case RADEON_HPD_4: 82362306a36Sopenharmony_ci if (RREG32(DC_HPD4_INT_STATUS) & DC_HPDx_SENSE) 82462306a36Sopenharmony_ci connected = true; 82562306a36Sopenharmony_ci break; 82662306a36Sopenharmony_ci /* DCE 3.2 */ 82762306a36Sopenharmony_ci case RADEON_HPD_5: 82862306a36Sopenharmony_ci if (RREG32(DC_HPD5_INT_STATUS) & DC_HPDx_SENSE) 82962306a36Sopenharmony_ci connected = true; 83062306a36Sopenharmony_ci break; 83162306a36Sopenharmony_ci case RADEON_HPD_6: 83262306a36Sopenharmony_ci if (RREG32(DC_HPD6_INT_STATUS) & DC_HPDx_SENSE) 83362306a36Sopenharmony_ci connected = true; 83462306a36Sopenharmony_ci break; 83562306a36Sopenharmony_ci default: 83662306a36Sopenharmony_ci break; 83762306a36Sopenharmony_ci } 83862306a36Sopenharmony_ci } else { 83962306a36Sopenharmony_ci switch (hpd) { 84062306a36Sopenharmony_ci case RADEON_HPD_1: 84162306a36Sopenharmony_ci if (RREG32(DC_HOT_PLUG_DETECT1_INT_STATUS) & DC_HOT_PLUG_DETECTx_SENSE) 84262306a36Sopenharmony_ci connected = true; 84362306a36Sopenharmony_ci break; 84462306a36Sopenharmony_ci case RADEON_HPD_2: 84562306a36Sopenharmony_ci if (RREG32(DC_HOT_PLUG_DETECT2_INT_STATUS) & DC_HOT_PLUG_DETECTx_SENSE) 84662306a36Sopenharmony_ci connected = true; 84762306a36Sopenharmony_ci break; 84862306a36Sopenharmony_ci case RADEON_HPD_3: 84962306a36Sopenharmony_ci if (RREG32(DC_HOT_PLUG_DETECT3_INT_STATUS) & DC_HOT_PLUG_DETECTx_SENSE) 85062306a36Sopenharmony_ci connected = true; 85162306a36Sopenharmony_ci break; 85262306a36Sopenharmony_ci default: 85362306a36Sopenharmony_ci break; 85462306a36Sopenharmony_ci } 85562306a36Sopenharmony_ci } 85662306a36Sopenharmony_ci return connected; 85762306a36Sopenharmony_ci} 85862306a36Sopenharmony_ci 85962306a36Sopenharmony_civoid r600_hpd_set_polarity(struct radeon_device *rdev, 86062306a36Sopenharmony_ci enum radeon_hpd_id hpd) 86162306a36Sopenharmony_ci{ 86262306a36Sopenharmony_ci u32 tmp; 86362306a36Sopenharmony_ci bool connected = r600_hpd_sense(rdev, hpd); 86462306a36Sopenharmony_ci 86562306a36Sopenharmony_ci if (ASIC_IS_DCE3(rdev)) { 86662306a36Sopenharmony_ci switch (hpd) { 86762306a36Sopenharmony_ci case RADEON_HPD_1: 86862306a36Sopenharmony_ci tmp = RREG32(DC_HPD1_INT_CONTROL); 86962306a36Sopenharmony_ci if (connected) 87062306a36Sopenharmony_ci tmp &= ~DC_HPDx_INT_POLARITY; 87162306a36Sopenharmony_ci else 87262306a36Sopenharmony_ci tmp |= DC_HPDx_INT_POLARITY; 87362306a36Sopenharmony_ci WREG32(DC_HPD1_INT_CONTROL, tmp); 87462306a36Sopenharmony_ci break; 87562306a36Sopenharmony_ci case RADEON_HPD_2: 87662306a36Sopenharmony_ci tmp = RREG32(DC_HPD2_INT_CONTROL); 87762306a36Sopenharmony_ci if (connected) 87862306a36Sopenharmony_ci tmp &= ~DC_HPDx_INT_POLARITY; 87962306a36Sopenharmony_ci else 88062306a36Sopenharmony_ci tmp |= DC_HPDx_INT_POLARITY; 88162306a36Sopenharmony_ci WREG32(DC_HPD2_INT_CONTROL, tmp); 88262306a36Sopenharmony_ci break; 88362306a36Sopenharmony_ci case RADEON_HPD_3: 88462306a36Sopenharmony_ci tmp = RREG32(DC_HPD3_INT_CONTROL); 88562306a36Sopenharmony_ci if (connected) 88662306a36Sopenharmony_ci tmp &= ~DC_HPDx_INT_POLARITY; 88762306a36Sopenharmony_ci else 88862306a36Sopenharmony_ci tmp |= DC_HPDx_INT_POLARITY; 88962306a36Sopenharmony_ci WREG32(DC_HPD3_INT_CONTROL, tmp); 89062306a36Sopenharmony_ci break; 89162306a36Sopenharmony_ci case RADEON_HPD_4: 89262306a36Sopenharmony_ci tmp = RREG32(DC_HPD4_INT_CONTROL); 89362306a36Sopenharmony_ci if (connected) 89462306a36Sopenharmony_ci tmp &= ~DC_HPDx_INT_POLARITY; 89562306a36Sopenharmony_ci else 89662306a36Sopenharmony_ci tmp |= DC_HPDx_INT_POLARITY; 89762306a36Sopenharmony_ci WREG32(DC_HPD4_INT_CONTROL, tmp); 89862306a36Sopenharmony_ci break; 89962306a36Sopenharmony_ci case RADEON_HPD_5: 90062306a36Sopenharmony_ci tmp = RREG32(DC_HPD5_INT_CONTROL); 90162306a36Sopenharmony_ci if (connected) 90262306a36Sopenharmony_ci tmp &= ~DC_HPDx_INT_POLARITY; 90362306a36Sopenharmony_ci else 90462306a36Sopenharmony_ci tmp |= DC_HPDx_INT_POLARITY; 90562306a36Sopenharmony_ci WREG32(DC_HPD5_INT_CONTROL, tmp); 90662306a36Sopenharmony_ci break; 90762306a36Sopenharmony_ci /* DCE 3.2 */ 90862306a36Sopenharmony_ci case RADEON_HPD_6: 90962306a36Sopenharmony_ci tmp = RREG32(DC_HPD6_INT_CONTROL); 91062306a36Sopenharmony_ci if (connected) 91162306a36Sopenharmony_ci tmp &= ~DC_HPDx_INT_POLARITY; 91262306a36Sopenharmony_ci else 91362306a36Sopenharmony_ci tmp |= DC_HPDx_INT_POLARITY; 91462306a36Sopenharmony_ci WREG32(DC_HPD6_INT_CONTROL, tmp); 91562306a36Sopenharmony_ci break; 91662306a36Sopenharmony_ci default: 91762306a36Sopenharmony_ci break; 91862306a36Sopenharmony_ci } 91962306a36Sopenharmony_ci } else { 92062306a36Sopenharmony_ci switch (hpd) { 92162306a36Sopenharmony_ci case RADEON_HPD_1: 92262306a36Sopenharmony_ci tmp = RREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL); 92362306a36Sopenharmony_ci if (connected) 92462306a36Sopenharmony_ci tmp &= ~DC_HOT_PLUG_DETECTx_INT_POLARITY; 92562306a36Sopenharmony_ci else 92662306a36Sopenharmony_ci tmp |= DC_HOT_PLUG_DETECTx_INT_POLARITY; 92762306a36Sopenharmony_ci WREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL, tmp); 92862306a36Sopenharmony_ci break; 92962306a36Sopenharmony_ci case RADEON_HPD_2: 93062306a36Sopenharmony_ci tmp = RREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL); 93162306a36Sopenharmony_ci if (connected) 93262306a36Sopenharmony_ci tmp &= ~DC_HOT_PLUG_DETECTx_INT_POLARITY; 93362306a36Sopenharmony_ci else 93462306a36Sopenharmony_ci tmp |= DC_HOT_PLUG_DETECTx_INT_POLARITY; 93562306a36Sopenharmony_ci WREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL, tmp); 93662306a36Sopenharmony_ci break; 93762306a36Sopenharmony_ci case RADEON_HPD_3: 93862306a36Sopenharmony_ci tmp = RREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL); 93962306a36Sopenharmony_ci if (connected) 94062306a36Sopenharmony_ci tmp &= ~DC_HOT_PLUG_DETECTx_INT_POLARITY; 94162306a36Sopenharmony_ci else 94262306a36Sopenharmony_ci tmp |= DC_HOT_PLUG_DETECTx_INT_POLARITY; 94362306a36Sopenharmony_ci WREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL, tmp); 94462306a36Sopenharmony_ci break; 94562306a36Sopenharmony_ci default: 94662306a36Sopenharmony_ci break; 94762306a36Sopenharmony_ci } 94862306a36Sopenharmony_ci } 94962306a36Sopenharmony_ci} 95062306a36Sopenharmony_ci 95162306a36Sopenharmony_civoid r600_hpd_init(struct radeon_device *rdev) 95262306a36Sopenharmony_ci{ 95362306a36Sopenharmony_ci struct drm_device *dev = rdev->ddev; 95462306a36Sopenharmony_ci struct drm_connector *connector; 95562306a36Sopenharmony_ci unsigned enable = 0; 95662306a36Sopenharmony_ci 95762306a36Sopenharmony_ci list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 95862306a36Sopenharmony_ci struct radeon_connector *radeon_connector = to_radeon_connector(connector); 95962306a36Sopenharmony_ci 96062306a36Sopenharmony_ci if (connector->connector_type == DRM_MODE_CONNECTOR_eDP || 96162306a36Sopenharmony_ci connector->connector_type == DRM_MODE_CONNECTOR_LVDS) { 96262306a36Sopenharmony_ci /* don't try to enable hpd on eDP or LVDS avoid breaking the 96362306a36Sopenharmony_ci * aux dp channel on imac and help (but not completely fix) 96462306a36Sopenharmony_ci * https://bugzilla.redhat.com/show_bug.cgi?id=726143 96562306a36Sopenharmony_ci */ 96662306a36Sopenharmony_ci continue; 96762306a36Sopenharmony_ci } 96862306a36Sopenharmony_ci if (ASIC_IS_DCE3(rdev)) { 96962306a36Sopenharmony_ci u32 tmp = DC_HPDx_CONNECTION_TIMER(0x9c4) | DC_HPDx_RX_INT_TIMER(0xfa); 97062306a36Sopenharmony_ci if (ASIC_IS_DCE32(rdev)) 97162306a36Sopenharmony_ci tmp |= DC_HPDx_EN; 97262306a36Sopenharmony_ci 97362306a36Sopenharmony_ci switch (radeon_connector->hpd.hpd) { 97462306a36Sopenharmony_ci case RADEON_HPD_1: 97562306a36Sopenharmony_ci WREG32(DC_HPD1_CONTROL, tmp); 97662306a36Sopenharmony_ci break; 97762306a36Sopenharmony_ci case RADEON_HPD_2: 97862306a36Sopenharmony_ci WREG32(DC_HPD2_CONTROL, tmp); 97962306a36Sopenharmony_ci break; 98062306a36Sopenharmony_ci case RADEON_HPD_3: 98162306a36Sopenharmony_ci WREG32(DC_HPD3_CONTROL, tmp); 98262306a36Sopenharmony_ci break; 98362306a36Sopenharmony_ci case RADEON_HPD_4: 98462306a36Sopenharmony_ci WREG32(DC_HPD4_CONTROL, tmp); 98562306a36Sopenharmony_ci break; 98662306a36Sopenharmony_ci /* DCE 3.2 */ 98762306a36Sopenharmony_ci case RADEON_HPD_5: 98862306a36Sopenharmony_ci WREG32(DC_HPD5_CONTROL, tmp); 98962306a36Sopenharmony_ci break; 99062306a36Sopenharmony_ci case RADEON_HPD_6: 99162306a36Sopenharmony_ci WREG32(DC_HPD6_CONTROL, tmp); 99262306a36Sopenharmony_ci break; 99362306a36Sopenharmony_ci default: 99462306a36Sopenharmony_ci break; 99562306a36Sopenharmony_ci } 99662306a36Sopenharmony_ci } else { 99762306a36Sopenharmony_ci switch (radeon_connector->hpd.hpd) { 99862306a36Sopenharmony_ci case RADEON_HPD_1: 99962306a36Sopenharmony_ci WREG32(DC_HOT_PLUG_DETECT1_CONTROL, DC_HOT_PLUG_DETECTx_EN); 100062306a36Sopenharmony_ci break; 100162306a36Sopenharmony_ci case RADEON_HPD_2: 100262306a36Sopenharmony_ci WREG32(DC_HOT_PLUG_DETECT2_CONTROL, DC_HOT_PLUG_DETECTx_EN); 100362306a36Sopenharmony_ci break; 100462306a36Sopenharmony_ci case RADEON_HPD_3: 100562306a36Sopenharmony_ci WREG32(DC_HOT_PLUG_DETECT3_CONTROL, DC_HOT_PLUG_DETECTx_EN); 100662306a36Sopenharmony_ci break; 100762306a36Sopenharmony_ci default: 100862306a36Sopenharmony_ci break; 100962306a36Sopenharmony_ci } 101062306a36Sopenharmony_ci } 101162306a36Sopenharmony_ci if (radeon_connector->hpd.hpd != RADEON_HPD_NONE) 101262306a36Sopenharmony_ci enable |= 1 << radeon_connector->hpd.hpd; 101362306a36Sopenharmony_ci radeon_hpd_set_polarity(rdev, radeon_connector->hpd.hpd); 101462306a36Sopenharmony_ci } 101562306a36Sopenharmony_ci radeon_irq_kms_enable_hpd(rdev, enable); 101662306a36Sopenharmony_ci} 101762306a36Sopenharmony_ci 101862306a36Sopenharmony_civoid r600_hpd_fini(struct radeon_device *rdev) 101962306a36Sopenharmony_ci{ 102062306a36Sopenharmony_ci struct drm_device *dev = rdev->ddev; 102162306a36Sopenharmony_ci struct drm_connector *connector; 102262306a36Sopenharmony_ci unsigned disable = 0; 102362306a36Sopenharmony_ci 102462306a36Sopenharmony_ci list_for_each_entry(connector, &dev->mode_config.connector_list, head) { 102562306a36Sopenharmony_ci struct radeon_connector *radeon_connector = to_radeon_connector(connector); 102662306a36Sopenharmony_ci if (ASIC_IS_DCE3(rdev)) { 102762306a36Sopenharmony_ci switch (radeon_connector->hpd.hpd) { 102862306a36Sopenharmony_ci case RADEON_HPD_1: 102962306a36Sopenharmony_ci WREG32(DC_HPD1_CONTROL, 0); 103062306a36Sopenharmony_ci break; 103162306a36Sopenharmony_ci case RADEON_HPD_2: 103262306a36Sopenharmony_ci WREG32(DC_HPD2_CONTROL, 0); 103362306a36Sopenharmony_ci break; 103462306a36Sopenharmony_ci case RADEON_HPD_3: 103562306a36Sopenharmony_ci WREG32(DC_HPD3_CONTROL, 0); 103662306a36Sopenharmony_ci break; 103762306a36Sopenharmony_ci case RADEON_HPD_4: 103862306a36Sopenharmony_ci WREG32(DC_HPD4_CONTROL, 0); 103962306a36Sopenharmony_ci break; 104062306a36Sopenharmony_ci /* DCE 3.2 */ 104162306a36Sopenharmony_ci case RADEON_HPD_5: 104262306a36Sopenharmony_ci WREG32(DC_HPD5_CONTROL, 0); 104362306a36Sopenharmony_ci break; 104462306a36Sopenharmony_ci case RADEON_HPD_6: 104562306a36Sopenharmony_ci WREG32(DC_HPD6_CONTROL, 0); 104662306a36Sopenharmony_ci break; 104762306a36Sopenharmony_ci default: 104862306a36Sopenharmony_ci break; 104962306a36Sopenharmony_ci } 105062306a36Sopenharmony_ci } else { 105162306a36Sopenharmony_ci switch (radeon_connector->hpd.hpd) { 105262306a36Sopenharmony_ci case RADEON_HPD_1: 105362306a36Sopenharmony_ci WREG32(DC_HOT_PLUG_DETECT1_CONTROL, 0); 105462306a36Sopenharmony_ci break; 105562306a36Sopenharmony_ci case RADEON_HPD_2: 105662306a36Sopenharmony_ci WREG32(DC_HOT_PLUG_DETECT2_CONTROL, 0); 105762306a36Sopenharmony_ci break; 105862306a36Sopenharmony_ci case RADEON_HPD_3: 105962306a36Sopenharmony_ci WREG32(DC_HOT_PLUG_DETECT3_CONTROL, 0); 106062306a36Sopenharmony_ci break; 106162306a36Sopenharmony_ci default: 106262306a36Sopenharmony_ci break; 106362306a36Sopenharmony_ci } 106462306a36Sopenharmony_ci } 106562306a36Sopenharmony_ci if (radeon_connector->hpd.hpd != RADEON_HPD_NONE) 106662306a36Sopenharmony_ci disable |= 1 << radeon_connector->hpd.hpd; 106762306a36Sopenharmony_ci } 106862306a36Sopenharmony_ci radeon_irq_kms_disable_hpd(rdev, disable); 106962306a36Sopenharmony_ci} 107062306a36Sopenharmony_ci 107162306a36Sopenharmony_ci/* 107262306a36Sopenharmony_ci * R600 PCIE GART 107362306a36Sopenharmony_ci */ 107462306a36Sopenharmony_civoid r600_pcie_gart_tlb_flush(struct radeon_device *rdev) 107562306a36Sopenharmony_ci{ 107662306a36Sopenharmony_ci unsigned i; 107762306a36Sopenharmony_ci u32 tmp; 107862306a36Sopenharmony_ci 107962306a36Sopenharmony_ci /* flush hdp cache so updates hit vram */ 108062306a36Sopenharmony_ci if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_RV740) && 108162306a36Sopenharmony_ci !(rdev->flags & RADEON_IS_AGP)) { 108262306a36Sopenharmony_ci void __iomem *ptr = (void *)rdev->gart.ptr; 108362306a36Sopenharmony_ci 108462306a36Sopenharmony_ci /* r7xx hw bug. write to HDP_DEBUG1 followed by fb read 108562306a36Sopenharmony_ci * rather than write to HDP_REG_COHERENCY_FLUSH_CNTL 108662306a36Sopenharmony_ci * This seems to cause problems on some AGP cards. Just use the old 108762306a36Sopenharmony_ci * method for them. 108862306a36Sopenharmony_ci */ 108962306a36Sopenharmony_ci WREG32(HDP_DEBUG1, 0); 109062306a36Sopenharmony_ci readl((void __iomem *)ptr); 109162306a36Sopenharmony_ci } else 109262306a36Sopenharmony_ci WREG32(R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1); 109362306a36Sopenharmony_ci 109462306a36Sopenharmony_ci WREG32(VM_CONTEXT0_INVALIDATION_LOW_ADDR, rdev->mc.gtt_start >> 12); 109562306a36Sopenharmony_ci WREG32(VM_CONTEXT0_INVALIDATION_HIGH_ADDR, (rdev->mc.gtt_end - 1) >> 12); 109662306a36Sopenharmony_ci WREG32(VM_CONTEXT0_REQUEST_RESPONSE, REQUEST_TYPE(1)); 109762306a36Sopenharmony_ci for (i = 0; i < rdev->usec_timeout; i++) { 109862306a36Sopenharmony_ci /* read MC_STATUS */ 109962306a36Sopenharmony_ci tmp = RREG32(VM_CONTEXT0_REQUEST_RESPONSE); 110062306a36Sopenharmony_ci tmp = (tmp & RESPONSE_TYPE_MASK) >> RESPONSE_TYPE_SHIFT; 110162306a36Sopenharmony_ci if (tmp == 2) { 110262306a36Sopenharmony_ci pr_warn("[drm] r600 flush TLB failed\n"); 110362306a36Sopenharmony_ci return; 110462306a36Sopenharmony_ci } 110562306a36Sopenharmony_ci if (tmp) { 110662306a36Sopenharmony_ci return; 110762306a36Sopenharmony_ci } 110862306a36Sopenharmony_ci udelay(1); 110962306a36Sopenharmony_ci } 111062306a36Sopenharmony_ci} 111162306a36Sopenharmony_ci 111262306a36Sopenharmony_ciint r600_pcie_gart_init(struct radeon_device *rdev) 111362306a36Sopenharmony_ci{ 111462306a36Sopenharmony_ci int r; 111562306a36Sopenharmony_ci 111662306a36Sopenharmony_ci if (rdev->gart.robj) { 111762306a36Sopenharmony_ci WARN(1, "R600 PCIE GART already initialized\n"); 111862306a36Sopenharmony_ci return 0; 111962306a36Sopenharmony_ci } 112062306a36Sopenharmony_ci /* Initialize common gart structure */ 112162306a36Sopenharmony_ci r = radeon_gart_init(rdev); 112262306a36Sopenharmony_ci if (r) 112362306a36Sopenharmony_ci return r; 112462306a36Sopenharmony_ci rdev->gart.table_size = rdev->gart.num_gpu_pages * 8; 112562306a36Sopenharmony_ci return radeon_gart_table_vram_alloc(rdev); 112662306a36Sopenharmony_ci} 112762306a36Sopenharmony_ci 112862306a36Sopenharmony_cistatic int r600_pcie_gart_enable(struct radeon_device *rdev) 112962306a36Sopenharmony_ci{ 113062306a36Sopenharmony_ci u32 tmp; 113162306a36Sopenharmony_ci int r, i; 113262306a36Sopenharmony_ci 113362306a36Sopenharmony_ci if (rdev->gart.robj == NULL) { 113462306a36Sopenharmony_ci dev_err(rdev->dev, "No VRAM object for PCIE GART.\n"); 113562306a36Sopenharmony_ci return -EINVAL; 113662306a36Sopenharmony_ci } 113762306a36Sopenharmony_ci r = radeon_gart_table_vram_pin(rdev); 113862306a36Sopenharmony_ci if (r) 113962306a36Sopenharmony_ci return r; 114062306a36Sopenharmony_ci 114162306a36Sopenharmony_ci /* Setup L2 cache */ 114262306a36Sopenharmony_ci WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | ENABLE_L2_FRAGMENT_PROCESSING | 114362306a36Sopenharmony_ci ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE | 114462306a36Sopenharmony_ci EFFECTIVE_L2_QUEUE_SIZE(7)); 114562306a36Sopenharmony_ci WREG32(VM_L2_CNTL2, 0); 114662306a36Sopenharmony_ci WREG32(VM_L2_CNTL3, BANK_SELECT_0(0) | BANK_SELECT_1(1)); 114762306a36Sopenharmony_ci /* Setup TLB control */ 114862306a36Sopenharmony_ci tmp = ENABLE_L1_TLB | ENABLE_L1_FRAGMENT_PROCESSING | 114962306a36Sopenharmony_ci SYSTEM_ACCESS_MODE_NOT_IN_SYS | 115062306a36Sopenharmony_ci EFFECTIVE_L1_TLB_SIZE(5) | EFFECTIVE_L1_QUEUE_SIZE(5) | 115162306a36Sopenharmony_ci ENABLE_WAIT_L2_QUERY; 115262306a36Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_RD_SYS_CNTL, tmp); 115362306a36Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_WR_SYS_CNTL, tmp); 115462306a36Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_RD_HDP_CNTL, tmp | ENABLE_L1_STRICT_ORDERING); 115562306a36Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_WR_HDP_CNTL, tmp); 115662306a36Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCD_RD_A_CNTL, tmp); 115762306a36Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCD_WR_A_CNTL, tmp); 115862306a36Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCD_RD_B_CNTL, tmp); 115962306a36Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCD_WR_B_CNTL, tmp); 116062306a36Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_RD_GFX_CNTL, tmp); 116162306a36Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_WR_GFX_CNTL, tmp); 116262306a36Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_RD_PDMA_CNTL, tmp); 116362306a36Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_WR_PDMA_CNTL, tmp); 116462306a36Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_RD_UVD_CNTL, tmp); 116562306a36Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_WR_UVD_CNTL, tmp); 116662306a36Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_RD_SEM_CNTL, tmp | ENABLE_SEMAPHORE_MODE); 116762306a36Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_WR_SEM_CNTL, tmp | ENABLE_SEMAPHORE_MODE); 116862306a36Sopenharmony_ci WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR, rdev->mc.gtt_start >> 12); 116962306a36Sopenharmony_ci WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, rdev->mc.gtt_end >> 12); 117062306a36Sopenharmony_ci WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, rdev->gart.table_addr >> 12); 117162306a36Sopenharmony_ci WREG32(VM_CONTEXT0_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(0) | 117262306a36Sopenharmony_ci RANGE_PROTECTION_FAULT_ENABLE_DEFAULT); 117362306a36Sopenharmony_ci WREG32(VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR, 117462306a36Sopenharmony_ci (u32)(rdev->dummy_page.addr >> 12)); 117562306a36Sopenharmony_ci for (i = 1; i < 7; i++) 117662306a36Sopenharmony_ci WREG32(VM_CONTEXT0_CNTL + (i * 4), 0); 117762306a36Sopenharmony_ci 117862306a36Sopenharmony_ci r600_pcie_gart_tlb_flush(rdev); 117962306a36Sopenharmony_ci DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n", 118062306a36Sopenharmony_ci (unsigned)(rdev->mc.gtt_size >> 20), 118162306a36Sopenharmony_ci (unsigned long long)rdev->gart.table_addr); 118262306a36Sopenharmony_ci rdev->gart.ready = true; 118362306a36Sopenharmony_ci return 0; 118462306a36Sopenharmony_ci} 118562306a36Sopenharmony_ci 118662306a36Sopenharmony_cistatic void r600_pcie_gart_disable(struct radeon_device *rdev) 118762306a36Sopenharmony_ci{ 118862306a36Sopenharmony_ci u32 tmp; 118962306a36Sopenharmony_ci int i; 119062306a36Sopenharmony_ci 119162306a36Sopenharmony_ci /* Disable all tables */ 119262306a36Sopenharmony_ci for (i = 0; i < 7; i++) 119362306a36Sopenharmony_ci WREG32(VM_CONTEXT0_CNTL + (i * 4), 0); 119462306a36Sopenharmony_ci 119562306a36Sopenharmony_ci /* Disable L2 cache */ 119662306a36Sopenharmony_ci WREG32(VM_L2_CNTL, ENABLE_L2_FRAGMENT_PROCESSING | 119762306a36Sopenharmony_ci EFFECTIVE_L2_QUEUE_SIZE(7)); 119862306a36Sopenharmony_ci WREG32(VM_L2_CNTL3, BANK_SELECT_0(0) | BANK_SELECT_1(1)); 119962306a36Sopenharmony_ci /* Setup L1 TLB control */ 120062306a36Sopenharmony_ci tmp = EFFECTIVE_L1_TLB_SIZE(5) | EFFECTIVE_L1_QUEUE_SIZE(5) | 120162306a36Sopenharmony_ci ENABLE_WAIT_L2_QUERY; 120262306a36Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCD_RD_A_CNTL, tmp); 120362306a36Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCD_WR_A_CNTL, tmp); 120462306a36Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCD_RD_B_CNTL, tmp); 120562306a36Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCD_WR_B_CNTL, tmp); 120662306a36Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_RD_GFX_CNTL, tmp); 120762306a36Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_WR_GFX_CNTL, tmp); 120862306a36Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_RD_PDMA_CNTL, tmp); 120962306a36Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_WR_PDMA_CNTL, tmp); 121062306a36Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_RD_SEM_CNTL, tmp); 121162306a36Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_WR_SEM_CNTL, tmp); 121262306a36Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_RD_SYS_CNTL, tmp); 121362306a36Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_WR_SYS_CNTL, tmp); 121462306a36Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_RD_HDP_CNTL, tmp); 121562306a36Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_WR_HDP_CNTL, tmp); 121662306a36Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_RD_UVD_CNTL, tmp); 121762306a36Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_WR_UVD_CNTL, tmp); 121862306a36Sopenharmony_ci radeon_gart_table_vram_unpin(rdev); 121962306a36Sopenharmony_ci} 122062306a36Sopenharmony_ci 122162306a36Sopenharmony_cistatic void r600_pcie_gart_fini(struct radeon_device *rdev) 122262306a36Sopenharmony_ci{ 122362306a36Sopenharmony_ci radeon_gart_fini(rdev); 122462306a36Sopenharmony_ci r600_pcie_gart_disable(rdev); 122562306a36Sopenharmony_ci radeon_gart_table_vram_free(rdev); 122662306a36Sopenharmony_ci} 122762306a36Sopenharmony_ci 122862306a36Sopenharmony_cistatic void r600_agp_enable(struct radeon_device *rdev) 122962306a36Sopenharmony_ci{ 123062306a36Sopenharmony_ci u32 tmp; 123162306a36Sopenharmony_ci int i; 123262306a36Sopenharmony_ci 123362306a36Sopenharmony_ci /* Setup L2 cache */ 123462306a36Sopenharmony_ci WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | ENABLE_L2_FRAGMENT_PROCESSING | 123562306a36Sopenharmony_ci ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE | 123662306a36Sopenharmony_ci EFFECTIVE_L2_QUEUE_SIZE(7)); 123762306a36Sopenharmony_ci WREG32(VM_L2_CNTL2, 0); 123862306a36Sopenharmony_ci WREG32(VM_L2_CNTL3, BANK_SELECT_0(0) | BANK_SELECT_1(1)); 123962306a36Sopenharmony_ci /* Setup TLB control */ 124062306a36Sopenharmony_ci tmp = ENABLE_L1_TLB | ENABLE_L1_FRAGMENT_PROCESSING | 124162306a36Sopenharmony_ci SYSTEM_ACCESS_MODE_NOT_IN_SYS | 124262306a36Sopenharmony_ci EFFECTIVE_L1_TLB_SIZE(5) | EFFECTIVE_L1_QUEUE_SIZE(5) | 124362306a36Sopenharmony_ci ENABLE_WAIT_L2_QUERY; 124462306a36Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_RD_SYS_CNTL, tmp); 124562306a36Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_WR_SYS_CNTL, tmp); 124662306a36Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_RD_HDP_CNTL, tmp | ENABLE_L1_STRICT_ORDERING); 124762306a36Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_WR_HDP_CNTL, tmp); 124862306a36Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCD_RD_A_CNTL, tmp); 124962306a36Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCD_WR_A_CNTL, tmp); 125062306a36Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCD_RD_B_CNTL, tmp); 125162306a36Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCD_WR_B_CNTL, tmp); 125262306a36Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_RD_GFX_CNTL, tmp); 125362306a36Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_WR_GFX_CNTL, tmp); 125462306a36Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_RD_PDMA_CNTL, tmp); 125562306a36Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_WR_PDMA_CNTL, tmp); 125662306a36Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_RD_SEM_CNTL, tmp | ENABLE_SEMAPHORE_MODE); 125762306a36Sopenharmony_ci WREG32(MC_VM_L1_TLB_MCB_WR_SEM_CNTL, tmp | ENABLE_SEMAPHORE_MODE); 125862306a36Sopenharmony_ci for (i = 0; i < 7; i++) 125962306a36Sopenharmony_ci WREG32(VM_CONTEXT0_CNTL + (i * 4), 0); 126062306a36Sopenharmony_ci} 126162306a36Sopenharmony_ci 126262306a36Sopenharmony_ciint r600_mc_wait_for_idle(struct radeon_device *rdev) 126362306a36Sopenharmony_ci{ 126462306a36Sopenharmony_ci unsigned i; 126562306a36Sopenharmony_ci u32 tmp; 126662306a36Sopenharmony_ci 126762306a36Sopenharmony_ci for (i = 0; i < rdev->usec_timeout; i++) { 126862306a36Sopenharmony_ci /* read MC_STATUS */ 126962306a36Sopenharmony_ci tmp = RREG32(R_000E50_SRBM_STATUS) & 0x3F00; 127062306a36Sopenharmony_ci if (!tmp) 127162306a36Sopenharmony_ci return 0; 127262306a36Sopenharmony_ci udelay(1); 127362306a36Sopenharmony_ci } 127462306a36Sopenharmony_ci return -1; 127562306a36Sopenharmony_ci} 127662306a36Sopenharmony_ci 127762306a36Sopenharmony_ciuint32_t rs780_mc_rreg(struct radeon_device *rdev, uint32_t reg) 127862306a36Sopenharmony_ci{ 127962306a36Sopenharmony_ci unsigned long flags; 128062306a36Sopenharmony_ci uint32_t r; 128162306a36Sopenharmony_ci 128262306a36Sopenharmony_ci spin_lock_irqsave(&rdev->mc_idx_lock, flags); 128362306a36Sopenharmony_ci WREG32(R_0028F8_MC_INDEX, S_0028F8_MC_IND_ADDR(reg)); 128462306a36Sopenharmony_ci r = RREG32(R_0028FC_MC_DATA); 128562306a36Sopenharmony_ci WREG32(R_0028F8_MC_INDEX, ~C_0028F8_MC_IND_ADDR); 128662306a36Sopenharmony_ci spin_unlock_irqrestore(&rdev->mc_idx_lock, flags); 128762306a36Sopenharmony_ci return r; 128862306a36Sopenharmony_ci} 128962306a36Sopenharmony_ci 129062306a36Sopenharmony_civoid rs780_mc_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) 129162306a36Sopenharmony_ci{ 129262306a36Sopenharmony_ci unsigned long flags; 129362306a36Sopenharmony_ci 129462306a36Sopenharmony_ci spin_lock_irqsave(&rdev->mc_idx_lock, flags); 129562306a36Sopenharmony_ci WREG32(R_0028F8_MC_INDEX, S_0028F8_MC_IND_ADDR(reg) | 129662306a36Sopenharmony_ci S_0028F8_MC_IND_WR_EN(1)); 129762306a36Sopenharmony_ci WREG32(R_0028FC_MC_DATA, v); 129862306a36Sopenharmony_ci WREG32(R_0028F8_MC_INDEX, 0x7F); 129962306a36Sopenharmony_ci spin_unlock_irqrestore(&rdev->mc_idx_lock, flags); 130062306a36Sopenharmony_ci} 130162306a36Sopenharmony_ci 130262306a36Sopenharmony_cistatic void r600_mc_program(struct radeon_device *rdev) 130362306a36Sopenharmony_ci{ 130462306a36Sopenharmony_ci struct rv515_mc_save save; 130562306a36Sopenharmony_ci u32 tmp; 130662306a36Sopenharmony_ci int i, j; 130762306a36Sopenharmony_ci 130862306a36Sopenharmony_ci /* Initialize HDP */ 130962306a36Sopenharmony_ci for (i = 0, j = 0; i < 32; i++, j += 0x18) { 131062306a36Sopenharmony_ci WREG32((0x2c14 + j), 0x00000000); 131162306a36Sopenharmony_ci WREG32((0x2c18 + j), 0x00000000); 131262306a36Sopenharmony_ci WREG32((0x2c1c + j), 0x00000000); 131362306a36Sopenharmony_ci WREG32((0x2c20 + j), 0x00000000); 131462306a36Sopenharmony_ci WREG32((0x2c24 + j), 0x00000000); 131562306a36Sopenharmony_ci } 131662306a36Sopenharmony_ci WREG32(HDP_REG_COHERENCY_FLUSH_CNTL, 0); 131762306a36Sopenharmony_ci 131862306a36Sopenharmony_ci rv515_mc_stop(rdev, &save); 131962306a36Sopenharmony_ci if (r600_mc_wait_for_idle(rdev)) { 132062306a36Sopenharmony_ci dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); 132162306a36Sopenharmony_ci } 132262306a36Sopenharmony_ci /* Lockout access through VGA aperture (doesn't exist before R600) */ 132362306a36Sopenharmony_ci WREG32(VGA_HDP_CONTROL, VGA_MEMORY_DISABLE); 132462306a36Sopenharmony_ci /* Update configuration */ 132562306a36Sopenharmony_ci if (rdev->flags & RADEON_IS_AGP) { 132662306a36Sopenharmony_ci if (rdev->mc.vram_start < rdev->mc.gtt_start) { 132762306a36Sopenharmony_ci /* VRAM before AGP */ 132862306a36Sopenharmony_ci WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR, 132962306a36Sopenharmony_ci rdev->mc.vram_start >> 12); 133062306a36Sopenharmony_ci WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR, 133162306a36Sopenharmony_ci rdev->mc.gtt_end >> 12); 133262306a36Sopenharmony_ci } else { 133362306a36Sopenharmony_ci /* VRAM after AGP */ 133462306a36Sopenharmony_ci WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR, 133562306a36Sopenharmony_ci rdev->mc.gtt_start >> 12); 133662306a36Sopenharmony_ci WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR, 133762306a36Sopenharmony_ci rdev->mc.vram_end >> 12); 133862306a36Sopenharmony_ci } 133962306a36Sopenharmony_ci } else { 134062306a36Sopenharmony_ci WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR, rdev->mc.vram_start >> 12); 134162306a36Sopenharmony_ci WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR, rdev->mc.vram_end >> 12); 134262306a36Sopenharmony_ci } 134362306a36Sopenharmony_ci WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, rdev->vram_scratch.gpu_addr >> 12); 134462306a36Sopenharmony_ci tmp = ((rdev->mc.vram_end >> 24) & 0xFFFF) << 16; 134562306a36Sopenharmony_ci tmp |= ((rdev->mc.vram_start >> 24) & 0xFFFF); 134662306a36Sopenharmony_ci WREG32(MC_VM_FB_LOCATION, tmp); 134762306a36Sopenharmony_ci WREG32(HDP_NONSURFACE_BASE, (rdev->mc.vram_start >> 8)); 134862306a36Sopenharmony_ci WREG32(HDP_NONSURFACE_INFO, (2 << 7)); 134962306a36Sopenharmony_ci WREG32(HDP_NONSURFACE_SIZE, 0x3FFFFFFF); 135062306a36Sopenharmony_ci if (rdev->flags & RADEON_IS_AGP) { 135162306a36Sopenharmony_ci WREG32(MC_VM_AGP_TOP, rdev->mc.gtt_end >> 22); 135262306a36Sopenharmony_ci WREG32(MC_VM_AGP_BOT, rdev->mc.gtt_start >> 22); 135362306a36Sopenharmony_ci WREG32(MC_VM_AGP_BASE, rdev->mc.agp_base >> 22); 135462306a36Sopenharmony_ci } else { 135562306a36Sopenharmony_ci WREG32(MC_VM_AGP_BASE, 0); 135662306a36Sopenharmony_ci WREG32(MC_VM_AGP_TOP, 0x0FFFFFFF); 135762306a36Sopenharmony_ci WREG32(MC_VM_AGP_BOT, 0x0FFFFFFF); 135862306a36Sopenharmony_ci } 135962306a36Sopenharmony_ci if (r600_mc_wait_for_idle(rdev)) { 136062306a36Sopenharmony_ci dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); 136162306a36Sopenharmony_ci } 136262306a36Sopenharmony_ci rv515_mc_resume(rdev, &save); 136362306a36Sopenharmony_ci /* we need to own VRAM, so turn off the VGA renderer here 136462306a36Sopenharmony_ci * to stop it overwriting our objects */ 136562306a36Sopenharmony_ci rv515_vga_render_disable(rdev); 136662306a36Sopenharmony_ci} 136762306a36Sopenharmony_ci 136862306a36Sopenharmony_ci/** 136962306a36Sopenharmony_ci * r600_vram_gtt_location - try to find VRAM & GTT location 137062306a36Sopenharmony_ci * @rdev: radeon device structure holding all necessary informations 137162306a36Sopenharmony_ci * @mc: memory controller structure holding memory informations 137262306a36Sopenharmony_ci * 137362306a36Sopenharmony_ci * Function will place try to place VRAM at same place as in CPU (PCI) 137462306a36Sopenharmony_ci * address space as some GPU seems to have issue when we reprogram at 137562306a36Sopenharmony_ci * different address space. 137662306a36Sopenharmony_ci * 137762306a36Sopenharmony_ci * If there is not enough space to fit the unvisible VRAM after the 137862306a36Sopenharmony_ci * aperture then we limit the VRAM size to the aperture. 137962306a36Sopenharmony_ci * 138062306a36Sopenharmony_ci * If we are using AGP then place VRAM adjacent to AGP aperture are we need 138162306a36Sopenharmony_ci * them to be in one from GPU point of view so that we can program GPU to 138262306a36Sopenharmony_ci * catch access outside them (weird GPU policy see ??). 138362306a36Sopenharmony_ci * 138462306a36Sopenharmony_ci * This function will never fails, worst case are limiting VRAM or GTT. 138562306a36Sopenharmony_ci * 138662306a36Sopenharmony_ci * Note: GTT start, end, size should be initialized before calling this 138762306a36Sopenharmony_ci * function on AGP platform. 138862306a36Sopenharmony_ci */ 138962306a36Sopenharmony_cistatic void r600_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc) 139062306a36Sopenharmony_ci{ 139162306a36Sopenharmony_ci u64 size_bf, size_af; 139262306a36Sopenharmony_ci 139362306a36Sopenharmony_ci if (mc->mc_vram_size > 0xE0000000) { 139462306a36Sopenharmony_ci /* leave room for at least 512M GTT */ 139562306a36Sopenharmony_ci dev_warn(rdev->dev, "limiting VRAM\n"); 139662306a36Sopenharmony_ci mc->real_vram_size = 0xE0000000; 139762306a36Sopenharmony_ci mc->mc_vram_size = 0xE0000000; 139862306a36Sopenharmony_ci } 139962306a36Sopenharmony_ci if (rdev->flags & RADEON_IS_AGP) { 140062306a36Sopenharmony_ci size_bf = mc->gtt_start; 140162306a36Sopenharmony_ci size_af = mc->mc_mask - mc->gtt_end; 140262306a36Sopenharmony_ci if (size_bf > size_af) { 140362306a36Sopenharmony_ci if (mc->mc_vram_size > size_bf) { 140462306a36Sopenharmony_ci dev_warn(rdev->dev, "limiting VRAM\n"); 140562306a36Sopenharmony_ci mc->real_vram_size = size_bf; 140662306a36Sopenharmony_ci mc->mc_vram_size = size_bf; 140762306a36Sopenharmony_ci } 140862306a36Sopenharmony_ci mc->vram_start = mc->gtt_start - mc->mc_vram_size; 140962306a36Sopenharmony_ci } else { 141062306a36Sopenharmony_ci if (mc->mc_vram_size > size_af) { 141162306a36Sopenharmony_ci dev_warn(rdev->dev, "limiting VRAM\n"); 141262306a36Sopenharmony_ci mc->real_vram_size = size_af; 141362306a36Sopenharmony_ci mc->mc_vram_size = size_af; 141462306a36Sopenharmony_ci } 141562306a36Sopenharmony_ci mc->vram_start = mc->gtt_end + 1; 141662306a36Sopenharmony_ci } 141762306a36Sopenharmony_ci mc->vram_end = mc->vram_start + mc->mc_vram_size - 1; 141862306a36Sopenharmony_ci dev_info(rdev->dev, "VRAM: %lluM 0x%08llX - 0x%08llX (%lluM used)\n", 141962306a36Sopenharmony_ci mc->mc_vram_size >> 20, mc->vram_start, 142062306a36Sopenharmony_ci mc->vram_end, mc->real_vram_size >> 20); 142162306a36Sopenharmony_ci } else { 142262306a36Sopenharmony_ci u64 base = 0; 142362306a36Sopenharmony_ci if (rdev->flags & RADEON_IS_IGP) { 142462306a36Sopenharmony_ci base = RREG32(MC_VM_FB_LOCATION) & 0xFFFF; 142562306a36Sopenharmony_ci base <<= 24; 142662306a36Sopenharmony_ci } 142762306a36Sopenharmony_ci radeon_vram_location(rdev, &rdev->mc, base); 142862306a36Sopenharmony_ci rdev->mc.gtt_base_align = 0; 142962306a36Sopenharmony_ci radeon_gtt_location(rdev, mc); 143062306a36Sopenharmony_ci } 143162306a36Sopenharmony_ci} 143262306a36Sopenharmony_ci 143362306a36Sopenharmony_cistatic int r600_mc_init(struct radeon_device *rdev) 143462306a36Sopenharmony_ci{ 143562306a36Sopenharmony_ci u32 tmp; 143662306a36Sopenharmony_ci int chansize, numchan; 143762306a36Sopenharmony_ci uint32_t h_addr, l_addr; 143862306a36Sopenharmony_ci unsigned long long k8_addr; 143962306a36Sopenharmony_ci 144062306a36Sopenharmony_ci /* Get VRAM informations */ 144162306a36Sopenharmony_ci rdev->mc.vram_is_ddr = true; 144262306a36Sopenharmony_ci tmp = RREG32(RAMCFG); 144362306a36Sopenharmony_ci if (tmp & CHANSIZE_OVERRIDE) { 144462306a36Sopenharmony_ci chansize = 16; 144562306a36Sopenharmony_ci } else if (tmp & CHANSIZE_MASK) { 144662306a36Sopenharmony_ci chansize = 64; 144762306a36Sopenharmony_ci } else { 144862306a36Sopenharmony_ci chansize = 32; 144962306a36Sopenharmony_ci } 145062306a36Sopenharmony_ci tmp = RREG32(CHMAP); 145162306a36Sopenharmony_ci switch ((tmp & NOOFCHAN_MASK) >> NOOFCHAN_SHIFT) { 145262306a36Sopenharmony_ci case 0: 145362306a36Sopenharmony_ci default: 145462306a36Sopenharmony_ci numchan = 1; 145562306a36Sopenharmony_ci break; 145662306a36Sopenharmony_ci case 1: 145762306a36Sopenharmony_ci numchan = 2; 145862306a36Sopenharmony_ci break; 145962306a36Sopenharmony_ci case 2: 146062306a36Sopenharmony_ci numchan = 4; 146162306a36Sopenharmony_ci break; 146262306a36Sopenharmony_ci case 3: 146362306a36Sopenharmony_ci numchan = 8; 146462306a36Sopenharmony_ci break; 146562306a36Sopenharmony_ci } 146662306a36Sopenharmony_ci rdev->mc.vram_width = numchan * chansize; 146762306a36Sopenharmony_ci /* Could aper size report 0 ? */ 146862306a36Sopenharmony_ci rdev->mc.aper_base = pci_resource_start(rdev->pdev, 0); 146962306a36Sopenharmony_ci rdev->mc.aper_size = pci_resource_len(rdev->pdev, 0); 147062306a36Sopenharmony_ci /* Setup GPU memory space */ 147162306a36Sopenharmony_ci rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE); 147262306a36Sopenharmony_ci rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE); 147362306a36Sopenharmony_ci rdev->mc.visible_vram_size = rdev->mc.aper_size; 147462306a36Sopenharmony_ci r600_vram_gtt_location(rdev, &rdev->mc); 147562306a36Sopenharmony_ci 147662306a36Sopenharmony_ci if (rdev->flags & RADEON_IS_IGP) { 147762306a36Sopenharmony_ci rs690_pm_info(rdev); 147862306a36Sopenharmony_ci rdev->mc.igp_sideport_enabled = radeon_atombios_sideport_present(rdev); 147962306a36Sopenharmony_ci 148062306a36Sopenharmony_ci if (rdev->family == CHIP_RS780 || rdev->family == CHIP_RS880) { 148162306a36Sopenharmony_ci /* Use K8 direct mapping for fast fb access. */ 148262306a36Sopenharmony_ci rdev->fastfb_working = false; 148362306a36Sopenharmony_ci h_addr = G_000012_K8_ADDR_EXT(RREG32_MC(R_000012_MC_MISC_UMA_CNTL)); 148462306a36Sopenharmony_ci l_addr = RREG32_MC(R_000011_K8_FB_LOCATION); 148562306a36Sopenharmony_ci k8_addr = ((unsigned long long)h_addr) << 32 | l_addr; 148662306a36Sopenharmony_ci#if defined(CONFIG_X86_32) && !defined(CONFIG_X86_PAE) 148762306a36Sopenharmony_ci if (k8_addr + rdev->mc.visible_vram_size < 0x100000000ULL) 148862306a36Sopenharmony_ci#endif 148962306a36Sopenharmony_ci { 149062306a36Sopenharmony_ci /* FastFB shall be used with UMA memory. Here it is simply disabled when sideport 149162306a36Sopenharmony_ci * memory is present. 149262306a36Sopenharmony_ci */ 149362306a36Sopenharmony_ci if (rdev->mc.igp_sideport_enabled == false && radeon_fastfb == 1) { 149462306a36Sopenharmony_ci DRM_INFO("Direct mapping: aper base at 0x%llx, replaced by direct mapping base 0x%llx.\n", 149562306a36Sopenharmony_ci (unsigned long long)rdev->mc.aper_base, k8_addr); 149662306a36Sopenharmony_ci rdev->mc.aper_base = (resource_size_t)k8_addr; 149762306a36Sopenharmony_ci rdev->fastfb_working = true; 149862306a36Sopenharmony_ci } 149962306a36Sopenharmony_ci } 150062306a36Sopenharmony_ci } 150162306a36Sopenharmony_ci } 150262306a36Sopenharmony_ci 150362306a36Sopenharmony_ci radeon_update_bandwidth_info(rdev); 150462306a36Sopenharmony_ci return 0; 150562306a36Sopenharmony_ci} 150662306a36Sopenharmony_ci 150762306a36Sopenharmony_ciint r600_vram_scratch_init(struct radeon_device *rdev) 150862306a36Sopenharmony_ci{ 150962306a36Sopenharmony_ci int r; 151062306a36Sopenharmony_ci 151162306a36Sopenharmony_ci if (rdev->vram_scratch.robj == NULL) { 151262306a36Sopenharmony_ci r = radeon_bo_create(rdev, RADEON_GPU_PAGE_SIZE, 151362306a36Sopenharmony_ci PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM, 151462306a36Sopenharmony_ci 0, NULL, NULL, &rdev->vram_scratch.robj); 151562306a36Sopenharmony_ci if (r) { 151662306a36Sopenharmony_ci return r; 151762306a36Sopenharmony_ci } 151862306a36Sopenharmony_ci } 151962306a36Sopenharmony_ci 152062306a36Sopenharmony_ci r = radeon_bo_reserve(rdev->vram_scratch.robj, false); 152162306a36Sopenharmony_ci if (unlikely(r != 0)) 152262306a36Sopenharmony_ci return r; 152362306a36Sopenharmony_ci r = radeon_bo_pin(rdev->vram_scratch.robj, 152462306a36Sopenharmony_ci RADEON_GEM_DOMAIN_VRAM, &rdev->vram_scratch.gpu_addr); 152562306a36Sopenharmony_ci if (r) { 152662306a36Sopenharmony_ci radeon_bo_unreserve(rdev->vram_scratch.robj); 152762306a36Sopenharmony_ci return r; 152862306a36Sopenharmony_ci } 152962306a36Sopenharmony_ci r = radeon_bo_kmap(rdev->vram_scratch.robj, 153062306a36Sopenharmony_ci (void **)&rdev->vram_scratch.ptr); 153162306a36Sopenharmony_ci if (r) 153262306a36Sopenharmony_ci radeon_bo_unpin(rdev->vram_scratch.robj); 153362306a36Sopenharmony_ci radeon_bo_unreserve(rdev->vram_scratch.robj); 153462306a36Sopenharmony_ci 153562306a36Sopenharmony_ci return r; 153662306a36Sopenharmony_ci} 153762306a36Sopenharmony_ci 153862306a36Sopenharmony_civoid r600_vram_scratch_fini(struct radeon_device *rdev) 153962306a36Sopenharmony_ci{ 154062306a36Sopenharmony_ci int r; 154162306a36Sopenharmony_ci 154262306a36Sopenharmony_ci if (rdev->vram_scratch.robj == NULL) { 154362306a36Sopenharmony_ci return; 154462306a36Sopenharmony_ci } 154562306a36Sopenharmony_ci r = radeon_bo_reserve(rdev->vram_scratch.robj, false); 154662306a36Sopenharmony_ci if (likely(r == 0)) { 154762306a36Sopenharmony_ci radeon_bo_kunmap(rdev->vram_scratch.robj); 154862306a36Sopenharmony_ci radeon_bo_unpin(rdev->vram_scratch.robj); 154962306a36Sopenharmony_ci radeon_bo_unreserve(rdev->vram_scratch.robj); 155062306a36Sopenharmony_ci } 155162306a36Sopenharmony_ci radeon_bo_unref(&rdev->vram_scratch.robj); 155262306a36Sopenharmony_ci} 155362306a36Sopenharmony_ci 155462306a36Sopenharmony_civoid r600_set_bios_scratch_engine_hung(struct radeon_device *rdev, bool hung) 155562306a36Sopenharmony_ci{ 155662306a36Sopenharmony_ci u32 tmp = RREG32(R600_BIOS_3_SCRATCH); 155762306a36Sopenharmony_ci 155862306a36Sopenharmony_ci if (hung) 155962306a36Sopenharmony_ci tmp |= ATOM_S3_ASIC_GUI_ENGINE_HUNG; 156062306a36Sopenharmony_ci else 156162306a36Sopenharmony_ci tmp &= ~ATOM_S3_ASIC_GUI_ENGINE_HUNG; 156262306a36Sopenharmony_ci 156362306a36Sopenharmony_ci WREG32(R600_BIOS_3_SCRATCH, tmp); 156462306a36Sopenharmony_ci} 156562306a36Sopenharmony_ci 156662306a36Sopenharmony_cistatic void r600_print_gpu_status_regs(struct radeon_device *rdev) 156762306a36Sopenharmony_ci{ 156862306a36Sopenharmony_ci dev_info(rdev->dev, " R_008010_GRBM_STATUS = 0x%08X\n", 156962306a36Sopenharmony_ci RREG32(R_008010_GRBM_STATUS)); 157062306a36Sopenharmony_ci dev_info(rdev->dev, " R_008014_GRBM_STATUS2 = 0x%08X\n", 157162306a36Sopenharmony_ci RREG32(R_008014_GRBM_STATUS2)); 157262306a36Sopenharmony_ci dev_info(rdev->dev, " R_000E50_SRBM_STATUS = 0x%08X\n", 157362306a36Sopenharmony_ci RREG32(R_000E50_SRBM_STATUS)); 157462306a36Sopenharmony_ci dev_info(rdev->dev, " R_008674_CP_STALLED_STAT1 = 0x%08X\n", 157562306a36Sopenharmony_ci RREG32(CP_STALLED_STAT1)); 157662306a36Sopenharmony_ci dev_info(rdev->dev, " R_008678_CP_STALLED_STAT2 = 0x%08X\n", 157762306a36Sopenharmony_ci RREG32(CP_STALLED_STAT2)); 157862306a36Sopenharmony_ci dev_info(rdev->dev, " R_00867C_CP_BUSY_STAT = 0x%08X\n", 157962306a36Sopenharmony_ci RREG32(CP_BUSY_STAT)); 158062306a36Sopenharmony_ci dev_info(rdev->dev, " R_008680_CP_STAT = 0x%08X\n", 158162306a36Sopenharmony_ci RREG32(CP_STAT)); 158262306a36Sopenharmony_ci dev_info(rdev->dev, " R_00D034_DMA_STATUS_REG = 0x%08X\n", 158362306a36Sopenharmony_ci RREG32(DMA_STATUS_REG)); 158462306a36Sopenharmony_ci} 158562306a36Sopenharmony_ci 158662306a36Sopenharmony_cistatic bool r600_is_display_hung(struct radeon_device *rdev) 158762306a36Sopenharmony_ci{ 158862306a36Sopenharmony_ci u32 crtc_hung = 0; 158962306a36Sopenharmony_ci u32 crtc_status[2]; 159062306a36Sopenharmony_ci u32 i, j, tmp; 159162306a36Sopenharmony_ci 159262306a36Sopenharmony_ci for (i = 0; i < rdev->num_crtc; i++) { 159362306a36Sopenharmony_ci if (RREG32(AVIVO_D1CRTC_CONTROL + crtc_offsets[i]) & AVIVO_CRTC_EN) { 159462306a36Sopenharmony_ci crtc_status[i] = RREG32(AVIVO_D1CRTC_STATUS_HV_COUNT + crtc_offsets[i]); 159562306a36Sopenharmony_ci crtc_hung |= (1 << i); 159662306a36Sopenharmony_ci } 159762306a36Sopenharmony_ci } 159862306a36Sopenharmony_ci 159962306a36Sopenharmony_ci for (j = 0; j < 10; j++) { 160062306a36Sopenharmony_ci for (i = 0; i < rdev->num_crtc; i++) { 160162306a36Sopenharmony_ci if (crtc_hung & (1 << i)) { 160262306a36Sopenharmony_ci tmp = RREG32(AVIVO_D1CRTC_STATUS_HV_COUNT + crtc_offsets[i]); 160362306a36Sopenharmony_ci if (tmp != crtc_status[i]) 160462306a36Sopenharmony_ci crtc_hung &= ~(1 << i); 160562306a36Sopenharmony_ci } 160662306a36Sopenharmony_ci } 160762306a36Sopenharmony_ci if (crtc_hung == 0) 160862306a36Sopenharmony_ci return false; 160962306a36Sopenharmony_ci udelay(100); 161062306a36Sopenharmony_ci } 161162306a36Sopenharmony_ci 161262306a36Sopenharmony_ci return true; 161362306a36Sopenharmony_ci} 161462306a36Sopenharmony_ci 161562306a36Sopenharmony_ciu32 r600_gpu_check_soft_reset(struct radeon_device *rdev) 161662306a36Sopenharmony_ci{ 161762306a36Sopenharmony_ci u32 reset_mask = 0; 161862306a36Sopenharmony_ci u32 tmp; 161962306a36Sopenharmony_ci 162062306a36Sopenharmony_ci /* GRBM_STATUS */ 162162306a36Sopenharmony_ci tmp = RREG32(R_008010_GRBM_STATUS); 162262306a36Sopenharmony_ci if (rdev->family >= CHIP_RV770) { 162362306a36Sopenharmony_ci if (G_008010_PA_BUSY(tmp) | G_008010_SC_BUSY(tmp) | 162462306a36Sopenharmony_ci G_008010_SH_BUSY(tmp) | G_008010_SX_BUSY(tmp) | 162562306a36Sopenharmony_ci G_008010_TA_BUSY(tmp) | G_008010_VGT_BUSY(tmp) | 162662306a36Sopenharmony_ci G_008010_DB03_BUSY(tmp) | G_008010_CB03_BUSY(tmp) | 162762306a36Sopenharmony_ci G_008010_SPI03_BUSY(tmp) | G_008010_VGT_BUSY_NO_DMA(tmp)) 162862306a36Sopenharmony_ci reset_mask |= RADEON_RESET_GFX; 162962306a36Sopenharmony_ci } else { 163062306a36Sopenharmony_ci if (G_008010_PA_BUSY(tmp) | G_008010_SC_BUSY(tmp) | 163162306a36Sopenharmony_ci G_008010_SH_BUSY(tmp) | G_008010_SX_BUSY(tmp) | 163262306a36Sopenharmony_ci G_008010_TA03_BUSY(tmp) | G_008010_VGT_BUSY(tmp) | 163362306a36Sopenharmony_ci G_008010_DB03_BUSY(tmp) | G_008010_CB03_BUSY(tmp) | 163462306a36Sopenharmony_ci G_008010_SPI03_BUSY(tmp) | G_008010_VGT_BUSY_NO_DMA(tmp)) 163562306a36Sopenharmony_ci reset_mask |= RADEON_RESET_GFX; 163662306a36Sopenharmony_ci } 163762306a36Sopenharmony_ci 163862306a36Sopenharmony_ci if (G_008010_CF_RQ_PENDING(tmp) | G_008010_PF_RQ_PENDING(tmp) | 163962306a36Sopenharmony_ci G_008010_CP_BUSY(tmp) | G_008010_CP_COHERENCY_BUSY(tmp)) 164062306a36Sopenharmony_ci reset_mask |= RADEON_RESET_CP; 164162306a36Sopenharmony_ci 164262306a36Sopenharmony_ci if (G_008010_GRBM_EE_BUSY(tmp)) 164362306a36Sopenharmony_ci reset_mask |= RADEON_RESET_GRBM | RADEON_RESET_GFX | RADEON_RESET_CP; 164462306a36Sopenharmony_ci 164562306a36Sopenharmony_ci /* DMA_STATUS_REG */ 164662306a36Sopenharmony_ci tmp = RREG32(DMA_STATUS_REG); 164762306a36Sopenharmony_ci if (!(tmp & DMA_IDLE)) 164862306a36Sopenharmony_ci reset_mask |= RADEON_RESET_DMA; 164962306a36Sopenharmony_ci 165062306a36Sopenharmony_ci /* SRBM_STATUS */ 165162306a36Sopenharmony_ci tmp = RREG32(R_000E50_SRBM_STATUS); 165262306a36Sopenharmony_ci if (G_000E50_RLC_RQ_PENDING(tmp) | G_000E50_RLC_BUSY(tmp)) 165362306a36Sopenharmony_ci reset_mask |= RADEON_RESET_RLC; 165462306a36Sopenharmony_ci 165562306a36Sopenharmony_ci if (G_000E50_IH_BUSY(tmp)) 165662306a36Sopenharmony_ci reset_mask |= RADEON_RESET_IH; 165762306a36Sopenharmony_ci 165862306a36Sopenharmony_ci if (G_000E50_SEM_BUSY(tmp)) 165962306a36Sopenharmony_ci reset_mask |= RADEON_RESET_SEM; 166062306a36Sopenharmony_ci 166162306a36Sopenharmony_ci if (G_000E50_GRBM_RQ_PENDING(tmp)) 166262306a36Sopenharmony_ci reset_mask |= RADEON_RESET_GRBM; 166362306a36Sopenharmony_ci 166462306a36Sopenharmony_ci if (G_000E50_VMC_BUSY(tmp)) 166562306a36Sopenharmony_ci reset_mask |= RADEON_RESET_VMC; 166662306a36Sopenharmony_ci 166762306a36Sopenharmony_ci if (G_000E50_MCB_BUSY(tmp) | G_000E50_MCDZ_BUSY(tmp) | 166862306a36Sopenharmony_ci G_000E50_MCDY_BUSY(tmp) | G_000E50_MCDX_BUSY(tmp) | 166962306a36Sopenharmony_ci G_000E50_MCDW_BUSY(tmp)) 167062306a36Sopenharmony_ci reset_mask |= RADEON_RESET_MC; 167162306a36Sopenharmony_ci 167262306a36Sopenharmony_ci if (r600_is_display_hung(rdev)) 167362306a36Sopenharmony_ci reset_mask |= RADEON_RESET_DISPLAY; 167462306a36Sopenharmony_ci 167562306a36Sopenharmony_ci /* Skip MC reset as it's mostly likely not hung, just busy */ 167662306a36Sopenharmony_ci if (reset_mask & RADEON_RESET_MC) { 167762306a36Sopenharmony_ci DRM_DEBUG("MC busy: 0x%08X, clearing.\n", reset_mask); 167862306a36Sopenharmony_ci reset_mask &= ~RADEON_RESET_MC; 167962306a36Sopenharmony_ci } 168062306a36Sopenharmony_ci 168162306a36Sopenharmony_ci return reset_mask; 168262306a36Sopenharmony_ci} 168362306a36Sopenharmony_ci 168462306a36Sopenharmony_cistatic void r600_gpu_soft_reset(struct radeon_device *rdev, u32 reset_mask) 168562306a36Sopenharmony_ci{ 168662306a36Sopenharmony_ci struct rv515_mc_save save; 168762306a36Sopenharmony_ci u32 grbm_soft_reset = 0, srbm_soft_reset = 0; 168862306a36Sopenharmony_ci u32 tmp; 168962306a36Sopenharmony_ci 169062306a36Sopenharmony_ci if (reset_mask == 0) 169162306a36Sopenharmony_ci return; 169262306a36Sopenharmony_ci 169362306a36Sopenharmony_ci dev_info(rdev->dev, "GPU softreset: 0x%08X\n", reset_mask); 169462306a36Sopenharmony_ci 169562306a36Sopenharmony_ci r600_print_gpu_status_regs(rdev); 169662306a36Sopenharmony_ci 169762306a36Sopenharmony_ci /* Disable CP parsing/prefetching */ 169862306a36Sopenharmony_ci if (rdev->family >= CHIP_RV770) 169962306a36Sopenharmony_ci WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1) | S_0086D8_CP_PFP_HALT(1)); 170062306a36Sopenharmony_ci else 170162306a36Sopenharmony_ci WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1)); 170262306a36Sopenharmony_ci 170362306a36Sopenharmony_ci /* disable the RLC */ 170462306a36Sopenharmony_ci WREG32(RLC_CNTL, 0); 170562306a36Sopenharmony_ci 170662306a36Sopenharmony_ci if (reset_mask & RADEON_RESET_DMA) { 170762306a36Sopenharmony_ci /* Disable DMA */ 170862306a36Sopenharmony_ci tmp = RREG32(DMA_RB_CNTL); 170962306a36Sopenharmony_ci tmp &= ~DMA_RB_ENABLE; 171062306a36Sopenharmony_ci WREG32(DMA_RB_CNTL, tmp); 171162306a36Sopenharmony_ci } 171262306a36Sopenharmony_ci 171362306a36Sopenharmony_ci mdelay(50); 171462306a36Sopenharmony_ci 171562306a36Sopenharmony_ci rv515_mc_stop(rdev, &save); 171662306a36Sopenharmony_ci if (r600_mc_wait_for_idle(rdev)) { 171762306a36Sopenharmony_ci dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); 171862306a36Sopenharmony_ci } 171962306a36Sopenharmony_ci 172062306a36Sopenharmony_ci if (reset_mask & (RADEON_RESET_GFX | RADEON_RESET_COMPUTE)) { 172162306a36Sopenharmony_ci if (rdev->family >= CHIP_RV770) 172262306a36Sopenharmony_ci grbm_soft_reset |= S_008020_SOFT_RESET_DB(1) | 172362306a36Sopenharmony_ci S_008020_SOFT_RESET_CB(1) | 172462306a36Sopenharmony_ci S_008020_SOFT_RESET_PA(1) | 172562306a36Sopenharmony_ci S_008020_SOFT_RESET_SC(1) | 172662306a36Sopenharmony_ci S_008020_SOFT_RESET_SPI(1) | 172762306a36Sopenharmony_ci S_008020_SOFT_RESET_SX(1) | 172862306a36Sopenharmony_ci S_008020_SOFT_RESET_SH(1) | 172962306a36Sopenharmony_ci S_008020_SOFT_RESET_TC(1) | 173062306a36Sopenharmony_ci S_008020_SOFT_RESET_TA(1) | 173162306a36Sopenharmony_ci S_008020_SOFT_RESET_VC(1) | 173262306a36Sopenharmony_ci S_008020_SOFT_RESET_VGT(1); 173362306a36Sopenharmony_ci else 173462306a36Sopenharmony_ci grbm_soft_reset |= S_008020_SOFT_RESET_CR(1) | 173562306a36Sopenharmony_ci S_008020_SOFT_RESET_DB(1) | 173662306a36Sopenharmony_ci S_008020_SOFT_RESET_CB(1) | 173762306a36Sopenharmony_ci S_008020_SOFT_RESET_PA(1) | 173862306a36Sopenharmony_ci S_008020_SOFT_RESET_SC(1) | 173962306a36Sopenharmony_ci S_008020_SOFT_RESET_SMX(1) | 174062306a36Sopenharmony_ci S_008020_SOFT_RESET_SPI(1) | 174162306a36Sopenharmony_ci S_008020_SOFT_RESET_SX(1) | 174262306a36Sopenharmony_ci S_008020_SOFT_RESET_SH(1) | 174362306a36Sopenharmony_ci S_008020_SOFT_RESET_TC(1) | 174462306a36Sopenharmony_ci S_008020_SOFT_RESET_TA(1) | 174562306a36Sopenharmony_ci S_008020_SOFT_RESET_VC(1) | 174662306a36Sopenharmony_ci S_008020_SOFT_RESET_VGT(1); 174762306a36Sopenharmony_ci } 174862306a36Sopenharmony_ci 174962306a36Sopenharmony_ci if (reset_mask & RADEON_RESET_CP) { 175062306a36Sopenharmony_ci grbm_soft_reset |= S_008020_SOFT_RESET_CP(1) | 175162306a36Sopenharmony_ci S_008020_SOFT_RESET_VGT(1); 175262306a36Sopenharmony_ci 175362306a36Sopenharmony_ci srbm_soft_reset |= S_000E60_SOFT_RESET_GRBM(1); 175462306a36Sopenharmony_ci } 175562306a36Sopenharmony_ci 175662306a36Sopenharmony_ci if (reset_mask & RADEON_RESET_DMA) { 175762306a36Sopenharmony_ci if (rdev->family >= CHIP_RV770) 175862306a36Sopenharmony_ci srbm_soft_reset |= RV770_SOFT_RESET_DMA; 175962306a36Sopenharmony_ci else 176062306a36Sopenharmony_ci srbm_soft_reset |= SOFT_RESET_DMA; 176162306a36Sopenharmony_ci } 176262306a36Sopenharmony_ci 176362306a36Sopenharmony_ci if (reset_mask & RADEON_RESET_RLC) 176462306a36Sopenharmony_ci srbm_soft_reset |= S_000E60_SOFT_RESET_RLC(1); 176562306a36Sopenharmony_ci 176662306a36Sopenharmony_ci if (reset_mask & RADEON_RESET_SEM) 176762306a36Sopenharmony_ci srbm_soft_reset |= S_000E60_SOFT_RESET_SEM(1); 176862306a36Sopenharmony_ci 176962306a36Sopenharmony_ci if (reset_mask & RADEON_RESET_IH) 177062306a36Sopenharmony_ci srbm_soft_reset |= S_000E60_SOFT_RESET_IH(1); 177162306a36Sopenharmony_ci 177262306a36Sopenharmony_ci if (reset_mask & RADEON_RESET_GRBM) 177362306a36Sopenharmony_ci srbm_soft_reset |= S_000E60_SOFT_RESET_GRBM(1); 177462306a36Sopenharmony_ci 177562306a36Sopenharmony_ci if (!(rdev->flags & RADEON_IS_IGP)) { 177662306a36Sopenharmony_ci if (reset_mask & RADEON_RESET_MC) 177762306a36Sopenharmony_ci srbm_soft_reset |= S_000E60_SOFT_RESET_MC(1); 177862306a36Sopenharmony_ci } 177962306a36Sopenharmony_ci 178062306a36Sopenharmony_ci if (reset_mask & RADEON_RESET_VMC) 178162306a36Sopenharmony_ci srbm_soft_reset |= S_000E60_SOFT_RESET_VMC(1); 178262306a36Sopenharmony_ci 178362306a36Sopenharmony_ci if (grbm_soft_reset) { 178462306a36Sopenharmony_ci tmp = RREG32(R_008020_GRBM_SOFT_RESET); 178562306a36Sopenharmony_ci tmp |= grbm_soft_reset; 178662306a36Sopenharmony_ci dev_info(rdev->dev, "R_008020_GRBM_SOFT_RESET=0x%08X\n", tmp); 178762306a36Sopenharmony_ci WREG32(R_008020_GRBM_SOFT_RESET, tmp); 178862306a36Sopenharmony_ci tmp = RREG32(R_008020_GRBM_SOFT_RESET); 178962306a36Sopenharmony_ci 179062306a36Sopenharmony_ci udelay(50); 179162306a36Sopenharmony_ci 179262306a36Sopenharmony_ci tmp &= ~grbm_soft_reset; 179362306a36Sopenharmony_ci WREG32(R_008020_GRBM_SOFT_RESET, tmp); 179462306a36Sopenharmony_ci tmp = RREG32(R_008020_GRBM_SOFT_RESET); 179562306a36Sopenharmony_ci } 179662306a36Sopenharmony_ci 179762306a36Sopenharmony_ci if (srbm_soft_reset) { 179862306a36Sopenharmony_ci tmp = RREG32(SRBM_SOFT_RESET); 179962306a36Sopenharmony_ci tmp |= srbm_soft_reset; 180062306a36Sopenharmony_ci dev_info(rdev->dev, "SRBM_SOFT_RESET=0x%08X\n", tmp); 180162306a36Sopenharmony_ci WREG32(SRBM_SOFT_RESET, tmp); 180262306a36Sopenharmony_ci tmp = RREG32(SRBM_SOFT_RESET); 180362306a36Sopenharmony_ci 180462306a36Sopenharmony_ci udelay(50); 180562306a36Sopenharmony_ci 180662306a36Sopenharmony_ci tmp &= ~srbm_soft_reset; 180762306a36Sopenharmony_ci WREG32(SRBM_SOFT_RESET, tmp); 180862306a36Sopenharmony_ci tmp = RREG32(SRBM_SOFT_RESET); 180962306a36Sopenharmony_ci } 181062306a36Sopenharmony_ci 181162306a36Sopenharmony_ci /* Wait a little for things to settle down */ 181262306a36Sopenharmony_ci mdelay(1); 181362306a36Sopenharmony_ci 181462306a36Sopenharmony_ci rv515_mc_resume(rdev, &save); 181562306a36Sopenharmony_ci udelay(50); 181662306a36Sopenharmony_ci 181762306a36Sopenharmony_ci r600_print_gpu_status_regs(rdev); 181862306a36Sopenharmony_ci} 181962306a36Sopenharmony_ci 182062306a36Sopenharmony_cistatic void r600_gpu_pci_config_reset(struct radeon_device *rdev) 182162306a36Sopenharmony_ci{ 182262306a36Sopenharmony_ci struct rv515_mc_save save; 182362306a36Sopenharmony_ci u32 tmp, i; 182462306a36Sopenharmony_ci 182562306a36Sopenharmony_ci dev_info(rdev->dev, "GPU pci config reset\n"); 182662306a36Sopenharmony_ci 182762306a36Sopenharmony_ci /* disable dpm? */ 182862306a36Sopenharmony_ci 182962306a36Sopenharmony_ci /* Disable CP parsing/prefetching */ 183062306a36Sopenharmony_ci if (rdev->family >= CHIP_RV770) 183162306a36Sopenharmony_ci WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1) | S_0086D8_CP_PFP_HALT(1)); 183262306a36Sopenharmony_ci else 183362306a36Sopenharmony_ci WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1)); 183462306a36Sopenharmony_ci 183562306a36Sopenharmony_ci /* disable the RLC */ 183662306a36Sopenharmony_ci WREG32(RLC_CNTL, 0); 183762306a36Sopenharmony_ci 183862306a36Sopenharmony_ci /* Disable DMA */ 183962306a36Sopenharmony_ci tmp = RREG32(DMA_RB_CNTL); 184062306a36Sopenharmony_ci tmp &= ~DMA_RB_ENABLE; 184162306a36Sopenharmony_ci WREG32(DMA_RB_CNTL, tmp); 184262306a36Sopenharmony_ci 184362306a36Sopenharmony_ci mdelay(50); 184462306a36Sopenharmony_ci 184562306a36Sopenharmony_ci /* set mclk/sclk to bypass */ 184662306a36Sopenharmony_ci if (rdev->family >= CHIP_RV770) 184762306a36Sopenharmony_ci rv770_set_clk_bypass_mode(rdev); 184862306a36Sopenharmony_ci /* disable BM */ 184962306a36Sopenharmony_ci pci_clear_master(rdev->pdev); 185062306a36Sopenharmony_ci /* disable mem access */ 185162306a36Sopenharmony_ci rv515_mc_stop(rdev, &save); 185262306a36Sopenharmony_ci if (r600_mc_wait_for_idle(rdev)) { 185362306a36Sopenharmony_ci dev_warn(rdev->dev, "Wait for MC idle timedout !\n"); 185462306a36Sopenharmony_ci } 185562306a36Sopenharmony_ci 185662306a36Sopenharmony_ci /* BIF reset workaround. Not sure if this is needed on 6xx */ 185762306a36Sopenharmony_ci tmp = RREG32(BUS_CNTL); 185862306a36Sopenharmony_ci tmp |= VGA_COHE_SPEC_TIMER_DIS; 185962306a36Sopenharmony_ci WREG32(BUS_CNTL, tmp); 186062306a36Sopenharmony_ci 186162306a36Sopenharmony_ci tmp = RREG32(BIF_SCRATCH0); 186262306a36Sopenharmony_ci 186362306a36Sopenharmony_ci /* reset */ 186462306a36Sopenharmony_ci radeon_pci_config_reset(rdev); 186562306a36Sopenharmony_ci mdelay(1); 186662306a36Sopenharmony_ci 186762306a36Sopenharmony_ci /* BIF reset workaround. Not sure if this is needed on 6xx */ 186862306a36Sopenharmony_ci tmp = SOFT_RESET_BIF; 186962306a36Sopenharmony_ci WREG32(SRBM_SOFT_RESET, tmp); 187062306a36Sopenharmony_ci mdelay(1); 187162306a36Sopenharmony_ci WREG32(SRBM_SOFT_RESET, 0); 187262306a36Sopenharmony_ci 187362306a36Sopenharmony_ci /* wait for asic to come out of reset */ 187462306a36Sopenharmony_ci for (i = 0; i < rdev->usec_timeout; i++) { 187562306a36Sopenharmony_ci if (RREG32(CONFIG_MEMSIZE) != 0xffffffff) 187662306a36Sopenharmony_ci break; 187762306a36Sopenharmony_ci udelay(1); 187862306a36Sopenharmony_ci } 187962306a36Sopenharmony_ci} 188062306a36Sopenharmony_ci 188162306a36Sopenharmony_ciint r600_asic_reset(struct radeon_device *rdev, bool hard) 188262306a36Sopenharmony_ci{ 188362306a36Sopenharmony_ci u32 reset_mask; 188462306a36Sopenharmony_ci 188562306a36Sopenharmony_ci if (hard) { 188662306a36Sopenharmony_ci r600_gpu_pci_config_reset(rdev); 188762306a36Sopenharmony_ci return 0; 188862306a36Sopenharmony_ci } 188962306a36Sopenharmony_ci 189062306a36Sopenharmony_ci reset_mask = r600_gpu_check_soft_reset(rdev); 189162306a36Sopenharmony_ci 189262306a36Sopenharmony_ci if (reset_mask) 189362306a36Sopenharmony_ci r600_set_bios_scratch_engine_hung(rdev, true); 189462306a36Sopenharmony_ci 189562306a36Sopenharmony_ci /* try soft reset */ 189662306a36Sopenharmony_ci r600_gpu_soft_reset(rdev, reset_mask); 189762306a36Sopenharmony_ci 189862306a36Sopenharmony_ci reset_mask = r600_gpu_check_soft_reset(rdev); 189962306a36Sopenharmony_ci 190062306a36Sopenharmony_ci /* try pci config reset */ 190162306a36Sopenharmony_ci if (reset_mask && radeon_hard_reset) 190262306a36Sopenharmony_ci r600_gpu_pci_config_reset(rdev); 190362306a36Sopenharmony_ci 190462306a36Sopenharmony_ci reset_mask = r600_gpu_check_soft_reset(rdev); 190562306a36Sopenharmony_ci 190662306a36Sopenharmony_ci if (!reset_mask) 190762306a36Sopenharmony_ci r600_set_bios_scratch_engine_hung(rdev, false); 190862306a36Sopenharmony_ci 190962306a36Sopenharmony_ci return 0; 191062306a36Sopenharmony_ci} 191162306a36Sopenharmony_ci 191262306a36Sopenharmony_ci/** 191362306a36Sopenharmony_ci * r600_gfx_is_lockup - Check if the GFX engine is locked up 191462306a36Sopenharmony_ci * 191562306a36Sopenharmony_ci * @rdev: radeon_device pointer 191662306a36Sopenharmony_ci * @ring: radeon_ring structure holding ring information 191762306a36Sopenharmony_ci * 191862306a36Sopenharmony_ci * Check if the GFX engine is locked up. 191962306a36Sopenharmony_ci * Returns true if the engine appears to be locked up, false if not. 192062306a36Sopenharmony_ci */ 192162306a36Sopenharmony_cibool r600_gfx_is_lockup(struct radeon_device *rdev, struct radeon_ring *ring) 192262306a36Sopenharmony_ci{ 192362306a36Sopenharmony_ci u32 reset_mask = r600_gpu_check_soft_reset(rdev); 192462306a36Sopenharmony_ci 192562306a36Sopenharmony_ci if (!(reset_mask & (RADEON_RESET_GFX | 192662306a36Sopenharmony_ci RADEON_RESET_COMPUTE | 192762306a36Sopenharmony_ci RADEON_RESET_CP))) { 192862306a36Sopenharmony_ci radeon_ring_lockup_update(rdev, ring); 192962306a36Sopenharmony_ci return false; 193062306a36Sopenharmony_ci } 193162306a36Sopenharmony_ci return radeon_ring_test_lockup(rdev, ring); 193262306a36Sopenharmony_ci} 193362306a36Sopenharmony_ci 193462306a36Sopenharmony_ciu32 r6xx_remap_render_backend(struct radeon_device *rdev, 193562306a36Sopenharmony_ci u32 tiling_pipe_num, 193662306a36Sopenharmony_ci u32 max_rb_num, 193762306a36Sopenharmony_ci u32 total_max_rb_num, 193862306a36Sopenharmony_ci u32 disabled_rb_mask) 193962306a36Sopenharmony_ci{ 194062306a36Sopenharmony_ci u32 rendering_pipe_num, rb_num_width, req_rb_num; 194162306a36Sopenharmony_ci u32 pipe_rb_ratio, pipe_rb_remain, tmp; 194262306a36Sopenharmony_ci u32 data = 0, mask = 1 << (max_rb_num - 1); 194362306a36Sopenharmony_ci unsigned i, j; 194462306a36Sopenharmony_ci 194562306a36Sopenharmony_ci /* mask out the RBs that don't exist on that asic */ 194662306a36Sopenharmony_ci tmp = disabled_rb_mask | ((0xff << max_rb_num) & 0xff); 194762306a36Sopenharmony_ci /* make sure at least one RB is available */ 194862306a36Sopenharmony_ci if ((tmp & 0xff) != 0xff) 194962306a36Sopenharmony_ci disabled_rb_mask = tmp; 195062306a36Sopenharmony_ci 195162306a36Sopenharmony_ci rendering_pipe_num = 1 << tiling_pipe_num; 195262306a36Sopenharmony_ci req_rb_num = total_max_rb_num - r600_count_pipe_bits(disabled_rb_mask); 195362306a36Sopenharmony_ci BUG_ON(rendering_pipe_num < req_rb_num); 195462306a36Sopenharmony_ci 195562306a36Sopenharmony_ci pipe_rb_ratio = rendering_pipe_num / req_rb_num; 195662306a36Sopenharmony_ci pipe_rb_remain = rendering_pipe_num - pipe_rb_ratio * req_rb_num; 195762306a36Sopenharmony_ci 195862306a36Sopenharmony_ci if (rdev->family <= CHIP_RV740) { 195962306a36Sopenharmony_ci /* r6xx/r7xx */ 196062306a36Sopenharmony_ci rb_num_width = 2; 196162306a36Sopenharmony_ci } else { 196262306a36Sopenharmony_ci /* eg+ */ 196362306a36Sopenharmony_ci rb_num_width = 4; 196462306a36Sopenharmony_ci } 196562306a36Sopenharmony_ci 196662306a36Sopenharmony_ci for (i = 0; i < max_rb_num; i++) { 196762306a36Sopenharmony_ci if (!(mask & disabled_rb_mask)) { 196862306a36Sopenharmony_ci for (j = 0; j < pipe_rb_ratio; j++) { 196962306a36Sopenharmony_ci data <<= rb_num_width; 197062306a36Sopenharmony_ci data |= max_rb_num - i - 1; 197162306a36Sopenharmony_ci } 197262306a36Sopenharmony_ci if (pipe_rb_remain) { 197362306a36Sopenharmony_ci data <<= rb_num_width; 197462306a36Sopenharmony_ci data |= max_rb_num - i - 1; 197562306a36Sopenharmony_ci pipe_rb_remain--; 197662306a36Sopenharmony_ci } 197762306a36Sopenharmony_ci } 197862306a36Sopenharmony_ci mask >>= 1; 197962306a36Sopenharmony_ci } 198062306a36Sopenharmony_ci 198162306a36Sopenharmony_ci return data; 198262306a36Sopenharmony_ci} 198362306a36Sopenharmony_ci 198462306a36Sopenharmony_ciint r600_count_pipe_bits(uint32_t val) 198562306a36Sopenharmony_ci{ 198662306a36Sopenharmony_ci return hweight32(val); 198762306a36Sopenharmony_ci} 198862306a36Sopenharmony_ci 198962306a36Sopenharmony_cistatic void r600_gpu_init(struct radeon_device *rdev) 199062306a36Sopenharmony_ci{ 199162306a36Sopenharmony_ci u32 tiling_config; 199262306a36Sopenharmony_ci u32 ramcfg; 199362306a36Sopenharmony_ci u32 cc_gc_shader_pipe_config; 199462306a36Sopenharmony_ci u32 tmp; 199562306a36Sopenharmony_ci int i, j; 199662306a36Sopenharmony_ci u32 sq_config; 199762306a36Sopenharmony_ci u32 sq_gpr_resource_mgmt_1 = 0; 199862306a36Sopenharmony_ci u32 sq_gpr_resource_mgmt_2 = 0; 199962306a36Sopenharmony_ci u32 sq_thread_resource_mgmt = 0; 200062306a36Sopenharmony_ci u32 sq_stack_resource_mgmt_1 = 0; 200162306a36Sopenharmony_ci u32 sq_stack_resource_mgmt_2 = 0; 200262306a36Sopenharmony_ci u32 disabled_rb_mask; 200362306a36Sopenharmony_ci 200462306a36Sopenharmony_ci rdev->config.r600.tiling_group_size = 256; 200562306a36Sopenharmony_ci switch (rdev->family) { 200662306a36Sopenharmony_ci case CHIP_R600: 200762306a36Sopenharmony_ci rdev->config.r600.max_pipes = 4; 200862306a36Sopenharmony_ci rdev->config.r600.max_tile_pipes = 8; 200962306a36Sopenharmony_ci rdev->config.r600.max_simds = 4; 201062306a36Sopenharmony_ci rdev->config.r600.max_backends = 4; 201162306a36Sopenharmony_ci rdev->config.r600.max_gprs = 256; 201262306a36Sopenharmony_ci rdev->config.r600.max_threads = 192; 201362306a36Sopenharmony_ci rdev->config.r600.max_stack_entries = 256; 201462306a36Sopenharmony_ci rdev->config.r600.max_hw_contexts = 8; 201562306a36Sopenharmony_ci rdev->config.r600.max_gs_threads = 16; 201662306a36Sopenharmony_ci rdev->config.r600.sx_max_export_size = 128; 201762306a36Sopenharmony_ci rdev->config.r600.sx_max_export_pos_size = 16; 201862306a36Sopenharmony_ci rdev->config.r600.sx_max_export_smx_size = 128; 201962306a36Sopenharmony_ci rdev->config.r600.sq_num_cf_insts = 2; 202062306a36Sopenharmony_ci break; 202162306a36Sopenharmony_ci case CHIP_RV630: 202262306a36Sopenharmony_ci case CHIP_RV635: 202362306a36Sopenharmony_ci rdev->config.r600.max_pipes = 2; 202462306a36Sopenharmony_ci rdev->config.r600.max_tile_pipes = 2; 202562306a36Sopenharmony_ci rdev->config.r600.max_simds = 3; 202662306a36Sopenharmony_ci rdev->config.r600.max_backends = 1; 202762306a36Sopenharmony_ci rdev->config.r600.max_gprs = 128; 202862306a36Sopenharmony_ci rdev->config.r600.max_threads = 192; 202962306a36Sopenharmony_ci rdev->config.r600.max_stack_entries = 128; 203062306a36Sopenharmony_ci rdev->config.r600.max_hw_contexts = 8; 203162306a36Sopenharmony_ci rdev->config.r600.max_gs_threads = 4; 203262306a36Sopenharmony_ci rdev->config.r600.sx_max_export_size = 128; 203362306a36Sopenharmony_ci rdev->config.r600.sx_max_export_pos_size = 16; 203462306a36Sopenharmony_ci rdev->config.r600.sx_max_export_smx_size = 128; 203562306a36Sopenharmony_ci rdev->config.r600.sq_num_cf_insts = 2; 203662306a36Sopenharmony_ci break; 203762306a36Sopenharmony_ci case CHIP_RV610: 203862306a36Sopenharmony_ci case CHIP_RV620: 203962306a36Sopenharmony_ci case CHIP_RS780: 204062306a36Sopenharmony_ci case CHIP_RS880: 204162306a36Sopenharmony_ci rdev->config.r600.max_pipes = 1; 204262306a36Sopenharmony_ci rdev->config.r600.max_tile_pipes = 1; 204362306a36Sopenharmony_ci rdev->config.r600.max_simds = 2; 204462306a36Sopenharmony_ci rdev->config.r600.max_backends = 1; 204562306a36Sopenharmony_ci rdev->config.r600.max_gprs = 128; 204662306a36Sopenharmony_ci rdev->config.r600.max_threads = 192; 204762306a36Sopenharmony_ci rdev->config.r600.max_stack_entries = 128; 204862306a36Sopenharmony_ci rdev->config.r600.max_hw_contexts = 4; 204962306a36Sopenharmony_ci rdev->config.r600.max_gs_threads = 4; 205062306a36Sopenharmony_ci rdev->config.r600.sx_max_export_size = 128; 205162306a36Sopenharmony_ci rdev->config.r600.sx_max_export_pos_size = 16; 205262306a36Sopenharmony_ci rdev->config.r600.sx_max_export_smx_size = 128; 205362306a36Sopenharmony_ci rdev->config.r600.sq_num_cf_insts = 1; 205462306a36Sopenharmony_ci break; 205562306a36Sopenharmony_ci case CHIP_RV670: 205662306a36Sopenharmony_ci rdev->config.r600.max_pipes = 4; 205762306a36Sopenharmony_ci rdev->config.r600.max_tile_pipes = 4; 205862306a36Sopenharmony_ci rdev->config.r600.max_simds = 4; 205962306a36Sopenharmony_ci rdev->config.r600.max_backends = 4; 206062306a36Sopenharmony_ci rdev->config.r600.max_gprs = 192; 206162306a36Sopenharmony_ci rdev->config.r600.max_threads = 192; 206262306a36Sopenharmony_ci rdev->config.r600.max_stack_entries = 256; 206362306a36Sopenharmony_ci rdev->config.r600.max_hw_contexts = 8; 206462306a36Sopenharmony_ci rdev->config.r600.max_gs_threads = 16; 206562306a36Sopenharmony_ci rdev->config.r600.sx_max_export_size = 128; 206662306a36Sopenharmony_ci rdev->config.r600.sx_max_export_pos_size = 16; 206762306a36Sopenharmony_ci rdev->config.r600.sx_max_export_smx_size = 128; 206862306a36Sopenharmony_ci rdev->config.r600.sq_num_cf_insts = 2; 206962306a36Sopenharmony_ci break; 207062306a36Sopenharmony_ci default: 207162306a36Sopenharmony_ci break; 207262306a36Sopenharmony_ci } 207362306a36Sopenharmony_ci 207462306a36Sopenharmony_ci /* Initialize HDP */ 207562306a36Sopenharmony_ci for (i = 0, j = 0; i < 32; i++, j += 0x18) { 207662306a36Sopenharmony_ci WREG32((0x2c14 + j), 0x00000000); 207762306a36Sopenharmony_ci WREG32((0x2c18 + j), 0x00000000); 207862306a36Sopenharmony_ci WREG32((0x2c1c + j), 0x00000000); 207962306a36Sopenharmony_ci WREG32((0x2c20 + j), 0x00000000); 208062306a36Sopenharmony_ci WREG32((0x2c24 + j), 0x00000000); 208162306a36Sopenharmony_ci } 208262306a36Sopenharmony_ci 208362306a36Sopenharmony_ci WREG32(GRBM_CNTL, GRBM_READ_TIMEOUT(0xff)); 208462306a36Sopenharmony_ci 208562306a36Sopenharmony_ci /* Setup tiling */ 208662306a36Sopenharmony_ci tiling_config = 0; 208762306a36Sopenharmony_ci ramcfg = RREG32(RAMCFG); 208862306a36Sopenharmony_ci switch (rdev->config.r600.max_tile_pipes) { 208962306a36Sopenharmony_ci case 1: 209062306a36Sopenharmony_ci tiling_config |= PIPE_TILING(0); 209162306a36Sopenharmony_ci break; 209262306a36Sopenharmony_ci case 2: 209362306a36Sopenharmony_ci tiling_config |= PIPE_TILING(1); 209462306a36Sopenharmony_ci break; 209562306a36Sopenharmony_ci case 4: 209662306a36Sopenharmony_ci tiling_config |= PIPE_TILING(2); 209762306a36Sopenharmony_ci break; 209862306a36Sopenharmony_ci case 8: 209962306a36Sopenharmony_ci tiling_config |= PIPE_TILING(3); 210062306a36Sopenharmony_ci break; 210162306a36Sopenharmony_ci default: 210262306a36Sopenharmony_ci break; 210362306a36Sopenharmony_ci } 210462306a36Sopenharmony_ci rdev->config.r600.tiling_npipes = rdev->config.r600.max_tile_pipes; 210562306a36Sopenharmony_ci rdev->config.r600.tiling_nbanks = 4 << ((ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT); 210662306a36Sopenharmony_ci tiling_config |= BANK_TILING((ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT); 210762306a36Sopenharmony_ci tiling_config |= GROUP_SIZE((ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT); 210862306a36Sopenharmony_ci 210962306a36Sopenharmony_ci tmp = (ramcfg & NOOFROWS_MASK) >> NOOFROWS_SHIFT; 211062306a36Sopenharmony_ci if (tmp > 3) { 211162306a36Sopenharmony_ci tiling_config |= ROW_TILING(3); 211262306a36Sopenharmony_ci tiling_config |= SAMPLE_SPLIT(3); 211362306a36Sopenharmony_ci } else { 211462306a36Sopenharmony_ci tiling_config |= ROW_TILING(tmp); 211562306a36Sopenharmony_ci tiling_config |= SAMPLE_SPLIT(tmp); 211662306a36Sopenharmony_ci } 211762306a36Sopenharmony_ci tiling_config |= BANK_SWAPS(1); 211862306a36Sopenharmony_ci 211962306a36Sopenharmony_ci cc_gc_shader_pipe_config = RREG32(CC_GC_SHADER_PIPE_CONFIG) & 0x00ffff00; 212062306a36Sopenharmony_ci tmp = rdev->config.r600.max_simds - 212162306a36Sopenharmony_ci r600_count_pipe_bits((cc_gc_shader_pipe_config >> 16) & R6XX_MAX_SIMDS_MASK); 212262306a36Sopenharmony_ci rdev->config.r600.active_simds = tmp; 212362306a36Sopenharmony_ci 212462306a36Sopenharmony_ci disabled_rb_mask = (RREG32(CC_RB_BACKEND_DISABLE) >> 16) & R6XX_MAX_BACKENDS_MASK; 212562306a36Sopenharmony_ci tmp = 0; 212662306a36Sopenharmony_ci for (i = 0; i < rdev->config.r600.max_backends; i++) 212762306a36Sopenharmony_ci tmp |= (1 << i); 212862306a36Sopenharmony_ci /* if all the backends are disabled, fix it up here */ 212962306a36Sopenharmony_ci if ((disabled_rb_mask & tmp) == tmp) { 213062306a36Sopenharmony_ci for (i = 0; i < rdev->config.r600.max_backends; i++) 213162306a36Sopenharmony_ci disabled_rb_mask &= ~(1 << i); 213262306a36Sopenharmony_ci } 213362306a36Sopenharmony_ci tmp = (tiling_config & PIPE_TILING__MASK) >> PIPE_TILING__SHIFT; 213462306a36Sopenharmony_ci tmp = r6xx_remap_render_backend(rdev, tmp, rdev->config.r600.max_backends, 213562306a36Sopenharmony_ci R6XX_MAX_BACKENDS, disabled_rb_mask); 213662306a36Sopenharmony_ci tiling_config |= tmp << 16; 213762306a36Sopenharmony_ci rdev->config.r600.backend_map = tmp; 213862306a36Sopenharmony_ci 213962306a36Sopenharmony_ci rdev->config.r600.tile_config = tiling_config; 214062306a36Sopenharmony_ci WREG32(GB_TILING_CONFIG, tiling_config); 214162306a36Sopenharmony_ci WREG32(DCP_TILING_CONFIG, tiling_config & 0xffff); 214262306a36Sopenharmony_ci WREG32(HDP_TILING_CONFIG, tiling_config & 0xffff); 214362306a36Sopenharmony_ci WREG32(DMA_TILING_CONFIG, tiling_config & 0xffff); 214462306a36Sopenharmony_ci 214562306a36Sopenharmony_ci tmp = R6XX_MAX_PIPES - r600_count_pipe_bits((cc_gc_shader_pipe_config & INACTIVE_QD_PIPES_MASK) >> 8); 214662306a36Sopenharmony_ci WREG32(VGT_OUT_DEALLOC_CNTL, (tmp * 4) & DEALLOC_DIST_MASK); 214762306a36Sopenharmony_ci WREG32(VGT_VERTEX_REUSE_BLOCK_CNTL, ((tmp * 4) - 2) & VTX_REUSE_DEPTH_MASK); 214862306a36Sopenharmony_ci 214962306a36Sopenharmony_ci /* Setup some CP states */ 215062306a36Sopenharmony_ci WREG32(CP_QUEUE_THRESHOLDS, (ROQ_IB1_START(0x16) | ROQ_IB2_START(0x2b))); 215162306a36Sopenharmony_ci WREG32(CP_MEQ_THRESHOLDS, (MEQ_END(0x40) | ROQ_END(0x40))); 215262306a36Sopenharmony_ci 215362306a36Sopenharmony_ci WREG32(TA_CNTL_AUX, (DISABLE_CUBE_ANISO | SYNC_GRADIENT | 215462306a36Sopenharmony_ci SYNC_WALKER | SYNC_ALIGNER)); 215562306a36Sopenharmony_ci /* Setup various GPU states */ 215662306a36Sopenharmony_ci if (rdev->family == CHIP_RV670) 215762306a36Sopenharmony_ci WREG32(ARB_GDEC_RD_CNTL, 0x00000021); 215862306a36Sopenharmony_ci 215962306a36Sopenharmony_ci tmp = RREG32(SX_DEBUG_1); 216062306a36Sopenharmony_ci tmp |= SMX_EVENT_RELEASE; 216162306a36Sopenharmony_ci if ((rdev->family > CHIP_R600)) 216262306a36Sopenharmony_ci tmp |= ENABLE_NEW_SMX_ADDRESS; 216362306a36Sopenharmony_ci WREG32(SX_DEBUG_1, tmp); 216462306a36Sopenharmony_ci 216562306a36Sopenharmony_ci if (((rdev->family) == CHIP_R600) || 216662306a36Sopenharmony_ci ((rdev->family) == CHIP_RV630) || 216762306a36Sopenharmony_ci ((rdev->family) == CHIP_RV610) || 216862306a36Sopenharmony_ci ((rdev->family) == CHIP_RV620) || 216962306a36Sopenharmony_ci ((rdev->family) == CHIP_RS780) || 217062306a36Sopenharmony_ci ((rdev->family) == CHIP_RS880)) { 217162306a36Sopenharmony_ci WREG32(DB_DEBUG, PREZ_MUST_WAIT_FOR_POSTZ_DONE); 217262306a36Sopenharmony_ci } else { 217362306a36Sopenharmony_ci WREG32(DB_DEBUG, 0); 217462306a36Sopenharmony_ci } 217562306a36Sopenharmony_ci WREG32(DB_WATERMARKS, (DEPTH_FREE(4) | DEPTH_CACHELINE_FREE(16) | 217662306a36Sopenharmony_ci DEPTH_FLUSH(16) | DEPTH_PENDING_FREE(4))); 217762306a36Sopenharmony_ci 217862306a36Sopenharmony_ci WREG32(PA_SC_MULTI_CHIP_CNTL, 0); 217962306a36Sopenharmony_ci WREG32(VGT_NUM_INSTANCES, 0); 218062306a36Sopenharmony_ci 218162306a36Sopenharmony_ci WREG32(SPI_CONFIG_CNTL, GPR_WRITE_PRIORITY(0)); 218262306a36Sopenharmony_ci WREG32(SPI_CONFIG_CNTL_1, VTX_DONE_DELAY(0)); 218362306a36Sopenharmony_ci 218462306a36Sopenharmony_ci tmp = RREG32(SQ_MS_FIFO_SIZES); 218562306a36Sopenharmony_ci if (((rdev->family) == CHIP_RV610) || 218662306a36Sopenharmony_ci ((rdev->family) == CHIP_RV620) || 218762306a36Sopenharmony_ci ((rdev->family) == CHIP_RS780) || 218862306a36Sopenharmony_ci ((rdev->family) == CHIP_RS880)) { 218962306a36Sopenharmony_ci tmp = (CACHE_FIFO_SIZE(0xa) | 219062306a36Sopenharmony_ci FETCH_FIFO_HIWATER(0xa) | 219162306a36Sopenharmony_ci DONE_FIFO_HIWATER(0xe0) | 219262306a36Sopenharmony_ci ALU_UPDATE_FIFO_HIWATER(0x8)); 219362306a36Sopenharmony_ci } else if (((rdev->family) == CHIP_R600) || 219462306a36Sopenharmony_ci ((rdev->family) == CHIP_RV630)) { 219562306a36Sopenharmony_ci tmp &= ~DONE_FIFO_HIWATER(0xff); 219662306a36Sopenharmony_ci tmp |= DONE_FIFO_HIWATER(0x4); 219762306a36Sopenharmony_ci } 219862306a36Sopenharmony_ci WREG32(SQ_MS_FIFO_SIZES, tmp); 219962306a36Sopenharmony_ci 220062306a36Sopenharmony_ci /* SQ_CONFIG, SQ_GPR_RESOURCE_MGMT, SQ_THREAD_RESOURCE_MGMT, SQ_STACK_RESOURCE_MGMT 220162306a36Sopenharmony_ci * should be adjusted as needed by the 2D/3D drivers. This just sets default values 220262306a36Sopenharmony_ci */ 220362306a36Sopenharmony_ci sq_config = RREG32(SQ_CONFIG); 220462306a36Sopenharmony_ci sq_config &= ~(PS_PRIO(3) | 220562306a36Sopenharmony_ci VS_PRIO(3) | 220662306a36Sopenharmony_ci GS_PRIO(3) | 220762306a36Sopenharmony_ci ES_PRIO(3)); 220862306a36Sopenharmony_ci sq_config |= (DX9_CONSTS | 220962306a36Sopenharmony_ci VC_ENABLE | 221062306a36Sopenharmony_ci PS_PRIO(0) | 221162306a36Sopenharmony_ci VS_PRIO(1) | 221262306a36Sopenharmony_ci GS_PRIO(2) | 221362306a36Sopenharmony_ci ES_PRIO(3)); 221462306a36Sopenharmony_ci 221562306a36Sopenharmony_ci if ((rdev->family) == CHIP_R600) { 221662306a36Sopenharmony_ci sq_gpr_resource_mgmt_1 = (NUM_PS_GPRS(124) | 221762306a36Sopenharmony_ci NUM_VS_GPRS(124) | 221862306a36Sopenharmony_ci NUM_CLAUSE_TEMP_GPRS(4)); 221962306a36Sopenharmony_ci sq_gpr_resource_mgmt_2 = (NUM_GS_GPRS(0) | 222062306a36Sopenharmony_ci NUM_ES_GPRS(0)); 222162306a36Sopenharmony_ci sq_thread_resource_mgmt = (NUM_PS_THREADS(136) | 222262306a36Sopenharmony_ci NUM_VS_THREADS(48) | 222362306a36Sopenharmony_ci NUM_GS_THREADS(4) | 222462306a36Sopenharmony_ci NUM_ES_THREADS(4)); 222562306a36Sopenharmony_ci sq_stack_resource_mgmt_1 = (NUM_PS_STACK_ENTRIES(128) | 222662306a36Sopenharmony_ci NUM_VS_STACK_ENTRIES(128)); 222762306a36Sopenharmony_ci sq_stack_resource_mgmt_2 = (NUM_GS_STACK_ENTRIES(0) | 222862306a36Sopenharmony_ci NUM_ES_STACK_ENTRIES(0)); 222962306a36Sopenharmony_ci } else if (((rdev->family) == CHIP_RV610) || 223062306a36Sopenharmony_ci ((rdev->family) == CHIP_RV620) || 223162306a36Sopenharmony_ci ((rdev->family) == CHIP_RS780) || 223262306a36Sopenharmony_ci ((rdev->family) == CHIP_RS880)) { 223362306a36Sopenharmony_ci /* no vertex cache */ 223462306a36Sopenharmony_ci sq_config &= ~VC_ENABLE; 223562306a36Sopenharmony_ci 223662306a36Sopenharmony_ci sq_gpr_resource_mgmt_1 = (NUM_PS_GPRS(44) | 223762306a36Sopenharmony_ci NUM_VS_GPRS(44) | 223862306a36Sopenharmony_ci NUM_CLAUSE_TEMP_GPRS(2)); 223962306a36Sopenharmony_ci sq_gpr_resource_mgmt_2 = (NUM_GS_GPRS(17) | 224062306a36Sopenharmony_ci NUM_ES_GPRS(17)); 224162306a36Sopenharmony_ci sq_thread_resource_mgmt = (NUM_PS_THREADS(79) | 224262306a36Sopenharmony_ci NUM_VS_THREADS(78) | 224362306a36Sopenharmony_ci NUM_GS_THREADS(4) | 224462306a36Sopenharmony_ci NUM_ES_THREADS(31)); 224562306a36Sopenharmony_ci sq_stack_resource_mgmt_1 = (NUM_PS_STACK_ENTRIES(40) | 224662306a36Sopenharmony_ci NUM_VS_STACK_ENTRIES(40)); 224762306a36Sopenharmony_ci sq_stack_resource_mgmt_2 = (NUM_GS_STACK_ENTRIES(32) | 224862306a36Sopenharmony_ci NUM_ES_STACK_ENTRIES(16)); 224962306a36Sopenharmony_ci } else if (((rdev->family) == CHIP_RV630) || 225062306a36Sopenharmony_ci ((rdev->family) == CHIP_RV635)) { 225162306a36Sopenharmony_ci sq_gpr_resource_mgmt_1 = (NUM_PS_GPRS(44) | 225262306a36Sopenharmony_ci NUM_VS_GPRS(44) | 225362306a36Sopenharmony_ci NUM_CLAUSE_TEMP_GPRS(2)); 225462306a36Sopenharmony_ci sq_gpr_resource_mgmt_2 = (NUM_GS_GPRS(18) | 225562306a36Sopenharmony_ci NUM_ES_GPRS(18)); 225662306a36Sopenharmony_ci sq_thread_resource_mgmt = (NUM_PS_THREADS(79) | 225762306a36Sopenharmony_ci NUM_VS_THREADS(78) | 225862306a36Sopenharmony_ci NUM_GS_THREADS(4) | 225962306a36Sopenharmony_ci NUM_ES_THREADS(31)); 226062306a36Sopenharmony_ci sq_stack_resource_mgmt_1 = (NUM_PS_STACK_ENTRIES(40) | 226162306a36Sopenharmony_ci NUM_VS_STACK_ENTRIES(40)); 226262306a36Sopenharmony_ci sq_stack_resource_mgmt_2 = (NUM_GS_STACK_ENTRIES(32) | 226362306a36Sopenharmony_ci NUM_ES_STACK_ENTRIES(16)); 226462306a36Sopenharmony_ci } else if ((rdev->family) == CHIP_RV670) { 226562306a36Sopenharmony_ci sq_gpr_resource_mgmt_1 = (NUM_PS_GPRS(44) | 226662306a36Sopenharmony_ci NUM_VS_GPRS(44) | 226762306a36Sopenharmony_ci NUM_CLAUSE_TEMP_GPRS(2)); 226862306a36Sopenharmony_ci sq_gpr_resource_mgmt_2 = (NUM_GS_GPRS(17) | 226962306a36Sopenharmony_ci NUM_ES_GPRS(17)); 227062306a36Sopenharmony_ci sq_thread_resource_mgmt = (NUM_PS_THREADS(79) | 227162306a36Sopenharmony_ci NUM_VS_THREADS(78) | 227262306a36Sopenharmony_ci NUM_GS_THREADS(4) | 227362306a36Sopenharmony_ci NUM_ES_THREADS(31)); 227462306a36Sopenharmony_ci sq_stack_resource_mgmt_1 = (NUM_PS_STACK_ENTRIES(64) | 227562306a36Sopenharmony_ci NUM_VS_STACK_ENTRIES(64)); 227662306a36Sopenharmony_ci sq_stack_resource_mgmt_2 = (NUM_GS_STACK_ENTRIES(64) | 227762306a36Sopenharmony_ci NUM_ES_STACK_ENTRIES(64)); 227862306a36Sopenharmony_ci } 227962306a36Sopenharmony_ci 228062306a36Sopenharmony_ci WREG32(SQ_CONFIG, sq_config); 228162306a36Sopenharmony_ci WREG32(SQ_GPR_RESOURCE_MGMT_1, sq_gpr_resource_mgmt_1); 228262306a36Sopenharmony_ci WREG32(SQ_GPR_RESOURCE_MGMT_2, sq_gpr_resource_mgmt_2); 228362306a36Sopenharmony_ci WREG32(SQ_THREAD_RESOURCE_MGMT, sq_thread_resource_mgmt); 228462306a36Sopenharmony_ci WREG32(SQ_STACK_RESOURCE_MGMT_1, sq_stack_resource_mgmt_1); 228562306a36Sopenharmony_ci WREG32(SQ_STACK_RESOURCE_MGMT_2, sq_stack_resource_mgmt_2); 228662306a36Sopenharmony_ci 228762306a36Sopenharmony_ci if (((rdev->family) == CHIP_RV610) || 228862306a36Sopenharmony_ci ((rdev->family) == CHIP_RV620) || 228962306a36Sopenharmony_ci ((rdev->family) == CHIP_RS780) || 229062306a36Sopenharmony_ci ((rdev->family) == CHIP_RS880)) { 229162306a36Sopenharmony_ci WREG32(VGT_CACHE_INVALIDATION, CACHE_INVALIDATION(TC_ONLY)); 229262306a36Sopenharmony_ci } else { 229362306a36Sopenharmony_ci WREG32(VGT_CACHE_INVALIDATION, CACHE_INVALIDATION(VC_AND_TC)); 229462306a36Sopenharmony_ci } 229562306a36Sopenharmony_ci 229662306a36Sopenharmony_ci /* More default values. 2D/3D driver should adjust as needed */ 229762306a36Sopenharmony_ci WREG32(PA_SC_AA_SAMPLE_LOCS_2S, (S0_X(0xc) | S0_Y(0x4) | 229862306a36Sopenharmony_ci S1_X(0x4) | S1_Y(0xc))); 229962306a36Sopenharmony_ci WREG32(PA_SC_AA_SAMPLE_LOCS_4S, (S0_X(0xe) | S0_Y(0xe) | 230062306a36Sopenharmony_ci S1_X(0x2) | S1_Y(0x2) | 230162306a36Sopenharmony_ci S2_X(0xa) | S2_Y(0x6) | 230262306a36Sopenharmony_ci S3_X(0x6) | S3_Y(0xa))); 230362306a36Sopenharmony_ci WREG32(PA_SC_AA_SAMPLE_LOCS_8S_WD0, (S0_X(0xe) | S0_Y(0xb) | 230462306a36Sopenharmony_ci S1_X(0x4) | S1_Y(0xc) | 230562306a36Sopenharmony_ci S2_X(0x1) | S2_Y(0x6) | 230662306a36Sopenharmony_ci S3_X(0xa) | S3_Y(0xe))); 230762306a36Sopenharmony_ci WREG32(PA_SC_AA_SAMPLE_LOCS_8S_WD1, (S4_X(0x6) | S4_Y(0x1) | 230862306a36Sopenharmony_ci S5_X(0x0) | S5_Y(0x0) | 230962306a36Sopenharmony_ci S6_X(0xb) | S6_Y(0x4) | 231062306a36Sopenharmony_ci S7_X(0x7) | S7_Y(0x8))); 231162306a36Sopenharmony_ci 231262306a36Sopenharmony_ci WREG32(VGT_STRMOUT_EN, 0); 231362306a36Sopenharmony_ci tmp = rdev->config.r600.max_pipes * 16; 231462306a36Sopenharmony_ci switch (rdev->family) { 231562306a36Sopenharmony_ci case CHIP_RV610: 231662306a36Sopenharmony_ci case CHIP_RV620: 231762306a36Sopenharmony_ci case CHIP_RS780: 231862306a36Sopenharmony_ci case CHIP_RS880: 231962306a36Sopenharmony_ci tmp += 32; 232062306a36Sopenharmony_ci break; 232162306a36Sopenharmony_ci case CHIP_RV670: 232262306a36Sopenharmony_ci tmp += 128; 232362306a36Sopenharmony_ci break; 232462306a36Sopenharmony_ci default: 232562306a36Sopenharmony_ci break; 232662306a36Sopenharmony_ci } 232762306a36Sopenharmony_ci if (tmp > 256) { 232862306a36Sopenharmony_ci tmp = 256; 232962306a36Sopenharmony_ci } 233062306a36Sopenharmony_ci WREG32(VGT_ES_PER_GS, 128); 233162306a36Sopenharmony_ci WREG32(VGT_GS_PER_ES, tmp); 233262306a36Sopenharmony_ci WREG32(VGT_GS_PER_VS, 2); 233362306a36Sopenharmony_ci WREG32(VGT_GS_VERTEX_REUSE, 16); 233462306a36Sopenharmony_ci 233562306a36Sopenharmony_ci /* more default values. 2D/3D driver should adjust as needed */ 233662306a36Sopenharmony_ci WREG32(PA_SC_LINE_STIPPLE_STATE, 0); 233762306a36Sopenharmony_ci WREG32(VGT_STRMOUT_EN, 0); 233862306a36Sopenharmony_ci WREG32(SX_MISC, 0); 233962306a36Sopenharmony_ci WREG32(PA_SC_MODE_CNTL, 0); 234062306a36Sopenharmony_ci WREG32(PA_SC_AA_CONFIG, 0); 234162306a36Sopenharmony_ci WREG32(PA_SC_LINE_STIPPLE, 0); 234262306a36Sopenharmony_ci WREG32(SPI_INPUT_Z, 0); 234362306a36Sopenharmony_ci WREG32(SPI_PS_IN_CONTROL_0, NUM_INTERP(2)); 234462306a36Sopenharmony_ci WREG32(CB_COLOR7_FRAG, 0); 234562306a36Sopenharmony_ci 234662306a36Sopenharmony_ci /* Clear render buffer base addresses */ 234762306a36Sopenharmony_ci WREG32(CB_COLOR0_BASE, 0); 234862306a36Sopenharmony_ci WREG32(CB_COLOR1_BASE, 0); 234962306a36Sopenharmony_ci WREG32(CB_COLOR2_BASE, 0); 235062306a36Sopenharmony_ci WREG32(CB_COLOR3_BASE, 0); 235162306a36Sopenharmony_ci WREG32(CB_COLOR4_BASE, 0); 235262306a36Sopenharmony_ci WREG32(CB_COLOR5_BASE, 0); 235362306a36Sopenharmony_ci WREG32(CB_COLOR6_BASE, 0); 235462306a36Sopenharmony_ci WREG32(CB_COLOR7_BASE, 0); 235562306a36Sopenharmony_ci WREG32(CB_COLOR7_FRAG, 0); 235662306a36Sopenharmony_ci 235762306a36Sopenharmony_ci switch (rdev->family) { 235862306a36Sopenharmony_ci case CHIP_RV610: 235962306a36Sopenharmony_ci case CHIP_RV620: 236062306a36Sopenharmony_ci case CHIP_RS780: 236162306a36Sopenharmony_ci case CHIP_RS880: 236262306a36Sopenharmony_ci tmp = TC_L2_SIZE(8); 236362306a36Sopenharmony_ci break; 236462306a36Sopenharmony_ci case CHIP_RV630: 236562306a36Sopenharmony_ci case CHIP_RV635: 236662306a36Sopenharmony_ci tmp = TC_L2_SIZE(4); 236762306a36Sopenharmony_ci break; 236862306a36Sopenharmony_ci case CHIP_R600: 236962306a36Sopenharmony_ci tmp = TC_L2_SIZE(0) | L2_DISABLE_LATE_HIT; 237062306a36Sopenharmony_ci break; 237162306a36Sopenharmony_ci default: 237262306a36Sopenharmony_ci tmp = TC_L2_SIZE(0); 237362306a36Sopenharmony_ci break; 237462306a36Sopenharmony_ci } 237562306a36Sopenharmony_ci WREG32(TC_CNTL, tmp); 237662306a36Sopenharmony_ci 237762306a36Sopenharmony_ci tmp = RREG32(HDP_HOST_PATH_CNTL); 237862306a36Sopenharmony_ci WREG32(HDP_HOST_PATH_CNTL, tmp); 237962306a36Sopenharmony_ci 238062306a36Sopenharmony_ci tmp = RREG32(ARB_POP); 238162306a36Sopenharmony_ci tmp |= ENABLE_TC128; 238262306a36Sopenharmony_ci WREG32(ARB_POP, tmp); 238362306a36Sopenharmony_ci 238462306a36Sopenharmony_ci WREG32(PA_SC_MULTI_CHIP_CNTL, 0); 238562306a36Sopenharmony_ci WREG32(PA_CL_ENHANCE, (CLIP_VTX_REORDER_ENA | 238662306a36Sopenharmony_ci NUM_CLIP_SEQ(3))); 238762306a36Sopenharmony_ci WREG32(PA_SC_ENHANCE, FORCE_EOV_MAX_CLK_CNT(4095)); 238862306a36Sopenharmony_ci WREG32(VC_ENHANCE, 0); 238962306a36Sopenharmony_ci} 239062306a36Sopenharmony_ci 239162306a36Sopenharmony_ci 239262306a36Sopenharmony_ci/* 239362306a36Sopenharmony_ci * Indirect registers accessor 239462306a36Sopenharmony_ci */ 239562306a36Sopenharmony_ciu32 r600_pciep_rreg(struct radeon_device *rdev, u32 reg) 239662306a36Sopenharmony_ci{ 239762306a36Sopenharmony_ci unsigned long flags; 239862306a36Sopenharmony_ci u32 r; 239962306a36Sopenharmony_ci 240062306a36Sopenharmony_ci spin_lock_irqsave(&rdev->pciep_idx_lock, flags); 240162306a36Sopenharmony_ci WREG32(PCIE_PORT_INDEX, ((reg) & 0xff)); 240262306a36Sopenharmony_ci (void)RREG32(PCIE_PORT_INDEX); 240362306a36Sopenharmony_ci r = RREG32(PCIE_PORT_DATA); 240462306a36Sopenharmony_ci spin_unlock_irqrestore(&rdev->pciep_idx_lock, flags); 240562306a36Sopenharmony_ci return r; 240662306a36Sopenharmony_ci} 240762306a36Sopenharmony_ci 240862306a36Sopenharmony_civoid r600_pciep_wreg(struct radeon_device *rdev, u32 reg, u32 v) 240962306a36Sopenharmony_ci{ 241062306a36Sopenharmony_ci unsigned long flags; 241162306a36Sopenharmony_ci 241262306a36Sopenharmony_ci spin_lock_irqsave(&rdev->pciep_idx_lock, flags); 241362306a36Sopenharmony_ci WREG32(PCIE_PORT_INDEX, ((reg) & 0xff)); 241462306a36Sopenharmony_ci (void)RREG32(PCIE_PORT_INDEX); 241562306a36Sopenharmony_ci WREG32(PCIE_PORT_DATA, (v)); 241662306a36Sopenharmony_ci (void)RREG32(PCIE_PORT_DATA); 241762306a36Sopenharmony_ci spin_unlock_irqrestore(&rdev->pciep_idx_lock, flags); 241862306a36Sopenharmony_ci} 241962306a36Sopenharmony_ci 242062306a36Sopenharmony_ci/* 242162306a36Sopenharmony_ci * CP & Ring 242262306a36Sopenharmony_ci */ 242362306a36Sopenharmony_civoid r600_cp_stop(struct radeon_device *rdev) 242462306a36Sopenharmony_ci{ 242562306a36Sopenharmony_ci if (rdev->asic->copy.copy_ring_index == RADEON_RING_TYPE_GFX_INDEX) 242662306a36Sopenharmony_ci radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size); 242762306a36Sopenharmony_ci WREG32(R_0086D8_CP_ME_CNTL, S_0086D8_CP_ME_HALT(1)); 242862306a36Sopenharmony_ci WREG32(SCRATCH_UMSK, 0); 242962306a36Sopenharmony_ci rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false; 243062306a36Sopenharmony_ci} 243162306a36Sopenharmony_ci 243262306a36Sopenharmony_ciint r600_init_microcode(struct radeon_device *rdev) 243362306a36Sopenharmony_ci{ 243462306a36Sopenharmony_ci const char *chip_name; 243562306a36Sopenharmony_ci const char *rlc_chip_name; 243662306a36Sopenharmony_ci const char *smc_chip_name = "RV770"; 243762306a36Sopenharmony_ci size_t pfp_req_size, me_req_size, rlc_req_size, smc_req_size = 0; 243862306a36Sopenharmony_ci char fw_name[30]; 243962306a36Sopenharmony_ci int err; 244062306a36Sopenharmony_ci 244162306a36Sopenharmony_ci DRM_DEBUG("\n"); 244262306a36Sopenharmony_ci 244362306a36Sopenharmony_ci switch (rdev->family) { 244462306a36Sopenharmony_ci case CHIP_R600: 244562306a36Sopenharmony_ci chip_name = "R600"; 244662306a36Sopenharmony_ci rlc_chip_name = "R600"; 244762306a36Sopenharmony_ci break; 244862306a36Sopenharmony_ci case CHIP_RV610: 244962306a36Sopenharmony_ci chip_name = "RV610"; 245062306a36Sopenharmony_ci rlc_chip_name = "R600"; 245162306a36Sopenharmony_ci break; 245262306a36Sopenharmony_ci case CHIP_RV630: 245362306a36Sopenharmony_ci chip_name = "RV630"; 245462306a36Sopenharmony_ci rlc_chip_name = "R600"; 245562306a36Sopenharmony_ci break; 245662306a36Sopenharmony_ci case CHIP_RV620: 245762306a36Sopenharmony_ci chip_name = "RV620"; 245862306a36Sopenharmony_ci rlc_chip_name = "R600"; 245962306a36Sopenharmony_ci break; 246062306a36Sopenharmony_ci case CHIP_RV635: 246162306a36Sopenharmony_ci chip_name = "RV635"; 246262306a36Sopenharmony_ci rlc_chip_name = "R600"; 246362306a36Sopenharmony_ci break; 246462306a36Sopenharmony_ci case CHIP_RV670: 246562306a36Sopenharmony_ci chip_name = "RV670"; 246662306a36Sopenharmony_ci rlc_chip_name = "R600"; 246762306a36Sopenharmony_ci break; 246862306a36Sopenharmony_ci case CHIP_RS780: 246962306a36Sopenharmony_ci case CHIP_RS880: 247062306a36Sopenharmony_ci chip_name = "RS780"; 247162306a36Sopenharmony_ci rlc_chip_name = "R600"; 247262306a36Sopenharmony_ci break; 247362306a36Sopenharmony_ci case CHIP_RV770: 247462306a36Sopenharmony_ci chip_name = "RV770"; 247562306a36Sopenharmony_ci rlc_chip_name = "R700"; 247662306a36Sopenharmony_ci smc_chip_name = "RV770"; 247762306a36Sopenharmony_ci smc_req_size = ALIGN(RV770_SMC_UCODE_SIZE, 4); 247862306a36Sopenharmony_ci break; 247962306a36Sopenharmony_ci case CHIP_RV730: 248062306a36Sopenharmony_ci chip_name = "RV730"; 248162306a36Sopenharmony_ci rlc_chip_name = "R700"; 248262306a36Sopenharmony_ci smc_chip_name = "RV730"; 248362306a36Sopenharmony_ci smc_req_size = ALIGN(RV730_SMC_UCODE_SIZE, 4); 248462306a36Sopenharmony_ci break; 248562306a36Sopenharmony_ci case CHIP_RV710: 248662306a36Sopenharmony_ci chip_name = "RV710"; 248762306a36Sopenharmony_ci rlc_chip_name = "R700"; 248862306a36Sopenharmony_ci smc_chip_name = "RV710"; 248962306a36Sopenharmony_ci smc_req_size = ALIGN(RV710_SMC_UCODE_SIZE, 4); 249062306a36Sopenharmony_ci break; 249162306a36Sopenharmony_ci case CHIP_RV740: 249262306a36Sopenharmony_ci chip_name = "RV730"; 249362306a36Sopenharmony_ci rlc_chip_name = "R700"; 249462306a36Sopenharmony_ci smc_chip_name = "RV740"; 249562306a36Sopenharmony_ci smc_req_size = ALIGN(RV740_SMC_UCODE_SIZE, 4); 249662306a36Sopenharmony_ci break; 249762306a36Sopenharmony_ci case CHIP_CEDAR: 249862306a36Sopenharmony_ci chip_name = "CEDAR"; 249962306a36Sopenharmony_ci rlc_chip_name = "CEDAR"; 250062306a36Sopenharmony_ci smc_chip_name = "CEDAR"; 250162306a36Sopenharmony_ci smc_req_size = ALIGN(CEDAR_SMC_UCODE_SIZE, 4); 250262306a36Sopenharmony_ci break; 250362306a36Sopenharmony_ci case CHIP_REDWOOD: 250462306a36Sopenharmony_ci chip_name = "REDWOOD"; 250562306a36Sopenharmony_ci rlc_chip_name = "REDWOOD"; 250662306a36Sopenharmony_ci smc_chip_name = "REDWOOD"; 250762306a36Sopenharmony_ci smc_req_size = ALIGN(REDWOOD_SMC_UCODE_SIZE, 4); 250862306a36Sopenharmony_ci break; 250962306a36Sopenharmony_ci case CHIP_JUNIPER: 251062306a36Sopenharmony_ci chip_name = "JUNIPER"; 251162306a36Sopenharmony_ci rlc_chip_name = "JUNIPER"; 251262306a36Sopenharmony_ci smc_chip_name = "JUNIPER"; 251362306a36Sopenharmony_ci smc_req_size = ALIGN(JUNIPER_SMC_UCODE_SIZE, 4); 251462306a36Sopenharmony_ci break; 251562306a36Sopenharmony_ci case CHIP_CYPRESS: 251662306a36Sopenharmony_ci case CHIP_HEMLOCK: 251762306a36Sopenharmony_ci chip_name = "CYPRESS"; 251862306a36Sopenharmony_ci rlc_chip_name = "CYPRESS"; 251962306a36Sopenharmony_ci smc_chip_name = "CYPRESS"; 252062306a36Sopenharmony_ci smc_req_size = ALIGN(CYPRESS_SMC_UCODE_SIZE, 4); 252162306a36Sopenharmony_ci break; 252262306a36Sopenharmony_ci case CHIP_PALM: 252362306a36Sopenharmony_ci chip_name = "PALM"; 252462306a36Sopenharmony_ci rlc_chip_name = "SUMO"; 252562306a36Sopenharmony_ci break; 252662306a36Sopenharmony_ci case CHIP_SUMO: 252762306a36Sopenharmony_ci chip_name = "SUMO"; 252862306a36Sopenharmony_ci rlc_chip_name = "SUMO"; 252962306a36Sopenharmony_ci break; 253062306a36Sopenharmony_ci case CHIP_SUMO2: 253162306a36Sopenharmony_ci chip_name = "SUMO2"; 253262306a36Sopenharmony_ci rlc_chip_name = "SUMO"; 253362306a36Sopenharmony_ci break; 253462306a36Sopenharmony_ci default: BUG(); 253562306a36Sopenharmony_ci } 253662306a36Sopenharmony_ci 253762306a36Sopenharmony_ci if (rdev->family >= CHIP_CEDAR) { 253862306a36Sopenharmony_ci pfp_req_size = EVERGREEN_PFP_UCODE_SIZE * 4; 253962306a36Sopenharmony_ci me_req_size = EVERGREEN_PM4_UCODE_SIZE * 4; 254062306a36Sopenharmony_ci rlc_req_size = EVERGREEN_RLC_UCODE_SIZE * 4; 254162306a36Sopenharmony_ci } else if (rdev->family >= CHIP_RV770) { 254262306a36Sopenharmony_ci pfp_req_size = R700_PFP_UCODE_SIZE * 4; 254362306a36Sopenharmony_ci me_req_size = R700_PM4_UCODE_SIZE * 4; 254462306a36Sopenharmony_ci rlc_req_size = R700_RLC_UCODE_SIZE * 4; 254562306a36Sopenharmony_ci } else { 254662306a36Sopenharmony_ci pfp_req_size = R600_PFP_UCODE_SIZE * 4; 254762306a36Sopenharmony_ci me_req_size = R600_PM4_UCODE_SIZE * 12; 254862306a36Sopenharmony_ci rlc_req_size = R600_RLC_UCODE_SIZE * 4; 254962306a36Sopenharmony_ci } 255062306a36Sopenharmony_ci 255162306a36Sopenharmony_ci DRM_INFO("Loading %s Microcode\n", chip_name); 255262306a36Sopenharmony_ci 255362306a36Sopenharmony_ci snprintf(fw_name, sizeof(fw_name), "radeon/%s_pfp.bin", chip_name); 255462306a36Sopenharmony_ci err = request_firmware(&rdev->pfp_fw, fw_name, rdev->dev); 255562306a36Sopenharmony_ci if (err) 255662306a36Sopenharmony_ci goto out; 255762306a36Sopenharmony_ci if (rdev->pfp_fw->size != pfp_req_size) { 255862306a36Sopenharmony_ci pr_err("r600_cp: Bogus length %zu in firmware \"%s\"\n", 255962306a36Sopenharmony_ci rdev->pfp_fw->size, fw_name); 256062306a36Sopenharmony_ci err = -EINVAL; 256162306a36Sopenharmony_ci goto out; 256262306a36Sopenharmony_ci } 256362306a36Sopenharmony_ci 256462306a36Sopenharmony_ci snprintf(fw_name, sizeof(fw_name), "radeon/%s_me.bin", chip_name); 256562306a36Sopenharmony_ci err = request_firmware(&rdev->me_fw, fw_name, rdev->dev); 256662306a36Sopenharmony_ci if (err) 256762306a36Sopenharmony_ci goto out; 256862306a36Sopenharmony_ci if (rdev->me_fw->size != me_req_size) { 256962306a36Sopenharmony_ci pr_err("r600_cp: Bogus length %zu in firmware \"%s\"\n", 257062306a36Sopenharmony_ci rdev->me_fw->size, fw_name); 257162306a36Sopenharmony_ci err = -EINVAL; 257262306a36Sopenharmony_ci goto out; 257362306a36Sopenharmony_ci } 257462306a36Sopenharmony_ci 257562306a36Sopenharmony_ci snprintf(fw_name, sizeof(fw_name), "radeon/%s_rlc.bin", rlc_chip_name); 257662306a36Sopenharmony_ci err = request_firmware(&rdev->rlc_fw, fw_name, rdev->dev); 257762306a36Sopenharmony_ci if (err) 257862306a36Sopenharmony_ci goto out; 257962306a36Sopenharmony_ci if (rdev->rlc_fw->size != rlc_req_size) { 258062306a36Sopenharmony_ci pr_err("r600_rlc: Bogus length %zu in firmware \"%s\"\n", 258162306a36Sopenharmony_ci rdev->rlc_fw->size, fw_name); 258262306a36Sopenharmony_ci err = -EINVAL; 258362306a36Sopenharmony_ci goto out; 258462306a36Sopenharmony_ci } 258562306a36Sopenharmony_ci 258662306a36Sopenharmony_ci if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_HEMLOCK)) { 258762306a36Sopenharmony_ci snprintf(fw_name, sizeof(fw_name), "radeon/%s_smc.bin", smc_chip_name); 258862306a36Sopenharmony_ci err = request_firmware(&rdev->smc_fw, fw_name, rdev->dev); 258962306a36Sopenharmony_ci if (err) { 259062306a36Sopenharmony_ci pr_err("smc: error loading firmware \"%s\"\n", fw_name); 259162306a36Sopenharmony_ci release_firmware(rdev->smc_fw); 259262306a36Sopenharmony_ci rdev->smc_fw = NULL; 259362306a36Sopenharmony_ci err = 0; 259462306a36Sopenharmony_ci } else if (rdev->smc_fw->size != smc_req_size) { 259562306a36Sopenharmony_ci pr_err("smc: Bogus length %zu in firmware \"%s\"\n", 259662306a36Sopenharmony_ci rdev->smc_fw->size, fw_name); 259762306a36Sopenharmony_ci err = -EINVAL; 259862306a36Sopenharmony_ci } 259962306a36Sopenharmony_ci } 260062306a36Sopenharmony_ci 260162306a36Sopenharmony_ciout: 260262306a36Sopenharmony_ci if (err) { 260362306a36Sopenharmony_ci if (err != -EINVAL) 260462306a36Sopenharmony_ci pr_err("r600_cp: Failed to load firmware \"%s\"\n", 260562306a36Sopenharmony_ci fw_name); 260662306a36Sopenharmony_ci release_firmware(rdev->pfp_fw); 260762306a36Sopenharmony_ci rdev->pfp_fw = NULL; 260862306a36Sopenharmony_ci release_firmware(rdev->me_fw); 260962306a36Sopenharmony_ci rdev->me_fw = NULL; 261062306a36Sopenharmony_ci release_firmware(rdev->rlc_fw); 261162306a36Sopenharmony_ci rdev->rlc_fw = NULL; 261262306a36Sopenharmony_ci release_firmware(rdev->smc_fw); 261362306a36Sopenharmony_ci rdev->smc_fw = NULL; 261462306a36Sopenharmony_ci } 261562306a36Sopenharmony_ci return err; 261662306a36Sopenharmony_ci} 261762306a36Sopenharmony_ci 261862306a36Sopenharmony_ciu32 r600_gfx_get_rptr(struct radeon_device *rdev, 261962306a36Sopenharmony_ci struct radeon_ring *ring) 262062306a36Sopenharmony_ci{ 262162306a36Sopenharmony_ci u32 rptr; 262262306a36Sopenharmony_ci 262362306a36Sopenharmony_ci if (rdev->wb.enabled) 262462306a36Sopenharmony_ci rptr = rdev->wb.wb[ring->rptr_offs/4]; 262562306a36Sopenharmony_ci else 262662306a36Sopenharmony_ci rptr = RREG32(R600_CP_RB_RPTR); 262762306a36Sopenharmony_ci 262862306a36Sopenharmony_ci return rptr; 262962306a36Sopenharmony_ci} 263062306a36Sopenharmony_ci 263162306a36Sopenharmony_ciu32 r600_gfx_get_wptr(struct radeon_device *rdev, 263262306a36Sopenharmony_ci struct radeon_ring *ring) 263362306a36Sopenharmony_ci{ 263462306a36Sopenharmony_ci return RREG32(R600_CP_RB_WPTR); 263562306a36Sopenharmony_ci} 263662306a36Sopenharmony_ci 263762306a36Sopenharmony_civoid r600_gfx_set_wptr(struct radeon_device *rdev, 263862306a36Sopenharmony_ci struct radeon_ring *ring) 263962306a36Sopenharmony_ci{ 264062306a36Sopenharmony_ci WREG32(R600_CP_RB_WPTR, ring->wptr); 264162306a36Sopenharmony_ci (void)RREG32(R600_CP_RB_WPTR); 264262306a36Sopenharmony_ci} 264362306a36Sopenharmony_ci 264462306a36Sopenharmony_cistatic int r600_cp_load_microcode(struct radeon_device *rdev) 264562306a36Sopenharmony_ci{ 264662306a36Sopenharmony_ci const __be32 *fw_data; 264762306a36Sopenharmony_ci int i; 264862306a36Sopenharmony_ci 264962306a36Sopenharmony_ci if (!rdev->me_fw || !rdev->pfp_fw) 265062306a36Sopenharmony_ci return -EINVAL; 265162306a36Sopenharmony_ci 265262306a36Sopenharmony_ci r600_cp_stop(rdev); 265362306a36Sopenharmony_ci 265462306a36Sopenharmony_ci WREG32(CP_RB_CNTL, 265562306a36Sopenharmony_ci#ifdef __BIG_ENDIAN 265662306a36Sopenharmony_ci BUF_SWAP_32BIT | 265762306a36Sopenharmony_ci#endif 265862306a36Sopenharmony_ci RB_NO_UPDATE | RB_BLKSZ(15) | RB_BUFSZ(3)); 265962306a36Sopenharmony_ci 266062306a36Sopenharmony_ci /* Reset cp */ 266162306a36Sopenharmony_ci WREG32(GRBM_SOFT_RESET, SOFT_RESET_CP); 266262306a36Sopenharmony_ci RREG32(GRBM_SOFT_RESET); 266362306a36Sopenharmony_ci mdelay(15); 266462306a36Sopenharmony_ci WREG32(GRBM_SOFT_RESET, 0); 266562306a36Sopenharmony_ci 266662306a36Sopenharmony_ci WREG32(CP_ME_RAM_WADDR, 0); 266762306a36Sopenharmony_ci 266862306a36Sopenharmony_ci fw_data = (const __be32 *)rdev->me_fw->data; 266962306a36Sopenharmony_ci WREG32(CP_ME_RAM_WADDR, 0); 267062306a36Sopenharmony_ci for (i = 0; i < R600_PM4_UCODE_SIZE * 3; i++) 267162306a36Sopenharmony_ci WREG32(CP_ME_RAM_DATA, 267262306a36Sopenharmony_ci be32_to_cpup(fw_data++)); 267362306a36Sopenharmony_ci 267462306a36Sopenharmony_ci fw_data = (const __be32 *)rdev->pfp_fw->data; 267562306a36Sopenharmony_ci WREG32(CP_PFP_UCODE_ADDR, 0); 267662306a36Sopenharmony_ci for (i = 0; i < R600_PFP_UCODE_SIZE; i++) 267762306a36Sopenharmony_ci WREG32(CP_PFP_UCODE_DATA, 267862306a36Sopenharmony_ci be32_to_cpup(fw_data++)); 267962306a36Sopenharmony_ci 268062306a36Sopenharmony_ci WREG32(CP_PFP_UCODE_ADDR, 0); 268162306a36Sopenharmony_ci WREG32(CP_ME_RAM_WADDR, 0); 268262306a36Sopenharmony_ci WREG32(CP_ME_RAM_RADDR, 0); 268362306a36Sopenharmony_ci return 0; 268462306a36Sopenharmony_ci} 268562306a36Sopenharmony_ci 268662306a36Sopenharmony_ciint r600_cp_start(struct radeon_device *rdev) 268762306a36Sopenharmony_ci{ 268862306a36Sopenharmony_ci struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; 268962306a36Sopenharmony_ci int r; 269062306a36Sopenharmony_ci uint32_t cp_me; 269162306a36Sopenharmony_ci 269262306a36Sopenharmony_ci r = radeon_ring_lock(rdev, ring, 7); 269362306a36Sopenharmony_ci if (r) { 269462306a36Sopenharmony_ci DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r); 269562306a36Sopenharmony_ci return r; 269662306a36Sopenharmony_ci } 269762306a36Sopenharmony_ci radeon_ring_write(ring, PACKET3(PACKET3_ME_INITIALIZE, 5)); 269862306a36Sopenharmony_ci radeon_ring_write(ring, 0x1); 269962306a36Sopenharmony_ci if (rdev->family >= CHIP_RV770) { 270062306a36Sopenharmony_ci radeon_ring_write(ring, 0x0); 270162306a36Sopenharmony_ci radeon_ring_write(ring, rdev->config.rv770.max_hw_contexts - 1); 270262306a36Sopenharmony_ci } else { 270362306a36Sopenharmony_ci radeon_ring_write(ring, 0x3); 270462306a36Sopenharmony_ci radeon_ring_write(ring, rdev->config.r600.max_hw_contexts - 1); 270562306a36Sopenharmony_ci } 270662306a36Sopenharmony_ci radeon_ring_write(ring, PACKET3_ME_INITIALIZE_DEVICE_ID(1)); 270762306a36Sopenharmony_ci radeon_ring_write(ring, 0); 270862306a36Sopenharmony_ci radeon_ring_write(ring, 0); 270962306a36Sopenharmony_ci radeon_ring_unlock_commit(rdev, ring, false); 271062306a36Sopenharmony_ci 271162306a36Sopenharmony_ci cp_me = 0xff; 271262306a36Sopenharmony_ci WREG32(R_0086D8_CP_ME_CNTL, cp_me); 271362306a36Sopenharmony_ci return 0; 271462306a36Sopenharmony_ci} 271562306a36Sopenharmony_ci 271662306a36Sopenharmony_ciint r600_cp_resume(struct radeon_device *rdev) 271762306a36Sopenharmony_ci{ 271862306a36Sopenharmony_ci struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; 271962306a36Sopenharmony_ci u32 tmp; 272062306a36Sopenharmony_ci u32 rb_bufsz; 272162306a36Sopenharmony_ci int r; 272262306a36Sopenharmony_ci 272362306a36Sopenharmony_ci /* Reset cp */ 272462306a36Sopenharmony_ci WREG32(GRBM_SOFT_RESET, SOFT_RESET_CP); 272562306a36Sopenharmony_ci RREG32(GRBM_SOFT_RESET); 272662306a36Sopenharmony_ci mdelay(15); 272762306a36Sopenharmony_ci WREG32(GRBM_SOFT_RESET, 0); 272862306a36Sopenharmony_ci 272962306a36Sopenharmony_ci /* Set ring buffer size */ 273062306a36Sopenharmony_ci rb_bufsz = order_base_2(ring->ring_size / 8); 273162306a36Sopenharmony_ci tmp = (order_base_2(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz; 273262306a36Sopenharmony_ci#ifdef __BIG_ENDIAN 273362306a36Sopenharmony_ci tmp |= BUF_SWAP_32BIT; 273462306a36Sopenharmony_ci#endif 273562306a36Sopenharmony_ci WREG32(CP_RB_CNTL, tmp); 273662306a36Sopenharmony_ci WREG32(CP_SEM_WAIT_TIMER, 0x0); 273762306a36Sopenharmony_ci 273862306a36Sopenharmony_ci /* Set the write pointer delay */ 273962306a36Sopenharmony_ci WREG32(CP_RB_WPTR_DELAY, 0); 274062306a36Sopenharmony_ci 274162306a36Sopenharmony_ci /* Initialize the ring buffer's read and write pointers */ 274262306a36Sopenharmony_ci WREG32(CP_RB_CNTL, tmp | RB_RPTR_WR_ENA); 274362306a36Sopenharmony_ci WREG32(CP_RB_RPTR_WR, 0); 274462306a36Sopenharmony_ci ring->wptr = 0; 274562306a36Sopenharmony_ci WREG32(CP_RB_WPTR, ring->wptr); 274662306a36Sopenharmony_ci 274762306a36Sopenharmony_ci /* set the wb address whether it's enabled or not */ 274862306a36Sopenharmony_ci WREG32(CP_RB_RPTR_ADDR, 274962306a36Sopenharmony_ci ((rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFFFFFFFC)); 275062306a36Sopenharmony_ci WREG32(CP_RB_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFF); 275162306a36Sopenharmony_ci WREG32(SCRATCH_ADDR, ((rdev->wb.gpu_addr + RADEON_WB_SCRATCH_OFFSET) >> 8) & 0xFFFFFFFF); 275262306a36Sopenharmony_ci 275362306a36Sopenharmony_ci if (rdev->wb.enabled) 275462306a36Sopenharmony_ci WREG32(SCRATCH_UMSK, 0xff); 275562306a36Sopenharmony_ci else { 275662306a36Sopenharmony_ci tmp |= RB_NO_UPDATE; 275762306a36Sopenharmony_ci WREG32(SCRATCH_UMSK, 0); 275862306a36Sopenharmony_ci } 275962306a36Sopenharmony_ci 276062306a36Sopenharmony_ci mdelay(1); 276162306a36Sopenharmony_ci WREG32(CP_RB_CNTL, tmp); 276262306a36Sopenharmony_ci 276362306a36Sopenharmony_ci WREG32(CP_RB_BASE, ring->gpu_addr >> 8); 276462306a36Sopenharmony_ci WREG32(CP_DEBUG, (1 << 27) | (1 << 28)); 276562306a36Sopenharmony_ci 276662306a36Sopenharmony_ci r600_cp_start(rdev); 276762306a36Sopenharmony_ci ring->ready = true; 276862306a36Sopenharmony_ci r = radeon_ring_test(rdev, RADEON_RING_TYPE_GFX_INDEX, ring); 276962306a36Sopenharmony_ci if (r) { 277062306a36Sopenharmony_ci ring->ready = false; 277162306a36Sopenharmony_ci return r; 277262306a36Sopenharmony_ci } 277362306a36Sopenharmony_ci 277462306a36Sopenharmony_ci if (rdev->asic->copy.copy_ring_index == RADEON_RING_TYPE_GFX_INDEX) 277562306a36Sopenharmony_ci radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size); 277662306a36Sopenharmony_ci 277762306a36Sopenharmony_ci return 0; 277862306a36Sopenharmony_ci} 277962306a36Sopenharmony_ci 278062306a36Sopenharmony_civoid r600_ring_init(struct radeon_device *rdev, struct radeon_ring *ring, unsigned ring_size) 278162306a36Sopenharmony_ci{ 278262306a36Sopenharmony_ci u32 rb_bufsz; 278362306a36Sopenharmony_ci int r; 278462306a36Sopenharmony_ci 278562306a36Sopenharmony_ci /* Align ring size */ 278662306a36Sopenharmony_ci rb_bufsz = order_base_2(ring_size / 8); 278762306a36Sopenharmony_ci ring_size = (1 << (rb_bufsz + 1)) * 4; 278862306a36Sopenharmony_ci ring->ring_size = ring_size; 278962306a36Sopenharmony_ci ring->align_mask = 16 - 1; 279062306a36Sopenharmony_ci 279162306a36Sopenharmony_ci if (radeon_ring_supports_scratch_reg(rdev, ring)) { 279262306a36Sopenharmony_ci r = radeon_scratch_get(rdev, &ring->rptr_save_reg); 279362306a36Sopenharmony_ci if (r) { 279462306a36Sopenharmony_ci DRM_ERROR("failed to get scratch reg for rptr save (%d).\n", r); 279562306a36Sopenharmony_ci ring->rptr_save_reg = 0; 279662306a36Sopenharmony_ci } 279762306a36Sopenharmony_ci } 279862306a36Sopenharmony_ci} 279962306a36Sopenharmony_ci 280062306a36Sopenharmony_civoid r600_cp_fini(struct radeon_device *rdev) 280162306a36Sopenharmony_ci{ 280262306a36Sopenharmony_ci struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; 280362306a36Sopenharmony_ci r600_cp_stop(rdev); 280462306a36Sopenharmony_ci radeon_ring_fini(rdev, ring); 280562306a36Sopenharmony_ci radeon_scratch_free(rdev, ring->rptr_save_reg); 280662306a36Sopenharmony_ci} 280762306a36Sopenharmony_ci 280862306a36Sopenharmony_ci/* 280962306a36Sopenharmony_ci * GPU scratch registers helpers function. 281062306a36Sopenharmony_ci */ 281162306a36Sopenharmony_civoid r600_scratch_init(struct radeon_device *rdev) 281262306a36Sopenharmony_ci{ 281362306a36Sopenharmony_ci int i; 281462306a36Sopenharmony_ci 281562306a36Sopenharmony_ci rdev->scratch.num_reg = 7; 281662306a36Sopenharmony_ci rdev->scratch.reg_base = SCRATCH_REG0; 281762306a36Sopenharmony_ci for (i = 0; i < rdev->scratch.num_reg; i++) { 281862306a36Sopenharmony_ci rdev->scratch.free[i] = true; 281962306a36Sopenharmony_ci rdev->scratch.reg[i] = rdev->scratch.reg_base + (i * 4); 282062306a36Sopenharmony_ci } 282162306a36Sopenharmony_ci} 282262306a36Sopenharmony_ci 282362306a36Sopenharmony_ciint r600_ring_test(struct radeon_device *rdev, struct radeon_ring *ring) 282462306a36Sopenharmony_ci{ 282562306a36Sopenharmony_ci uint32_t scratch; 282662306a36Sopenharmony_ci uint32_t tmp = 0; 282762306a36Sopenharmony_ci unsigned i; 282862306a36Sopenharmony_ci int r; 282962306a36Sopenharmony_ci 283062306a36Sopenharmony_ci r = radeon_scratch_get(rdev, &scratch); 283162306a36Sopenharmony_ci if (r) { 283262306a36Sopenharmony_ci DRM_ERROR("radeon: cp failed to get scratch reg (%d).\n", r); 283362306a36Sopenharmony_ci return r; 283462306a36Sopenharmony_ci } 283562306a36Sopenharmony_ci WREG32(scratch, 0xCAFEDEAD); 283662306a36Sopenharmony_ci r = radeon_ring_lock(rdev, ring, 3); 283762306a36Sopenharmony_ci if (r) { 283862306a36Sopenharmony_ci DRM_ERROR("radeon: cp failed to lock ring %d (%d).\n", ring->idx, r); 283962306a36Sopenharmony_ci radeon_scratch_free(rdev, scratch); 284062306a36Sopenharmony_ci return r; 284162306a36Sopenharmony_ci } 284262306a36Sopenharmony_ci radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); 284362306a36Sopenharmony_ci radeon_ring_write(ring, ((scratch - PACKET3_SET_CONFIG_REG_OFFSET) >> 2)); 284462306a36Sopenharmony_ci radeon_ring_write(ring, 0xDEADBEEF); 284562306a36Sopenharmony_ci radeon_ring_unlock_commit(rdev, ring, false); 284662306a36Sopenharmony_ci for (i = 0; i < rdev->usec_timeout; i++) { 284762306a36Sopenharmony_ci tmp = RREG32(scratch); 284862306a36Sopenharmony_ci if (tmp == 0xDEADBEEF) 284962306a36Sopenharmony_ci break; 285062306a36Sopenharmony_ci udelay(1); 285162306a36Sopenharmony_ci } 285262306a36Sopenharmony_ci if (i < rdev->usec_timeout) { 285362306a36Sopenharmony_ci DRM_INFO("ring test on %d succeeded in %d usecs\n", ring->idx, i); 285462306a36Sopenharmony_ci } else { 285562306a36Sopenharmony_ci DRM_ERROR("radeon: ring %d test failed (scratch(0x%04X)=0x%08X)\n", 285662306a36Sopenharmony_ci ring->idx, scratch, tmp); 285762306a36Sopenharmony_ci r = -EINVAL; 285862306a36Sopenharmony_ci } 285962306a36Sopenharmony_ci radeon_scratch_free(rdev, scratch); 286062306a36Sopenharmony_ci return r; 286162306a36Sopenharmony_ci} 286262306a36Sopenharmony_ci 286362306a36Sopenharmony_ci/* 286462306a36Sopenharmony_ci * CP fences/semaphores 286562306a36Sopenharmony_ci */ 286662306a36Sopenharmony_ci 286762306a36Sopenharmony_civoid r600_fence_ring_emit(struct radeon_device *rdev, 286862306a36Sopenharmony_ci struct radeon_fence *fence) 286962306a36Sopenharmony_ci{ 287062306a36Sopenharmony_ci struct radeon_ring *ring = &rdev->ring[fence->ring]; 287162306a36Sopenharmony_ci u32 cp_coher_cntl = PACKET3_TC_ACTION_ENA | PACKET3_VC_ACTION_ENA | 287262306a36Sopenharmony_ci PACKET3_SH_ACTION_ENA; 287362306a36Sopenharmony_ci 287462306a36Sopenharmony_ci if (rdev->family >= CHIP_RV770) 287562306a36Sopenharmony_ci cp_coher_cntl |= PACKET3_FULL_CACHE_ENA; 287662306a36Sopenharmony_ci 287762306a36Sopenharmony_ci if (rdev->wb.use_event) { 287862306a36Sopenharmony_ci u64 addr = rdev->fence_drv[fence->ring].gpu_addr; 287962306a36Sopenharmony_ci /* flush read cache over gart */ 288062306a36Sopenharmony_ci radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3)); 288162306a36Sopenharmony_ci radeon_ring_write(ring, cp_coher_cntl); 288262306a36Sopenharmony_ci radeon_ring_write(ring, 0xFFFFFFFF); 288362306a36Sopenharmony_ci radeon_ring_write(ring, 0); 288462306a36Sopenharmony_ci radeon_ring_write(ring, 10); /* poll interval */ 288562306a36Sopenharmony_ci /* EVENT_WRITE_EOP - flush caches, send int */ 288662306a36Sopenharmony_ci radeon_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE_EOP, 4)); 288762306a36Sopenharmony_ci radeon_ring_write(ring, EVENT_TYPE(CACHE_FLUSH_AND_INV_EVENT_TS) | EVENT_INDEX(5)); 288862306a36Sopenharmony_ci radeon_ring_write(ring, lower_32_bits(addr)); 288962306a36Sopenharmony_ci radeon_ring_write(ring, (upper_32_bits(addr) & 0xff) | DATA_SEL(1) | INT_SEL(2)); 289062306a36Sopenharmony_ci radeon_ring_write(ring, fence->seq); 289162306a36Sopenharmony_ci radeon_ring_write(ring, 0); 289262306a36Sopenharmony_ci } else { 289362306a36Sopenharmony_ci /* flush read cache over gart */ 289462306a36Sopenharmony_ci radeon_ring_write(ring, PACKET3(PACKET3_SURFACE_SYNC, 3)); 289562306a36Sopenharmony_ci radeon_ring_write(ring, cp_coher_cntl); 289662306a36Sopenharmony_ci radeon_ring_write(ring, 0xFFFFFFFF); 289762306a36Sopenharmony_ci radeon_ring_write(ring, 0); 289862306a36Sopenharmony_ci radeon_ring_write(ring, 10); /* poll interval */ 289962306a36Sopenharmony_ci radeon_ring_write(ring, PACKET3(PACKET3_EVENT_WRITE, 0)); 290062306a36Sopenharmony_ci radeon_ring_write(ring, EVENT_TYPE(CACHE_FLUSH_AND_INV_EVENT) | EVENT_INDEX(0)); 290162306a36Sopenharmony_ci /* wait for 3D idle clean */ 290262306a36Sopenharmony_ci radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); 290362306a36Sopenharmony_ci radeon_ring_write(ring, (WAIT_UNTIL - PACKET3_SET_CONFIG_REG_OFFSET) >> 2); 290462306a36Sopenharmony_ci radeon_ring_write(ring, WAIT_3D_IDLE_bit | WAIT_3D_IDLECLEAN_bit); 290562306a36Sopenharmony_ci /* Emit fence sequence & fire IRQ */ 290662306a36Sopenharmony_ci radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); 290762306a36Sopenharmony_ci radeon_ring_write(ring, ((rdev->fence_drv[fence->ring].scratch_reg - PACKET3_SET_CONFIG_REG_OFFSET) >> 2)); 290862306a36Sopenharmony_ci radeon_ring_write(ring, fence->seq); 290962306a36Sopenharmony_ci /* CP_INTERRUPT packet 3 no longer exists, use packet 0 */ 291062306a36Sopenharmony_ci radeon_ring_write(ring, PACKET0(CP_INT_STATUS, 0)); 291162306a36Sopenharmony_ci radeon_ring_write(ring, RB_INT_STAT); 291262306a36Sopenharmony_ci } 291362306a36Sopenharmony_ci} 291462306a36Sopenharmony_ci 291562306a36Sopenharmony_ci/** 291662306a36Sopenharmony_ci * r600_semaphore_ring_emit - emit a semaphore on the CP ring 291762306a36Sopenharmony_ci * 291862306a36Sopenharmony_ci * @rdev: radeon_device pointer 291962306a36Sopenharmony_ci * @ring: radeon ring buffer object 292062306a36Sopenharmony_ci * @semaphore: radeon semaphore object 292162306a36Sopenharmony_ci * @emit_wait: Is this a semaphore wait? 292262306a36Sopenharmony_ci * 292362306a36Sopenharmony_ci * Emits a semaphore signal/wait packet to the CP ring and prevents the PFP 292462306a36Sopenharmony_ci * from running ahead of semaphore waits. 292562306a36Sopenharmony_ci */ 292662306a36Sopenharmony_cibool r600_semaphore_ring_emit(struct radeon_device *rdev, 292762306a36Sopenharmony_ci struct radeon_ring *ring, 292862306a36Sopenharmony_ci struct radeon_semaphore *semaphore, 292962306a36Sopenharmony_ci bool emit_wait) 293062306a36Sopenharmony_ci{ 293162306a36Sopenharmony_ci uint64_t addr = semaphore->gpu_addr; 293262306a36Sopenharmony_ci unsigned sel = emit_wait ? PACKET3_SEM_SEL_WAIT : PACKET3_SEM_SEL_SIGNAL; 293362306a36Sopenharmony_ci 293462306a36Sopenharmony_ci if (rdev->family < CHIP_CAYMAN) 293562306a36Sopenharmony_ci sel |= PACKET3_SEM_WAIT_ON_SIGNAL; 293662306a36Sopenharmony_ci 293762306a36Sopenharmony_ci radeon_ring_write(ring, PACKET3(PACKET3_MEM_SEMAPHORE, 1)); 293862306a36Sopenharmony_ci radeon_ring_write(ring, lower_32_bits(addr)); 293962306a36Sopenharmony_ci radeon_ring_write(ring, (upper_32_bits(addr) & 0xff) | sel); 294062306a36Sopenharmony_ci 294162306a36Sopenharmony_ci /* PFP_SYNC_ME packet only exists on 7xx+, only enable it on eg+ */ 294262306a36Sopenharmony_ci if (emit_wait && (rdev->family >= CHIP_CEDAR)) { 294362306a36Sopenharmony_ci /* Prevent the PFP from running ahead of the semaphore wait */ 294462306a36Sopenharmony_ci radeon_ring_write(ring, PACKET3(PACKET3_PFP_SYNC_ME, 0)); 294562306a36Sopenharmony_ci radeon_ring_write(ring, 0x0); 294662306a36Sopenharmony_ci } 294762306a36Sopenharmony_ci 294862306a36Sopenharmony_ci return true; 294962306a36Sopenharmony_ci} 295062306a36Sopenharmony_ci 295162306a36Sopenharmony_ci/** 295262306a36Sopenharmony_ci * r600_copy_cpdma - copy pages using the CP DMA engine 295362306a36Sopenharmony_ci * 295462306a36Sopenharmony_ci * @rdev: radeon_device pointer 295562306a36Sopenharmony_ci * @src_offset: src GPU address 295662306a36Sopenharmony_ci * @dst_offset: dst GPU address 295762306a36Sopenharmony_ci * @num_gpu_pages: number of GPU pages to xfer 295862306a36Sopenharmony_ci * @resv: DMA reservation object to manage fences 295962306a36Sopenharmony_ci * 296062306a36Sopenharmony_ci * Copy GPU paging using the CP DMA engine (r6xx+). 296162306a36Sopenharmony_ci * Used by the radeon ttm implementation to move pages if 296262306a36Sopenharmony_ci * registered as the asic copy callback. 296362306a36Sopenharmony_ci */ 296462306a36Sopenharmony_cistruct radeon_fence *r600_copy_cpdma(struct radeon_device *rdev, 296562306a36Sopenharmony_ci uint64_t src_offset, uint64_t dst_offset, 296662306a36Sopenharmony_ci unsigned num_gpu_pages, 296762306a36Sopenharmony_ci struct dma_resv *resv) 296862306a36Sopenharmony_ci{ 296962306a36Sopenharmony_ci struct radeon_fence *fence; 297062306a36Sopenharmony_ci struct radeon_sync sync; 297162306a36Sopenharmony_ci int ring_index = rdev->asic->copy.blit_ring_index; 297262306a36Sopenharmony_ci struct radeon_ring *ring = &rdev->ring[ring_index]; 297362306a36Sopenharmony_ci u32 size_in_bytes, cur_size_in_bytes, tmp; 297462306a36Sopenharmony_ci int i, num_loops; 297562306a36Sopenharmony_ci int r = 0; 297662306a36Sopenharmony_ci 297762306a36Sopenharmony_ci radeon_sync_create(&sync); 297862306a36Sopenharmony_ci 297962306a36Sopenharmony_ci size_in_bytes = (num_gpu_pages << RADEON_GPU_PAGE_SHIFT); 298062306a36Sopenharmony_ci num_loops = DIV_ROUND_UP(size_in_bytes, 0x1fffff); 298162306a36Sopenharmony_ci r = radeon_ring_lock(rdev, ring, num_loops * 6 + 24); 298262306a36Sopenharmony_ci if (r) { 298362306a36Sopenharmony_ci DRM_ERROR("radeon: moving bo (%d).\n", r); 298462306a36Sopenharmony_ci radeon_sync_free(rdev, &sync, NULL); 298562306a36Sopenharmony_ci return ERR_PTR(r); 298662306a36Sopenharmony_ci } 298762306a36Sopenharmony_ci 298862306a36Sopenharmony_ci radeon_sync_resv(rdev, &sync, resv, false); 298962306a36Sopenharmony_ci radeon_sync_rings(rdev, &sync, ring->idx); 299062306a36Sopenharmony_ci 299162306a36Sopenharmony_ci radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); 299262306a36Sopenharmony_ci radeon_ring_write(ring, (WAIT_UNTIL - PACKET3_SET_CONFIG_REG_OFFSET) >> 2); 299362306a36Sopenharmony_ci radeon_ring_write(ring, WAIT_3D_IDLE_bit); 299462306a36Sopenharmony_ci for (i = 0; i < num_loops; i++) { 299562306a36Sopenharmony_ci cur_size_in_bytes = size_in_bytes; 299662306a36Sopenharmony_ci if (cur_size_in_bytes > 0x1fffff) 299762306a36Sopenharmony_ci cur_size_in_bytes = 0x1fffff; 299862306a36Sopenharmony_ci size_in_bytes -= cur_size_in_bytes; 299962306a36Sopenharmony_ci tmp = upper_32_bits(src_offset) & 0xff; 300062306a36Sopenharmony_ci if (size_in_bytes == 0) 300162306a36Sopenharmony_ci tmp |= PACKET3_CP_DMA_CP_SYNC; 300262306a36Sopenharmony_ci radeon_ring_write(ring, PACKET3(PACKET3_CP_DMA, 4)); 300362306a36Sopenharmony_ci radeon_ring_write(ring, lower_32_bits(src_offset)); 300462306a36Sopenharmony_ci radeon_ring_write(ring, tmp); 300562306a36Sopenharmony_ci radeon_ring_write(ring, lower_32_bits(dst_offset)); 300662306a36Sopenharmony_ci radeon_ring_write(ring, upper_32_bits(dst_offset) & 0xff); 300762306a36Sopenharmony_ci radeon_ring_write(ring, cur_size_in_bytes); 300862306a36Sopenharmony_ci src_offset += cur_size_in_bytes; 300962306a36Sopenharmony_ci dst_offset += cur_size_in_bytes; 301062306a36Sopenharmony_ci } 301162306a36Sopenharmony_ci radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); 301262306a36Sopenharmony_ci radeon_ring_write(ring, (WAIT_UNTIL - PACKET3_SET_CONFIG_REG_OFFSET) >> 2); 301362306a36Sopenharmony_ci radeon_ring_write(ring, WAIT_CP_DMA_IDLE_bit); 301462306a36Sopenharmony_ci 301562306a36Sopenharmony_ci r = radeon_fence_emit(rdev, &fence, ring->idx); 301662306a36Sopenharmony_ci if (r) { 301762306a36Sopenharmony_ci radeon_ring_unlock_undo(rdev, ring); 301862306a36Sopenharmony_ci radeon_sync_free(rdev, &sync, NULL); 301962306a36Sopenharmony_ci return ERR_PTR(r); 302062306a36Sopenharmony_ci } 302162306a36Sopenharmony_ci 302262306a36Sopenharmony_ci radeon_ring_unlock_commit(rdev, ring, false); 302362306a36Sopenharmony_ci radeon_sync_free(rdev, &sync, fence); 302462306a36Sopenharmony_ci 302562306a36Sopenharmony_ci return fence; 302662306a36Sopenharmony_ci} 302762306a36Sopenharmony_ci 302862306a36Sopenharmony_ciint r600_set_surface_reg(struct radeon_device *rdev, int reg, 302962306a36Sopenharmony_ci uint32_t tiling_flags, uint32_t pitch, 303062306a36Sopenharmony_ci uint32_t offset, uint32_t obj_size) 303162306a36Sopenharmony_ci{ 303262306a36Sopenharmony_ci /* FIXME: implement */ 303362306a36Sopenharmony_ci return 0; 303462306a36Sopenharmony_ci} 303562306a36Sopenharmony_ci 303662306a36Sopenharmony_civoid r600_clear_surface_reg(struct radeon_device *rdev, int reg) 303762306a36Sopenharmony_ci{ 303862306a36Sopenharmony_ci /* FIXME: implement */ 303962306a36Sopenharmony_ci} 304062306a36Sopenharmony_ci 304162306a36Sopenharmony_cistatic void r600_uvd_init(struct radeon_device *rdev) 304262306a36Sopenharmony_ci{ 304362306a36Sopenharmony_ci int r; 304462306a36Sopenharmony_ci 304562306a36Sopenharmony_ci if (!rdev->has_uvd) 304662306a36Sopenharmony_ci return; 304762306a36Sopenharmony_ci 304862306a36Sopenharmony_ci r = radeon_uvd_init(rdev); 304962306a36Sopenharmony_ci if (r) { 305062306a36Sopenharmony_ci dev_err(rdev->dev, "failed UVD (%d) init.\n", r); 305162306a36Sopenharmony_ci /* 305262306a36Sopenharmony_ci * At this point rdev->uvd.vcpu_bo is NULL which trickles down 305362306a36Sopenharmony_ci * to early fails uvd_v1_0_resume() and thus nothing happens 305462306a36Sopenharmony_ci * there. So it is pointless to try to go through that code 305562306a36Sopenharmony_ci * hence why we disable uvd here. 305662306a36Sopenharmony_ci */ 305762306a36Sopenharmony_ci rdev->has_uvd = false; 305862306a36Sopenharmony_ci return; 305962306a36Sopenharmony_ci } 306062306a36Sopenharmony_ci rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_obj = NULL; 306162306a36Sopenharmony_ci r600_ring_init(rdev, &rdev->ring[R600_RING_TYPE_UVD_INDEX], 4096); 306262306a36Sopenharmony_ci} 306362306a36Sopenharmony_ci 306462306a36Sopenharmony_cistatic void r600_uvd_start(struct radeon_device *rdev) 306562306a36Sopenharmony_ci{ 306662306a36Sopenharmony_ci int r; 306762306a36Sopenharmony_ci 306862306a36Sopenharmony_ci if (!rdev->has_uvd) 306962306a36Sopenharmony_ci return; 307062306a36Sopenharmony_ci 307162306a36Sopenharmony_ci r = uvd_v1_0_resume(rdev); 307262306a36Sopenharmony_ci if (r) { 307362306a36Sopenharmony_ci dev_err(rdev->dev, "failed UVD resume (%d).\n", r); 307462306a36Sopenharmony_ci goto error; 307562306a36Sopenharmony_ci } 307662306a36Sopenharmony_ci r = radeon_fence_driver_start_ring(rdev, R600_RING_TYPE_UVD_INDEX); 307762306a36Sopenharmony_ci if (r) { 307862306a36Sopenharmony_ci dev_err(rdev->dev, "failed initializing UVD fences (%d).\n", r); 307962306a36Sopenharmony_ci goto error; 308062306a36Sopenharmony_ci } 308162306a36Sopenharmony_ci return; 308262306a36Sopenharmony_ci 308362306a36Sopenharmony_cierror: 308462306a36Sopenharmony_ci rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0; 308562306a36Sopenharmony_ci} 308662306a36Sopenharmony_ci 308762306a36Sopenharmony_cistatic void r600_uvd_resume(struct radeon_device *rdev) 308862306a36Sopenharmony_ci{ 308962306a36Sopenharmony_ci struct radeon_ring *ring; 309062306a36Sopenharmony_ci int r; 309162306a36Sopenharmony_ci 309262306a36Sopenharmony_ci if (!rdev->has_uvd || !rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size) 309362306a36Sopenharmony_ci return; 309462306a36Sopenharmony_ci 309562306a36Sopenharmony_ci ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX]; 309662306a36Sopenharmony_ci r = radeon_ring_init(rdev, ring, ring->ring_size, 0, PACKET0(UVD_NO_OP, 0)); 309762306a36Sopenharmony_ci if (r) { 309862306a36Sopenharmony_ci dev_err(rdev->dev, "failed initializing UVD ring (%d).\n", r); 309962306a36Sopenharmony_ci return; 310062306a36Sopenharmony_ci } 310162306a36Sopenharmony_ci r = uvd_v1_0_init(rdev); 310262306a36Sopenharmony_ci if (r) { 310362306a36Sopenharmony_ci dev_err(rdev->dev, "failed initializing UVD (%d).\n", r); 310462306a36Sopenharmony_ci return; 310562306a36Sopenharmony_ci } 310662306a36Sopenharmony_ci} 310762306a36Sopenharmony_ci 310862306a36Sopenharmony_cistatic int r600_startup(struct radeon_device *rdev) 310962306a36Sopenharmony_ci{ 311062306a36Sopenharmony_ci struct radeon_ring *ring; 311162306a36Sopenharmony_ci int r; 311262306a36Sopenharmony_ci 311362306a36Sopenharmony_ci /* enable pcie gen2 link */ 311462306a36Sopenharmony_ci r600_pcie_gen2_enable(rdev); 311562306a36Sopenharmony_ci 311662306a36Sopenharmony_ci /* scratch needs to be initialized before MC */ 311762306a36Sopenharmony_ci r = r600_vram_scratch_init(rdev); 311862306a36Sopenharmony_ci if (r) 311962306a36Sopenharmony_ci return r; 312062306a36Sopenharmony_ci 312162306a36Sopenharmony_ci r600_mc_program(rdev); 312262306a36Sopenharmony_ci 312362306a36Sopenharmony_ci if (rdev->flags & RADEON_IS_AGP) { 312462306a36Sopenharmony_ci r600_agp_enable(rdev); 312562306a36Sopenharmony_ci } else { 312662306a36Sopenharmony_ci r = r600_pcie_gart_enable(rdev); 312762306a36Sopenharmony_ci if (r) 312862306a36Sopenharmony_ci return r; 312962306a36Sopenharmony_ci } 313062306a36Sopenharmony_ci r600_gpu_init(rdev); 313162306a36Sopenharmony_ci 313262306a36Sopenharmony_ci /* allocate wb buffer */ 313362306a36Sopenharmony_ci r = radeon_wb_init(rdev); 313462306a36Sopenharmony_ci if (r) 313562306a36Sopenharmony_ci return r; 313662306a36Sopenharmony_ci 313762306a36Sopenharmony_ci r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX); 313862306a36Sopenharmony_ci if (r) { 313962306a36Sopenharmony_ci dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); 314062306a36Sopenharmony_ci return r; 314162306a36Sopenharmony_ci } 314262306a36Sopenharmony_ci 314362306a36Sopenharmony_ci r600_uvd_start(rdev); 314462306a36Sopenharmony_ci 314562306a36Sopenharmony_ci /* Enable IRQ */ 314662306a36Sopenharmony_ci if (!rdev->irq.installed) { 314762306a36Sopenharmony_ci r = radeon_irq_kms_init(rdev); 314862306a36Sopenharmony_ci if (r) 314962306a36Sopenharmony_ci return r; 315062306a36Sopenharmony_ci } 315162306a36Sopenharmony_ci 315262306a36Sopenharmony_ci r = r600_irq_init(rdev); 315362306a36Sopenharmony_ci if (r) { 315462306a36Sopenharmony_ci DRM_ERROR("radeon: IH init failed (%d).\n", r); 315562306a36Sopenharmony_ci radeon_irq_kms_fini(rdev); 315662306a36Sopenharmony_ci return r; 315762306a36Sopenharmony_ci } 315862306a36Sopenharmony_ci r600_irq_set(rdev); 315962306a36Sopenharmony_ci 316062306a36Sopenharmony_ci ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; 316162306a36Sopenharmony_ci r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET, 316262306a36Sopenharmony_ci RADEON_CP_PACKET2); 316362306a36Sopenharmony_ci if (r) 316462306a36Sopenharmony_ci return r; 316562306a36Sopenharmony_ci 316662306a36Sopenharmony_ci r = r600_cp_load_microcode(rdev); 316762306a36Sopenharmony_ci if (r) 316862306a36Sopenharmony_ci return r; 316962306a36Sopenharmony_ci r = r600_cp_resume(rdev); 317062306a36Sopenharmony_ci if (r) 317162306a36Sopenharmony_ci return r; 317262306a36Sopenharmony_ci 317362306a36Sopenharmony_ci r600_uvd_resume(rdev); 317462306a36Sopenharmony_ci 317562306a36Sopenharmony_ci r = radeon_ib_pool_init(rdev); 317662306a36Sopenharmony_ci if (r) { 317762306a36Sopenharmony_ci dev_err(rdev->dev, "IB initialization failed (%d).\n", r); 317862306a36Sopenharmony_ci return r; 317962306a36Sopenharmony_ci } 318062306a36Sopenharmony_ci 318162306a36Sopenharmony_ci r = radeon_audio_init(rdev); 318262306a36Sopenharmony_ci if (r) { 318362306a36Sopenharmony_ci DRM_ERROR("radeon: audio init failed\n"); 318462306a36Sopenharmony_ci return r; 318562306a36Sopenharmony_ci } 318662306a36Sopenharmony_ci 318762306a36Sopenharmony_ci return 0; 318862306a36Sopenharmony_ci} 318962306a36Sopenharmony_ci 319062306a36Sopenharmony_civoid r600_vga_set_state(struct radeon_device *rdev, bool state) 319162306a36Sopenharmony_ci{ 319262306a36Sopenharmony_ci uint32_t temp; 319362306a36Sopenharmony_ci 319462306a36Sopenharmony_ci temp = RREG32(CONFIG_CNTL); 319562306a36Sopenharmony_ci if (!state) { 319662306a36Sopenharmony_ci temp &= ~(1<<0); 319762306a36Sopenharmony_ci temp |= (1<<1); 319862306a36Sopenharmony_ci } else { 319962306a36Sopenharmony_ci temp &= ~(1<<1); 320062306a36Sopenharmony_ci } 320162306a36Sopenharmony_ci WREG32(CONFIG_CNTL, temp); 320262306a36Sopenharmony_ci} 320362306a36Sopenharmony_ci 320462306a36Sopenharmony_ciint r600_resume(struct radeon_device *rdev) 320562306a36Sopenharmony_ci{ 320662306a36Sopenharmony_ci int r; 320762306a36Sopenharmony_ci 320862306a36Sopenharmony_ci /* Do not reset GPU before posting, on r600 hw unlike on r500 hw, 320962306a36Sopenharmony_ci * posting will perform necessary task to bring back GPU into good 321062306a36Sopenharmony_ci * shape. 321162306a36Sopenharmony_ci */ 321262306a36Sopenharmony_ci /* post card */ 321362306a36Sopenharmony_ci atom_asic_init(rdev->mode_info.atom_context); 321462306a36Sopenharmony_ci 321562306a36Sopenharmony_ci if (rdev->pm.pm_method == PM_METHOD_DPM) 321662306a36Sopenharmony_ci radeon_pm_resume(rdev); 321762306a36Sopenharmony_ci 321862306a36Sopenharmony_ci rdev->accel_working = true; 321962306a36Sopenharmony_ci r = r600_startup(rdev); 322062306a36Sopenharmony_ci if (r) { 322162306a36Sopenharmony_ci DRM_ERROR("r600 startup failed on resume\n"); 322262306a36Sopenharmony_ci rdev->accel_working = false; 322362306a36Sopenharmony_ci return r; 322462306a36Sopenharmony_ci } 322562306a36Sopenharmony_ci 322662306a36Sopenharmony_ci return r; 322762306a36Sopenharmony_ci} 322862306a36Sopenharmony_ci 322962306a36Sopenharmony_ciint r600_suspend(struct radeon_device *rdev) 323062306a36Sopenharmony_ci{ 323162306a36Sopenharmony_ci radeon_pm_suspend(rdev); 323262306a36Sopenharmony_ci radeon_audio_fini(rdev); 323362306a36Sopenharmony_ci r600_cp_stop(rdev); 323462306a36Sopenharmony_ci if (rdev->has_uvd) { 323562306a36Sopenharmony_ci radeon_uvd_suspend(rdev); 323662306a36Sopenharmony_ci uvd_v1_0_fini(rdev); 323762306a36Sopenharmony_ci } 323862306a36Sopenharmony_ci r600_irq_suspend(rdev); 323962306a36Sopenharmony_ci radeon_wb_disable(rdev); 324062306a36Sopenharmony_ci r600_pcie_gart_disable(rdev); 324162306a36Sopenharmony_ci 324262306a36Sopenharmony_ci return 0; 324362306a36Sopenharmony_ci} 324462306a36Sopenharmony_ci 324562306a36Sopenharmony_ci/* Plan is to move initialization in that function and use 324662306a36Sopenharmony_ci * helper function so that radeon_device_init pretty much 324762306a36Sopenharmony_ci * do nothing more than calling asic specific function. This 324862306a36Sopenharmony_ci * should also allow to remove a bunch of callback function 324962306a36Sopenharmony_ci * like vram_info. 325062306a36Sopenharmony_ci */ 325162306a36Sopenharmony_ciint r600_init(struct radeon_device *rdev) 325262306a36Sopenharmony_ci{ 325362306a36Sopenharmony_ci int r; 325462306a36Sopenharmony_ci 325562306a36Sopenharmony_ci r600_debugfs_mc_info_init(rdev); 325662306a36Sopenharmony_ci /* Read BIOS */ 325762306a36Sopenharmony_ci if (!radeon_get_bios(rdev)) { 325862306a36Sopenharmony_ci if (ASIC_IS_AVIVO(rdev)) 325962306a36Sopenharmony_ci return -EINVAL; 326062306a36Sopenharmony_ci } 326162306a36Sopenharmony_ci /* Must be an ATOMBIOS */ 326262306a36Sopenharmony_ci if (!rdev->is_atom_bios) { 326362306a36Sopenharmony_ci dev_err(rdev->dev, "Expecting atombios for R600 GPU\n"); 326462306a36Sopenharmony_ci return -EINVAL; 326562306a36Sopenharmony_ci } 326662306a36Sopenharmony_ci r = radeon_atombios_init(rdev); 326762306a36Sopenharmony_ci if (r) 326862306a36Sopenharmony_ci return r; 326962306a36Sopenharmony_ci /* Post card if necessary */ 327062306a36Sopenharmony_ci if (!radeon_card_posted(rdev)) { 327162306a36Sopenharmony_ci if (!rdev->bios) { 327262306a36Sopenharmony_ci dev_err(rdev->dev, "Card not posted and no BIOS - ignoring\n"); 327362306a36Sopenharmony_ci return -EINVAL; 327462306a36Sopenharmony_ci } 327562306a36Sopenharmony_ci DRM_INFO("GPU not posted. posting now...\n"); 327662306a36Sopenharmony_ci atom_asic_init(rdev->mode_info.atom_context); 327762306a36Sopenharmony_ci } 327862306a36Sopenharmony_ci /* Initialize scratch registers */ 327962306a36Sopenharmony_ci r600_scratch_init(rdev); 328062306a36Sopenharmony_ci /* Initialize surface registers */ 328162306a36Sopenharmony_ci radeon_surface_init(rdev); 328262306a36Sopenharmony_ci /* Initialize clocks */ 328362306a36Sopenharmony_ci radeon_get_clock_info(rdev->ddev); 328462306a36Sopenharmony_ci /* Fence driver */ 328562306a36Sopenharmony_ci radeon_fence_driver_init(rdev); 328662306a36Sopenharmony_ci if (rdev->flags & RADEON_IS_AGP) { 328762306a36Sopenharmony_ci r = radeon_agp_init(rdev); 328862306a36Sopenharmony_ci if (r) 328962306a36Sopenharmony_ci radeon_agp_disable(rdev); 329062306a36Sopenharmony_ci } 329162306a36Sopenharmony_ci r = r600_mc_init(rdev); 329262306a36Sopenharmony_ci if (r) 329362306a36Sopenharmony_ci return r; 329462306a36Sopenharmony_ci /* Memory manager */ 329562306a36Sopenharmony_ci r = radeon_bo_init(rdev); 329662306a36Sopenharmony_ci if (r) 329762306a36Sopenharmony_ci return r; 329862306a36Sopenharmony_ci 329962306a36Sopenharmony_ci if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) { 330062306a36Sopenharmony_ci r = r600_init_microcode(rdev); 330162306a36Sopenharmony_ci if (r) { 330262306a36Sopenharmony_ci DRM_ERROR("Failed to load firmware!\n"); 330362306a36Sopenharmony_ci return r; 330462306a36Sopenharmony_ci } 330562306a36Sopenharmony_ci } 330662306a36Sopenharmony_ci 330762306a36Sopenharmony_ci /* Initialize power management */ 330862306a36Sopenharmony_ci radeon_pm_init(rdev); 330962306a36Sopenharmony_ci 331062306a36Sopenharmony_ci rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ring_obj = NULL; 331162306a36Sopenharmony_ci r600_ring_init(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX], 1024 * 1024); 331262306a36Sopenharmony_ci 331362306a36Sopenharmony_ci r600_uvd_init(rdev); 331462306a36Sopenharmony_ci 331562306a36Sopenharmony_ci rdev->ih.ring_obj = NULL; 331662306a36Sopenharmony_ci r600_ih_ring_init(rdev, 64 * 1024); 331762306a36Sopenharmony_ci 331862306a36Sopenharmony_ci r = r600_pcie_gart_init(rdev); 331962306a36Sopenharmony_ci if (r) 332062306a36Sopenharmony_ci return r; 332162306a36Sopenharmony_ci 332262306a36Sopenharmony_ci rdev->accel_working = true; 332362306a36Sopenharmony_ci r = r600_startup(rdev); 332462306a36Sopenharmony_ci if (r) { 332562306a36Sopenharmony_ci dev_err(rdev->dev, "disabling GPU acceleration\n"); 332662306a36Sopenharmony_ci r600_cp_fini(rdev); 332762306a36Sopenharmony_ci r600_irq_fini(rdev); 332862306a36Sopenharmony_ci radeon_wb_fini(rdev); 332962306a36Sopenharmony_ci radeon_ib_pool_fini(rdev); 333062306a36Sopenharmony_ci radeon_irq_kms_fini(rdev); 333162306a36Sopenharmony_ci r600_pcie_gart_fini(rdev); 333262306a36Sopenharmony_ci rdev->accel_working = false; 333362306a36Sopenharmony_ci } 333462306a36Sopenharmony_ci 333562306a36Sopenharmony_ci return 0; 333662306a36Sopenharmony_ci} 333762306a36Sopenharmony_ci 333862306a36Sopenharmony_civoid r600_fini(struct radeon_device *rdev) 333962306a36Sopenharmony_ci{ 334062306a36Sopenharmony_ci radeon_pm_fini(rdev); 334162306a36Sopenharmony_ci radeon_audio_fini(rdev); 334262306a36Sopenharmony_ci r600_cp_fini(rdev); 334362306a36Sopenharmony_ci r600_irq_fini(rdev); 334462306a36Sopenharmony_ci if (rdev->has_uvd) { 334562306a36Sopenharmony_ci uvd_v1_0_fini(rdev); 334662306a36Sopenharmony_ci radeon_uvd_fini(rdev); 334762306a36Sopenharmony_ci } 334862306a36Sopenharmony_ci radeon_wb_fini(rdev); 334962306a36Sopenharmony_ci radeon_ib_pool_fini(rdev); 335062306a36Sopenharmony_ci radeon_irq_kms_fini(rdev); 335162306a36Sopenharmony_ci r600_pcie_gart_fini(rdev); 335262306a36Sopenharmony_ci r600_vram_scratch_fini(rdev); 335362306a36Sopenharmony_ci radeon_agp_fini(rdev); 335462306a36Sopenharmony_ci radeon_gem_fini(rdev); 335562306a36Sopenharmony_ci radeon_fence_driver_fini(rdev); 335662306a36Sopenharmony_ci radeon_bo_fini(rdev); 335762306a36Sopenharmony_ci radeon_atombios_fini(rdev); 335862306a36Sopenharmony_ci kfree(rdev->bios); 335962306a36Sopenharmony_ci rdev->bios = NULL; 336062306a36Sopenharmony_ci} 336162306a36Sopenharmony_ci 336262306a36Sopenharmony_ci 336362306a36Sopenharmony_ci/* 336462306a36Sopenharmony_ci * CS stuff 336562306a36Sopenharmony_ci */ 336662306a36Sopenharmony_civoid r600_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) 336762306a36Sopenharmony_ci{ 336862306a36Sopenharmony_ci struct radeon_ring *ring = &rdev->ring[ib->ring]; 336962306a36Sopenharmony_ci u32 next_rptr; 337062306a36Sopenharmony_ci 337162306a36Sopenharmony_ci if (ring->rptr_save_reg) { 337262306a36Sopenharmony_ci next_rptr = ring->wptr + 3 + 4; 337362306a36Sopenharmony_ci radeon_ring_write(ring, PACKET3(PACKET3_SET_CONFIG_REG, 1)); 337462306a36Sopenharmony_ci radeon_ring_write(ring, ((ring->rptr_save_reg - 337562306a36Sopenharmony_ci PACKET3_SET_CONFIG_REG_OFFSET) >> 2)); 337662306a36Sopenharmony_ci radeon_ring_write(ring, next_rptr); 337762306a36Sopenharmony_ci } else if (rdev->wb.enabled) { 337862306a36Sopenharmony_ci next_rptr = ring->wptr + 5 + 4; 337962306a36Sopenharmony_ci radeon_ring_write(ring, PACKET3(PACKET3_MEM_WRITE, 3)); 338062306a36Sopenharmony_ci radeon_ring_write(ring, ring->next_rptr_gpu_addr & 0xfffffffc); 338162306a36Sopenharmony_ci radeon_ring_write(ring, (upper_32_bits(ring->next_rptr_gpu_addr) & 0xff) | (1 << 18)); 338262306a36Sopenharmony_ci radeon_ring_write(ring, next_rptr); 338362306a36Sopenharmony_ci radeon_ring_write(ring, 0); 338462306a36Sopenharmony_ci } 338562306a36Sopenharmony_ci 338662306a36Sopenharmony_ci radeon_ring_write(ring, PACKET3(PACKET3_INDIRECT_BUFFER, 2)); 338762306a36Sopenharmony_ci radeon_ring_write(ring, 338862306a36Sopenharmony_ci#ifdef __BIG_ENDIAN 338962306a36Sopenharmony_ci (2 << 0) | 339062306a36Sopenharmony_ci#endif 339162306a36Sopenharmony_ci (ib->gpu_addr & 0xFFFFFFFC)); 339262306a36Sopenharmony_ci radeon_ring_write(ring, upper_32_bits(ib->gpu_addr) & 0xFF); 339362306a36Sopenharmony_ci radeon_ring_write(ring, ib->length_dw); 339462306a36Sopenharmony_ci} 339562306a36Sopenharmony_ci 339662306a36Sopenharmony_ciint r600_ib_test(struct radeon_device *rdev, struct radeon_ring *ring) 339762306a36Sopenharmony_ci{ 339862306a36Sopenharmony_ci struct radeon_ib ib; 339962306a36Sopenharmony_ci uint32_t scratch; 340062306a36Sopenharmony_ci uint32_t tmp = 0; 340162306a36Sopenharmony_ci unsigned i; 340262306a36Sopenharmony_ci int r; 340362306a36Sopenharmony_ci 340462306a36Sopenharmony_ci r = radeon_scratch_get(rdev, &scratch); 340562306a36Sopenharmony_ci if (r) { 340662306a36Sopenharmony_ci DRM_ERROR("radeon: failed to get scratch reg (%d).\n", r); 340762306a36Sopenharmony_ci return r; 340862306a36Sopenharmony_ci } 340962306a36Sopenharmony_ci WREG32(scratch, 0xCAFEDEAD); 341062306a36Sopenharmony_ci r = radeon_ib_get(rdev, ring->idx, &ib, NULL, 256); 341162306a36Sopenharmony_ci if (r) { 341262306a36Sopenharmony_ci DRM_ERROR("radeon: failed to get ib (%d).\n", r); 341362306a36Sopenharmony_ci goto free_scratch; 341462306a36Sopenharmony_ci } 341562306a36Sopenharmony_ci ib.ptr[0] = PACKET3(PACKET3_SET_CONFIG_REG, 1); 341662306a36Sopenharmony_ci ib.ptr[1] = ((scratch - PACKET3_SET_CONFIG_REG_OFFSET) >> 2); 341762306a36Sopenharmony_ci ib.ptr[2] = 0xDEADBEEF; 341862306a36Sopenharmony_ci ib.length_dw = 3; 341962306a36Sopenharmony_ci r = radeon_ib_schedule(rdev, &ib, NULL, false); 342062306a36Sopenharmony_ci if (r) { 342162306a36Sopenharmony_ci DRM_ERROR("radeon: failed to schedule ib (%d).\n", r); 342262306a36Sopenharmony_ci goto free_ib; 342362306a36Sopenharmony_ci } 342462306a36Sopenharmony_ci r = radeon_fence_wait_timeout(ib.fence, false, usecs_to_jiffies( 342562306a36Sopenharmony_ci RADEON_USEC_IB_TEST_TIMEOUT)); 342662306a36Sopenharmony_ci if (r < 0) { 342762306a36Sopenharmony_ci DRM_ERROR("radeon: fence wait failed (%d).\n", r); 342862306a36Sopenharmony_ci goto free_ib; 342962306a36Sopenharmony_ci } else if (r == 0) { 343062306a36Sopenharmony_ci DRM_ERROR("radeon: fence wait timed out.\n"); 343162306a36Sopenharmony_ci r = -ETIMEDOUT; 343262306a36Sopenharmony_ci goto free_ib; 343362306a36Sopenharmony_ci } 343462306a36Sopenharmony_ci r = 0; 343562306a36Sopenharmony_ci for (i = 0; i < rdev->usec_timeout; i++) { 343662306a36Sopenharmony_ci tmp = RREG32(scratch); 343762306a36Sopenharmony_ci if (tmp == 0xDEADBEEF) 343862306a36Sopenharmony_ci break; 343962306a36Sopenharmony_ci udelay(1); 344062306a36Sopenharmony_ci } 344162306a36Sopenharmony_ci if (i < rdev->usec_timeout) { 344262306a36Sopenharmony_ci DRM_INFO("ib test on ring %d succeeded in %u usecs\n", ib.fence->ring, i); 344362306a36Sopenharmony_ci } else { 344462306a36Sopenharmony_ci DRM_ERROR("radeon: ib test failed (scratch(0x%04X)=0x%08X)\n", 344562306a36Sopenharmony_ci scratch, tmp); 344662306a36Sopenharmony_ci r = -EINVAL; 344762306a36Sopenharmony_ci } 344862306a36Sopenharmony_cifree_ib: 344962306a36Sopenharmony_ci radeon_ib_free(rdev, &ib); 345062306a36Sopenharmony_cifree_scratch: 345162306a36Sopenharmony_ci radeon_scratch_free(rdev, scratch); 345262306a36Sopenharmony_ci return r; 345362306a36Sopenharmony_ci} 345462306a36Sopenharmony_ci 345562306a36Sopenharmony_ci/* 345662306a36Sopenharmony_ci * Interrupts 345762306a36Sopenharmony_ci * 345862306a36Sopenharmony_ci * Interrupts use a ring buffer on r6xx/r7xx hardware. It works pretty 345962306a36Sopenharmony_ci * the same as the CP ring buffer, but in reverse. Rather than the CPU 346062306a36Sopenharmony_ci * writing to the ring and the GPU consuming, the GPU writes to the ring 346162306a36Sopenharmony_ci * and host consumes. As the host irq handler processes interrupts, it 346262306a36Sopenharmony_ci * increments the rptr. When the rptr catches up with the wptr, all the 346362306a36Sopenharmony_ci * current interrupts have been processed. 346462306a36Sopenharmony_ci */ 346562306a36Sopenharmony_ci 346662306a36Sopenharmony_civoid r600_ih_ring_init(struct radeon_device *rdev, unsigned ring_size) 346762306a36Sopenharmony_ci{ 346862306a36Sopenharmony_ci u32 rb_bufsz; 346962306a36Sopenharmony_ci 347062306a36Sopenharmony_ci /* Align ring size */ 347162306a36Sopenharmony_ci rb_bufsz = order_base_2(ring_size / 4); 347262306a36Sopenharmony_ci ring_size = (1 << rb_bufsz) * 4; 347362306a36Sopenharmony_ci rdev->ih.ring_size = ring_size; 347462306a36Sopenharmony_ci rdev->ih.ptr_mask = rdev->ih.ring_size - 1; 347562306a36Sopenharmony_ci rdev->ih.rptr = 0; 347662306a36Sopenharmony_ci} 347762306a36Sopenharmony_ci 347862306a36Sopenharmony_ciint r600_ih_ring_alloc(struct radeon_device *rdev) 347962306a36Sopenharmony_ci{ 348062306a36Sopenharmony_ci int r; 348162306a36Sopenharmony_ci 348262306a36Sopenharmony_ci /* Allocate ring buffer */ 348362306a36Sopenharmony_ci if (rdev->ih.ring_obj == NULL) { 348462306a36Sopenharmony_ci r = radeon_bo_create(rdev, rdev->ih.ring_size, 348562306a36Sopenharmony_ci PAGE_SIZE, true, 348662306a36Sopenharmony_ci RADEON_GEM_DOMAIN_GTT, 0, 348762306a36Sopenharmony_ci NULL, NULL, &rdev->ih.ring_obj); 348862306a36Sopenharmony_ci if (r) { 348962306a36Sopenharmony_ci DRM_ERROR("radeon: failed to create ih ring buffer (%d).\n", r); 349062306a36Sopenharmony_ci return r; 349162306a36Sopenharmony_ci } 349262306a36Sopenharmony_ci r = radeon_bo_reserve(rdev->ih.ring_obj, false); 349362306a36Sopenharmony_ci if (unlikely(r != 0)) 349462306a36Sopenharmony_ci return r; 349562306a36Sopenharmony_ci r = radeon_bo_pin(rdev->ih.ring_obj, 349662306a36Sopenharmony_ci RADEON_GEM_DOMAIN_GTT, 349762306a36Sopenharmony_ci &rdev->ih.gpu_addr); 349862306a36Sopenharmony_ci if (r) { 349962306a36Sopenharmony_ci radeon_bo_unreserve(rdev->ih.ring_obj); 350062306a36Sopenharmony_ci DRM_ERROR("radeon: failed to pin ih ring buffer (%d).\n", r); 350162306a36Sopenharmony_ci return r; 350262306a36Sopenharmony_ci } 350362306a36Sopenharmony_ci r = radeon_bo_kmap(rdev->ih.ring_obj, 350462306a36Sopenharmony_ci (void **)&rdev->ih.ring); 350562306a36Sopenharmony_ci radeon_bo_unreserve(rdev->ih.ring_obj); 350662306a36Sopenharmony_ci if (r) { 350762306a36Sopenharmony_ci DRM_ERROR("radeon: failed to map ih ring buffer (%d).\n", r); 350862306a36Sopenharmony_ci return r; 350962306a36Sopenharmony_ci } 351062306a36Sopenharmony_ci } 351162306a36Sopenharmony_ci return 0; 351262306a36Sopenharmony_ci} 351362306a36Sopenharmony_ci 351462306a36Sopenharmony_civoid r600_ih_ring_fini(struct radeon_device *rdev) 351562306a36Sopenharmony_ci{ 351662306a36Sopenharmony_ci int r; 351762306a36Sopenharmony_ci if (rdev->ih.ring_obj) { 351862306a36Sopenharmony_ci r = radeon_bo_reserve(rdev->ih.ring_obj, false); 351962306a36Sopenharmony_ci if (likely(r == 0)) { 352062306a36Sopenharmony_ci radeon_bo_kunmap(rdev->ih.ring_obj); 352162306a36Sopenharmony_ci radeon_bo_unpin(rdev->ih.ring_obj); 352262306a36Sopenharmony_ci radeon_bo_unreserve(rdev->ih.ring_obj); 352362306a36Sopenharmony_ci } 352462306a36Sopenharmony_ci radeon_bo_unref(&rdev->ih.ring_obj); 352562306a36Sopenharmony_ci rdev->ih.ring = NULL; 352662306a36Sopenharmony_ci rdev->ih.ring_obj = NULL; 352762306a36Sopenharmony_ci } 352862306a36Sopenharmony_ci} 352962306a36Sopenharmony_ci 353062306a36Sopenharmony_civoid r600_rlc_stop(struct radeon_device *rdev) 353162306a36Sopenharmony_ci{ 353262306a36Sopenharmony_ci 353362306a36Sopenharmony_ci if ((rdev->family >= CHIP_RV770) && 353462306a36Sopenharmony_ci (rdev->family <= CHIP_RV740)) { 353562306a36Sopenharmony_ci /* r7xx asics need to soft reset RLC before halting */ 353662306a36Sopenharmony_ci WREG32(SRBM_SOFT_RESET, SOFT_RESET_RLC); 353762306a36Sopenharmony_ci RREG32(SRBM_SOFT_RESET); 353862306a36Sopenharmony_ci mdelay(15); 353962306a36Sopenharmony_ci WREG32(SRBM_SOFT_RESET, 0); 354062306a36Sopenharmony_ci RREG32(SRBM_SOFT_RESET); 354162306a36Sopenharmony_ci } 354262306a36Sopenharmony_ci 354362306a36Sopenharmony_ci WREG32(RLC_CNTL, 0); 354462306a36Sopenharmony_ci} 354562306a36Sopenharmony_ci 354662306a36Sopenharmony_cistatic void r600_rlc_start(struct radeon_device *rdev) 354762306a36Sopenharmony_ci{ 354862306a36Sopenharmony_ci WREG32(RLC_CNTL, RLC_ENABLE); 354962306a36Sopenharmony_ci} 355062306a36Sopenharmony_ci 355162306a36Sopenharmony_cistatic int r600_rlc_resume(struct radeon_device *rdev) 355262306a36Sopenharmony_ci{ 355362306a36Sopenharmony_ci u32 i; 355462306a36Sopenharmony_ci const __be32 *fw_data; 355562306a36Sopenharmony_ci 355662306a36Sopenharmony_ci if (!rdev->rlc_fw) 355762306a36Sopenharmony_ci return -EINVAL; 355862306a36Sopenharmony_ci 355962306a36Sopenharmony_ci r600_rlc_stop(rdev); 356062306a36Sopenharmony_ci 356162306a36Sopenharmony_ci WREG32(RLC_HB_CNTL, 0); 356262306a36Sopenharmony_ci 356362306a36Sopenharmony_ci WREG32(RLC_HB_BASE, 0); 356462306a36Sopenharmony_ci WREG32(RLC_HB_RPTR, 0); 356562306a36Sopenharmony_ci WREG32(RLC_HB_WPTR, 0); 356662306a36Sopenharmony_ci WREG32(RLC_HB_WPTR_LSB_ADDR, 0); 356762306a36Sopenharmony_ci WREG32(RLC_HB_WPTR_MSB_ADDR, 0); 356862306a36Sopenharmony_ci WREG32(RLC_MC_CNTL, 0); 356962306a36Sopenharmony_ci WREG32(RLC_UCODE_CNTL, 0); 357062306a36Sopenharmony_ci 357162306a36Sopenharmony_ci fw_data = (const __be32 *)rdev->rlc_fw->data; 357262306a36Sopenharmony_ci if (rdev->family >= CHIP_RV770) { 357362306a36Sopenharmony_ci for (i = 0; i < R700_RLC_UCODE_SIZE; i++) { 357462306a36Sopenharmony_ci WREG32(RLC_UCODE_ADDR, i); 357562306a36Sopenharmony_ci WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++)); 357662306a36Sopenharmony_ci } 357762306a36Sopenharmony_ci } else { 357862306a36Sopenharmony_ci for (i = 0; i < R600_RLC_UCODE_SIZE; i++) { 357962306a36Sopenharmony_ci WREG32(RLC_UCODE_ADDR, i); 358062306a36Sopenharmony_ci WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++)); 358162306a36Sopenharmony_ci } 358262306a36Sopenharmony_ci } 358362306a36Sopenharmony_ci WREG32(RLC_UCODE_ADDR, 0); 358462306a36Sopenharmony_ci 358562306a36Sopenharmony_ci r600_rlc_start(rdev); 358662306a36Sopenharmony_ci 358762306a36Sopenharmony_ci return 0; 358862306a36Sopenharmony_ci} 358962306a36Sopenharmony_ci 359062306a36Sopenharmony_cistatic void r600_enable_interrupts(struct radeon_device *rdev) 359162306a36Sopenharmony_ci{ 359262306a36Sopenharmony_ci u32 ih_cntl = RREG32(IH_CNTL); 359362306a36Sopenharmony_ci u32 ih_rb_cntl = RREG32(IH_RB_CNTL); 359462306a36Sopenharmony_ci 359562306a36Sopenharmony_ci ih_cntl |= ENABLE_INTR; 359662306a36Sopenharmony_ci ih_rb_cntl |= IH_RB_ENABLE; 359762306a36Sopenharmony_ci WREG32(IH_CNTL, ih_cntl); 359862306a36Sopenharmony_ci WREG32(IH_RB_CNTL, ih_rb_cntl); 359962306a36Sopenharmony_ci rdev->ih.enabled = true; 360062306a36Sopenharmony_ci} 360162306a36Sopenharmony_ci 360262306a36Sopenharmony_civoid r600_disable_interrupts(struct radeon_device *rdev) 360362306a36Sopenharmony_ci{ 360462306a36Sopenharmony_ci u32 ih_rb_cntl = RREG32(IH_RB_CNTL); 360562306a36Sopenharmony_ci u32 ih_cntl = RREG32(IH_CNTL); 360662306a36Sopenharmony_ci 360762306a36Sopenharmony_ci ih_rb_cntl &= ~IH_RB_ENABLE; 360862306a36Sopenharmony_ci ih_cntl &= ~ENABLE_INTR; 360962306a36Sopenharmony_ci WREG32(IH_RB_CNTL, ih_rb_cntl); 361062306a36Sopenharmony_ci WREG32(IH_CNTL, ih_cntl); 361162306a36Sopenharmony_ci /* set rptr, wptr to 0 */ 361262306a36Sopenharmony_ci WREG32(IH_RB_RPTR, 0); 361362306a36Sopenharmony_ci WREG32(IH_RB_WPTR, 0); 361462306a36Sopenharmony_ci rdev->ih.enabled = false; 361562306a36Sopenharmony_ci rdev->ih.rptr = 0; 361662306a36Sopenharmony_ci} 361762306a36Sopenharmony_ci 361862306a36Sopenharmony_cistatic void r600_disable_interrupt_state(struct radeon_device *rdev) 361962306a36Sopenharmony_ci{ 362062306a36Sopenharmony_ci u32 tmp; 362162306a36Sopenharmony_ci 362262306a36Sopenharmony_ci WREG32(CP_INT_CNTL, CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE); 362362306a36Sopenharmony_ci tmp = RREG32(DMA_CNTL) & ~TRAP_ENABLE; 362462306a36Sopenharmony_ci WREG32(DMA_CNTL, tmp); 362562306a36Sopenharmony_ci WREG32(GRBM_INT_CNTL, 0); 362662306a36Sopenharmony_ci WREG32(DxMODE_INT_MASK, 0); 362762306a36Sopenharmony_ci WREG32(D1GRPH_INTERRUPT_CONTROL, 0); 362862306a36Sopenharmony_ci WREG32(D2GRPH_INTERRUPT_CONTROL, 0); 362962306a36Sopenharmony_ci if (ASIC_IS_DCE3(rdev)) { 363062306a36Sopenharmony_ci WREG32(DCE3_DACA_AUTODETECT_INT_CONTROL, 0); 363162306a36Sopenharmony_ci WREG32(DCE3_DACB_AUTODETECT_INT_CONTROL, 0); 363262306a36Sopenharmony_ci tmp = RREG32(DC_HPD1_INT_CONTROL) & DC_HPDx_INT_POLARITY; 363362306a36Sopenharmony_ci WREG32(DC_HPD1_INT_CONTROL, tmp); 363462306a36Sopenharmony_ci tmp = RREG32(DC_HPD2_INT_CONTROL) & DC_HPDx_INT_POLARITY; 363562306a36Sopenharmony_ci WREG32(DC_HPD2_INT_CONTROL, tmp); 363662306a36Sopenharmony_ci tmp = RREG32(DC_HPD3_INT_CONTROL) & DC_HPDx_INT_POLARITY; 363762306a36Sopenharmony_ci WREG32(DC_HPD3_INT_CONTROL, tmp); 363862306a36Sopenharmony_ci tmp = RREG32(DC_HPD4_INT_CONTROL) & DC_HPDx_INT_POLARITY; 363962306a36Sopenharmony_ci WREG32(DC_HPD4_INT_CONTROL, tmp); 364062306a36Sopenharmony_ci if (ASIC_IS_DCE32(rdev)) { 364162306a36Sopenharmony_ci tmp = RREG32(DC_HPD5_INT_CONTROL) & DC_HPDx_INT_POLARITY; 364262306a36Sopenharmony_ci WREG32(DC_HPD5_INT_CONTROL, tmp); 364362306a36Sopenharmony_ci tmp = RREG32(DC_HPD6_INT_CONTROL) & DC_HPDx_INT_POLARITY; 364462306a36Sopenharmony_ci WREG32(DC_HPD6_INT_CONTROL, tmp); 364562306a36Sopenharmony_ci tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET0) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; 364662306a36Sopenharmony_ci WREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET0, tmp); 364762306a36Sopenharmony_ci tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET1) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; 364862306a36Sopenharmony_ci WREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET1, tmp); 364962306a36Sopenharmony_ci } else { 365062306a36Sopenharmony_ci tmp = RREG32(HDMI0_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; 365162306a36Sopenharmony_ci WREG32(HDMI0_AUDIO_PACKET_CONTROL, tmp); 365262306a36Sopenharmony_ci tmp = RREG32(DCE3_HDMI1_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; 365362306a36Sopenharmony_ci WREG32(DCE3_HDMI1_AUDIO_PACKET_CONTROL, tmp); 365462306a36Sopenharmony_ci } 365562306a36Sopenharmony_ci } else { 365662306a36Sopenharmony_ci WREG32(DACA_AUTODETECT_INT_CONTROL, 0); 365762306a36Sopenharmony_ci WREG32(DACB_AUTODETECT_INT_CONTROL, 0); 365862306a36Sopenharmony_ci tmp = RREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL) & DC_HOT_PLUG_DETECTx_INT_POLARITY; 365962306a36Sopenharmony_ci WREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL, tmp); 366062306a36Sopenharmony_ci tmp = RREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL) & DC_HOT_PLUG_DETECTx_INT_POLARITY; 366162306a36Sopenharmony_ci WREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL, tmp); 366262306a36Sopenharmony_ci tmp = RREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL) & DC_HOT_PLUG_DETECTx_INT_POLARITY; 366362306a36Sopenharmony_ci WREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL, tmp); 366462306a36Sopenharmony_ci tmp = RREG32(HDMI0_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; 366562306a36Sopenharmony_ci WREG32(HDMI0_AUDIO_PACKET_CONTROL, tmp); 366662306a36Sopenharmony_ci tmp = RREG32(HDMI1_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; 366762306a36Sopenharmony_ci WREG32(HDMI1_AUDIO_PACKET_CONTROL, tmp); 366862306a36Sopenharmony_ci } 366962306a36Sopenharmony_ci} 367062306a36Sopenharmony_ci 367162306a36Sopenharmony_ciint r600_irq_init(struct radeon_device *rdev) 367262306a36Sopenharmony_ci{ 367362306a36Sopenharmony_ci int ret = 0; 367462306a36Sopenharmony_ci int rb_bufsz; 367562306a36Sopenharmony_ci u32 interrupt_cntl, ih_cntl, ih_rb_cntl; 367662306a36Sopenharmony_ci 367762306a36Sopenharmony_ci /* allocate ring */ 367862306a36Sopenharmony_ci ret = r600_ih_ring_alloc(rdev); 367962306a36Sopenharmony_ci if (ret) 368062306a36Sopenharmony_ci return ret; 368162306a36Sopenharmony_ci 368262306a36Sopenharmony_ci /* disable irqs */ 368362306a36Sopenharmony_ci r600_disable_interrupts(rdev); 368462306a36Sopenharmony_ci 368562306a36Sopenharmony_ci /* init rlc */ 368662306a36Sopenharmony_ci if (rdev->family >= CHIP_CEDAR) 368762306a36Sopenharmony_ci ret = evergreen_rlc_resume(rdev); 368862306a36Sopenharmony_ci else 368962306a36Sopenharmony_ci ret = r600_rlc_resume(rdev); 369062306a36Sopenharmony_ci if (ret) { 369162306a36Sopenharmony_ci r600_ih_ring_fini(rdev); 369262306a36Sopenharmony_ci return ret; 369362306a36Sopenharmony_ci } 369462306a36Sopenharmony_ci 369562306a36Sopenharmony_ci /* setup interrupt control */ 369662306a36Sopenharmony_ci /* set dummy read address to dummy page address */ 369762306a36Sopenharmony_ci WREG32(INTERRUPT_CNTL2, rdev->dummy_page.addr >> 8); 369862306a36Sopenharmony_ci interrupt_cntl = RREG32(INTERRUPT_CNTL); 369962306a36Sopenharmony_ci /* IH_DUMMY_RD_OVERRIDE=0 - dummy read disabled with msi, enabled without msi 370062306a36Sopenharmony_ci * IH_DUMMY_RD_OVERRIDE=1 - dummy read controlled by IH_DUMMY_RD_EN 370162306a36Sopenharmony_ci */ 370262306a36Sopenharmony_ci interrupt_cntl &= ~IH_DUMMY_RD_OVERRIDE; 370362306a36Sopenharmony_ci /* IH_REQ_NONSNOOP_EN=1 if ring is in non-cacheable memory, e.g., vram */ 370462306a36Sopenharmony_ci interrupt_cntl &= ~IH_REQ_NONSNOOP_EN; 370562306a36Sopenharmony_ci WREG32(INTERRUPT_CNTL, interrupt_cntl); 370662306a36Sopenharmony_ci 370762306a36Sopenharmony_ci WREG32(IH_RB_BASE, rdev->ih.gpu_addr >> 8); 370862306a36Sopenharmony_ci rb_bufsz = order_base_2(rdev->ih.ring_size / 4); 370962306a36Sopenharmony_ci 371062306a36Sopenharmony_ci ih_rb_cntl = (IH_WPTR_OVERFLOW_ENABLE | 371162306a36Sopenharmony_ci IH_WPTR_OVERFLOW_CLEAR | 371262306a36Sopenharmony_ci (rb_bufsz << 1)); 371362306a36Sopenharmony_ci 371462306a36Sopenharmony_ci if (rdev->wb.enabled) 371562306a36Sopenharmony_ci ih_rb_cntl |= IH_WPTR_WRITEBACK_ENABLE; 371662306a36Sopenharmony_ci 371762306a36Sopenharmony_ci /* set the writeback address whether it's enabled or not */ 371862306a36Sopenharmony_ci WREG32(IH_RB_WPTR_ADDR_LO, (rdev->wb.gpu_addr + R600_WB_IH_WPTR_OFFSET) & 0xFFFFFFFC); 371962306a36Sopenharmony_ci WREG32(IH_RB_WPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + R600_WB_IH_WPTR_OFFSET) & 0xFF); 372062306a36Sopenharmony_ci 372162306a36Sopenharmony_ci WREG32(IH_RB_CNTL, ih_rb_cntl); 372262306a36Sopenharmony_ci 372362306a36Sopenharmony_ci /* set rptr, wptr to 0 */ 372462306a36Sopenharmony_ci WREG32(IH_RB_RPTR, 0); 372562306a36Sopenharmony_ci WREG32(IH_RB_WPTR, 0); 372662306a36Sopenharmony_ci 372762306a36Sopenharmony_ci /* Default settings for IH_CNTL (disabled at first) */ 372862306a36Sopenharmony_ci ih_cntl = MC_WRREQ_CREDIT(0x10) | MC_WR_CLEAN_CNT(0x10); 372962306a36Sopenharmony_ci /* RPTR_REARM only works if msi's are enabled */ 373062306a36Sopenharmony_ci if (rdev->msi_enabled) 373162306a36Sopenharmony_ci ih_cntl |= RPTR_REARM; 373262306a36Sopenharmony_ci WREG32(IH_CNTL, ih_cntl); 373362306a36Sopenharmony_ci 373462306a36Sopenharmony_ci /* force the active interrupt state to all disabled */ 373562306a36Sopenharmony_ci if (rdev->family >= CHIP_CEDAR) 373662306a36Sopenharmony_ci evergreen_disable_interrupt_state(rdev); 373762306a36Sopenharmony_ci else 373862306a36Sopenharmony_ci r600_disable_interrupt_state(rdev); 373962306a36Sopenharmony_ci 374062306a36Sopenharmony_ci /* at this point everything should be setup correctly to enable master */ 374162306a36Sopenharmony_ci pci_set_master(rdev->pdev); 374262306a36Sopenharmony_ci 374362306a36Sopenharmony_ci /* enable irqs */ 374462306a36Sopenharmony_ci r600_enable_interrupts(rdev); 374562306a36Sopenharmony_ci 374662306a36Sopenharmony_ci return ret; 374762306a36Sopenharmony_ci} 374862306a36Sopenharmony_ci 374962306a36Sopenharmony_civoid r600_irq_suspend(struct radeon_device *rdev) 375062306a36Sopenharmony_ci{ 375162306a36Sopenharmony_ci r600_irq_disable(rdev); 375262306a36Sopenharmony_ci r600_rlc_stop(rdev); 375362306a36Sopenharmony_ci} 375462306a36Sopenharmony_ci 375562306a36Sopenharmony_civoid r600_irq_fini(struct radeon_device *rdev) 375662306a36Sopenharmony_ci{ 375762306a36Sopenharmony_ci r600_irq_suspend(rdev); 375862306a36Sopenharmony_ci r600_ih_ring_fini(rdev); 375962306a36Sopenharmony_ci} 376062306a36Sopenharmony_ci 376162306a36Sopenharmony_ciint r600_irq_set(struct radeon_device *rdev) 376262306a36Sopenharmony_ci{ 376362306a36Sopenharmony_ci u32 cp_int_cntl = CNTX_BUSY_INT_ENABLE | CNTX_EMPTY_INT_ENABLE; 376462306a36Sopenharmony_ci u32 mode_int = 0; 376562306a36Sopenharmony_ci u32 hpd1, hpd2, hpd3, hpd4 = 0, hpd5 = 0, hpd6 = 0; 376662306a36Sopenharmony_ci u32 grbm_int_cntl = 0; 376762306a36Sopenharmony_ci u32 hdmi0, hdmi1; 376862306a36Sopenharmony_ci u32 dma_cntl; 376962306a36Sopenharmony_ci u32 thermal_int = 0; 377062306a36Sopenharmony_ci 377162306a36Sopenharmony_ci if (!rdev->irq.installed) { 377262306a36Sopenharmony_ci WARN(1, "Can't enable IRQ/MSI because no handler is installed\n"); 377362306a36Sopenharmony_ci return -EINVAL; 377462306a36Sopenharmony_ci } 377562306a36Sopenharmony_ci /* don't enable anything if the ih is disabled */ 377662306a36Sopenharmony_ci if (!rdev->ih.enabled) { 377762306a36Sopenharmony_ci r600_disable_interrupts(rdev); 377862306a36Sopenharmony_ci /* force the active interrupt state to all disabled */ 377962306a36Sopenharmony_ci r600_disable_interrupt_state(rdev); 378062306a36Sopenharmony_ci return 0; 378162306a36Sopenharmony_ci } 378262306a36Sopenharmony_ci 378362306a36Sopenharmony_ci if (ASIC_IS_DCE3(rdev)) { 378462306a36Sopenharmony_ci hpd1 = RREG32(DC_HPD1_INT_CONTROL) & ~DC_HPDx_INT_EN; 378562306a36Sopenharmony_ci hpd2 = RREG32(DC_HPD2_INT_CONTROL) & ~DC_HPDx_INT_EN; 378662306a36Sopenharmony_ci hpd3 = RREG32(DC_HPD3_INT_CONTROL) & ~DC_HPDx_INT_EN; 378762306a36Sopenharmony_ci hpd4 = RREG32(DC_HPD4_INT_CONTROL) & ~DC_HPDx_INT_EN; 378862306a36Sopenharmony_ci if (ASIC_IS_DCE32(rdev)) { 378962306a36Sopenharmony_ci hpd5 = RREG32(DC_HPD5_INT_CONTROL) & ~DC_HPDx_INT_EN; 379062306a36Sopenharmony_ci hpd6 = RREG32(DC_HPD6_INT_CONTROL) & ~DC_HPDx_INT_EN; 379162306a36Sopenharmony_ci hdmi0 = RREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET0) & ~AFMT_AZ_FORMAT_WTRIG_MASK; 379262306a36Sopenharmony_ci hdmi1 = RREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET1) & ~AFMT_AZ_FORMAT_WTRIG_MASK; 379362306a36Sopenharmony_ci } else { 379462306a36Sopenharmony_ci hdmi0 = RREG32(HDMI0_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; 379562306a36Sopenharmony_ci hdmi1 = RREG32(DCE3_HDMI1_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; 379662306a36Sopenharmony_ci } 379762306a36Sopenharmony_ci } else { 379862306a36Sopenharmony_ci hpd1 = RREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL) & ~DC_HPDx_INT_EN; 379962306a36Sopenharmony_ci hpd2 = RREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL) & ~DC_HPDx_INT_EN; 380062306a36Sopenharmony_ci hpd3 = RREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL) & ~DC_HPDx_INT_EN; 380162306a36Sopenharmony_ci hdmi0 = RREG32(HDMI0_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; 380262306a36Sopenharmony_ci hdmi1 = RREG32(HDMI1_AUDIO_PACKET_CONTROL) & ~HDMI0_AZ_FORMAT_WTRIG_MASK; 380362306a36Sopenharmony_ci } 380462306a36Sopenharmony_ci 380562306a36Sopenharmony_ci dma_cntl = RREG32(DMA_CNTL) & ~TRAP_ENABLE; 380662306a36Sopenharmony_ci 380762306a36Sopenharmony_ci if ((rdev->family > CHIP_R600) && (rdev->family < CHIP_RV770)) { 380862306a36Sopenharmony_ci thermal_int = RREG32(CG_THERMAL_INT) & 380962306a36Sopenharmony_ci ~(THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW); 381062306a36Sopenharmony_ci } else if (rdev->family >= CHIP_RV770) { 381162306a36Sopenharmony_ci thermal_int = RREG32(RV770_CG_THERMAL_INT) & 381262306a36Sopenharmony_ci ~(THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW); 381362306a36Sopenharmony_ci } 381462306a36Sopenharmony_ci if (rdev->irq.dpm_thermal) { 381562306a36Sopenharmony_ci DRM_DEBUG("dpm thermal\n"); 381662306a36Sopenharmony_ci thermal_int |= THERM_INT_MASK_HIGH | THERM_INT_MASK_LOW; 381762306a36Sopenharmony_ci } 381862306a36Sopenharmony_ci 381962306a36Sopenharmony_ci if (atomic_read(&rdev->irq.ring_int[RADEON_RING_TYPE_GFX_INDEX])) { 382062306a36Sopenharmony_ci DRM_DEBUG("r600_irq_set: sw int\n"); 382162306a36Sopenharmony_ci cp_int_cntl |= RB_INT_ENABLE; 382262306a36Sopenharmony_ci cp_int_cntl |= TIME_STAMP_INT_ENABLE; 382362306a36Sopenharmony_ci } 382462306a36Sopenharmony_ci 382562306a36Sopenharmony_ci if (atomic_read(&rdev->irq.ring_int[R600_RING_TYPE_DMA_INDEX])) { 382662306a36Sopenharmony_ci DRM_DEBUG("r600_irq_set: sw int dma\n"); 382762306a36Sopenharmony_ci dma_cntl |= TRAP_ENABLE; 382862306a36Sopenharmony_ci } 382962306a36Sopenharmony_ci 383062306a36Sopenharmony_ci if (rdev->irq.crtc_vblank_int[0] || 383162306a36Sopenharmony_ci atomic_read(&rdev->irq.pflip[0])) { 383262306a36Sopenharmony_ci DRM_DEBUG("r600_irq_set: vblank 0\n"); 383362306a36Sopenharmony_ci mode_int |= D1MODE_VBLANK_INT_MASK; 383462306a36Sopenharmony_ci } 383562306a36Sopenharmony_ci if (rdev->irq.crtc_vblank_int[1] || 383662306a36Sopenharmony_ci atomic_read(&rdev->irq.pflip[1])) { 383762306a36Sopenharmony_ci DRM_DEBUG("r600_irq_set: vblank 1\n"); 383862306a36Sopenharmony_ci mode_int |= D2MODE_VBLANK_INT_MASK; 383962306a36Sopenharmony_ci } 384062306a36Sopenharmony_ci if (rdev->irq.hpd[0]) { 384162306a36Sopenharmony_ci DRM_DEBUG("r600_irq_set: hpd 1\n"); 384262306a36Sopenharmony_ci hpd1 |= DC_HPDx_INT_EN; 384362306a36Sopenharmony_ci } 384462306a36Sopenharmony_ci if (rdev->irq.hpd[1]) { 384562306a36Sopenharmony_ci DRM_DEBUG("r600_irq_set: hpd 2\n"); 384662306a36Sopenharmony_ci hpd2 |= DC_HPDx_INT_EN; 384762306a36Sopenharmony_ci } 384862306a36Sopenharmony_ci if (rdev->irq.hpd[2]) { 384962306a36Sopenharmony_ci DRM_DEBUG("r600_irq_set: hpd 3\n"); 385062306a36Sopenharmony_ci hpd3 |= DC_HPDx_INT_EN; 385162306a36Sopenharmony_ci } 385262306a36Sopenharmony_ci if (rdev->irq.hpd[3]) { 385362306a36Sopenharmony_ci DRM_DEBUG("r600_irq_set: hpd 4\n"); 385462306a36Sopenharmony_ci hpd4 |= DC_HPDx_INT_EN; 385562306a36Sopenharmony_ci } 385662306a36Sopenharmony_ci if (rdev->irq.hpd[4]) { 385762306a36Sopenharmony_ci DRM_DEBUG("r600_irq_set: hpd 5\n"); 385862306a36Sopenharmony_ci hpd5 |= DC_HPDx_INT_EN; 385962306a36Sopenharmony_ci } 386062306a36Sopenharmony_ci if (rdev->irq.hpd[5]) { 386162306a36Sopenharmony_ci DRM_DEBUG("r600_irq_set: hpd 6\n"); 386262306a36Sopenharmony_ci hpd6 |= DC_HPDx_INT_EN; 386362306a36Sopenharmony_ci } 386462306a36Sopenharmony_ci if (rdev->irq.afmt[0]) { 386562306a36Sopenharmony_ci DRM_DEBUG("r600_irq_set: hdmi 0\n"); 386662306a36Sopenharmony_ci hdmi0 |= HDMI0_AZ_FORMAT_WTRIG_MASK; 386762306a36Sopenharmony_ci } 386862306a36Sopenharmony_ci if (rdev->irq.afmt[1]) { 386962306a36Sopenharmony_ci DRM_DEBUG("r600_irq_set: hdmi 0\n"); 387062306a36Sopenharmony_ci hdmi1 |= HDMI0_AZ_FORMAT_WTRIG_MASK; 387162306a36Sopenharmony_ci } 387262306a36Sopenharmony_ci 387362306a36Sopenharmony_ci WREG32(CP_INT_CNTL, cp_int_cntl); 387462306a36Sopenharmony_ci WREG32(DMA_CNTL, dma_cntl); 387562306a36Sopenharmony_ci WREG32(DxMODE_INT_MASK, mode_int); 387662306a36Sopenharmony_ci WREG32(D1GRPH_INTERRUPT_CONTROL, DxGRPH_PFLIP_INT_MASK); 387762306a36Sopenharmony_ci WREG32(D2GRPH_INTERRUPT_CONTROL, DxGRPH_PFLIP_INT_MASK); 387862306a36Sopenharmony_ci WREG32(GRBM_INT_CNTL, grbm_int_cntl); 387962306a36Sopenharmony_ci if (ASIC_IS_DCE3(rdev)) { 388062306a36Sopenharmony_ci WREG32(DC_HPD1_INT_CONTROL, hpd1); 388162306a36Sopenharmony_ci WREG32(DC_HPD2_INT_CONTROL, hpd2); 388262306a36Sopenharmony_ci WREG32(DC_HPD3_INT_CONTROL, hpd3); 388362306a36Sopenharmony_ci WREG32(DC_HPD4_INT_CONTROL, hpd4); 388462306a36Sopenharmony_ci if (ASIC_IS_DCE32(rdev)) { 388562306a36Sopenharmony_ci WREG32(DC_HPD5_INT_CONTROL, hpd5); 388662306a36Sopenharmony_ci WREG32(DC_HPD6_INT_CONTROL, hpd6); 388762306a36Sopenharmony_ci WREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET0, hdmi0); 388862306a36Sopenharmony_ci WREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET1, hdmi1); 388962306a36Sopenharmony_ci } else { 389062306a36Sopenharmony_ci WREG32(HDMI0_AUDIO_PACKET_CONTROL, hdmi0); 389162306a36Sopenharmony_ci WREG32(DCE3_HDMI1_AUDIO_PACKET_CONTROL, hdmi1); 389262306a36Sopenharmony_ci } 389362306a36Sopenharmony_ci } else { 389462306a36Sopenharmony_ci WREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL, hpd1); 389562306a36Sopenharmony_ci WREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL, hpd2); 389662306a36Sopenharmony_ci WREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL, hpd3); 389762306a36Sopenharmony_ci WREG32(HDMI0_AUDIO_PACKET_CONTROL, hdmi0); 389862306a36Sopenharmony_ci WREG32(HDMI1_AUDIO_PACKET_CONTROL, hdmi1); 389962306a36Sopenharmony_ci } 390062306a36Sopenharmony_ci if ((rdev->family > CHIP_R600) && (rdev->family < CHIP_RV770)) { 390162306a36Sopenharmony_ci WREG32(CG_THERMAL_INT, thermal_int); 390262306a36Sopenharmony_ci } else if (rdev->family >= CHIP_RV770) { 390362306a36Sopenharmony_ci WREG32(RV770_CG_THERMAL_INT, thermal_int); 390462306a36Sopenharmony_ci } 390562306a36Sopenharmony_ci 390662306a36Sopenharmony_ci /* posting read */ 390762306a36Sopenharmony_ci RREG32(R_000E50_SRBM_STATUS); 390862306a36Sopenharmony_ci 390962306a36Sopenharmony_ci return 0; 391062306a36Sopenharmony_ci} 391162306a36Sopenharmony_ci 391262306a36Sopenharmony_cistatic void r600_irq_ack(struct radeon_device *rdev) 391362306a36Sopenharmony_ci{ 391462306a36Sopenharmony_ci u32 tmp; 391562306a36Sopenharmony_ci 391662306a36Sopenharmony_ci if (ASIC_IS_DCE3(rdev)) { 391762306a36Sopenharmony_ci rdev->irq.stat_regs.r600.disp_int = RREG32(DCE3_DISP_INTERRUPT_STATUS); 391862306a36Sopenharmony_ci rdev->irq.stat_regs.r600.disp_int_cont = RREG32(DCE3_DISP_INTERRUPT_STATUS_CONTINUE); 391962306a36Sopenharmony_ci rdev->irq.stat_regs.r600.disp_int_cont2 = RREG32(DCE3_DISP_INTERRUPT_STATUS_CONTINUE2); 392062306a36Sopenharmony_ci if (ASIC_IS_DCE32(rdev)) { 392162306a36Sopenharmony_ci rdev->irq.stat_regs.r600.hdmi0_status = RREG32(AFMT_STATUS + DCE3_HDMI_OFFSET0); 392262306a36Sopenharmony_ci rdev->irq.stat_regs.r600.hdmi1_status = RREG32(AFMT_STATUS + DCE3_HDMI_OFFSET1); 392362306a36Sopenharmony_ci } else { 392462306a36Sopenharmony_ci rdev->irq.stat_regs.r600.hdmi0_status = RREG32(HDMI0_STATUS); 392562306a36Sopenharmony_ci rdev->irq.stat_regs.r600.hdmi1_status = RREG32(DCE3_HDMI1_STATUS); 392662306a36Sopenharmony_ci } 392762306a36Sopenharmony_ci } else { 392862306a36Sopenharmony_ci rdev->irq.stat_regs.r600.disp_int = RREG32(DISP_INTERRUPT_STATUS); 392962306a36Sopenharmony_ci rdev->irq.stat_regs.r600.disp_int_cont = RREG32(DISP_INTERRUPT_STATUS_CONTINUE); 393062306a36Sopenharmony_ci rdev->irq.stat_regs.r600.disp_int_cont2 = 0; 393162306a36Sopenharmony_ci rdev->irq.stat_regs.r600.hdmi0_status = RREG32(HDMI0_STATUS); 393262306a36Sopenharmony_ci rdev->irq.stat_regs.r600.hdmi1_status = RREG32(HDMI1_STATUS); 393362306a36Sopenharmony_ci } 393462306a36Sopenharmony_ci rdev->irq.stat_regs.r600.d1grph_int = RREG32(D1GRPH_INTERRUPT_STATUS); 393562306a36Sopenharmony_ci rdev->irq.stat_regs.r600.d2grph_int = RREG32(D2GRPH_INTERRUPT_STATUS); 393662306a36Sopenharmony_ci 393762306a36Sopenharmony_ci if (rdev->irq.stat_regs.r600.d1grph_int & DxGRPH_PFLIP_INT_OCCURRED) 393862306a36Sopenharmony_ci WREG32(D1GRPH_INTERRUPT_STATUS, DxGRPH_PFLIP_INT_CLEAR); 393962306a36Sopenharmony_ci if (rdev->irq.stat_regs.r600.d2grph_int & DxGRPH_PFLIP_INT_OCCURRED) 394062306a36Sopenharmony_ci WREG32(D2GRPH_INTERRUPT_STATUS, DxGRPH_PFLIP_INT_CLEAR); 394162306a36Sopenharmony_ci if (rdev->irq.stat_regs.r600.disp_int & LB_D1_VBLANK_INTERRUPT) 394262306a36Sopenharmony_ci WREG32(D1MODE_VBLANK_STATUS, DxMODE_VBLANK_ACK); 394362306a36Sopenharmony_ci if (rdev->irq.stat_regs.r600.disp_int & LB_D1_VLINE_INTERRUPT) 394462306a36Sopenharmony_ci WREG32(D1MODE_VLINE_STATUS, DxMODE_VLINE_ACK); 394562306a36Sopenharmony_ci if (rdev->irq.stat_regs.r600.disp_int & LB_D2_VBLANK_INTERRUPT) 394662306a36Sopenharmony_ci WREG32(D2MODE_VBLANK_STATUS, DxMODE_VBLANK_ACK); 394762306a36Sopenharmony_ci if (rdev->irq.stat_regs.r600.disp_int & LB_D2_VLINE_INTERRUPT) 394862306a36Sopenharmony_ci WREG32(D2MODE_VLINE_STATUS, DxMODE_VLINE_ACK); 394962306a36Sopenharmony_ci if (rdev->irq.stat_regs.r600.disp_int & DC_HPD1_INTERRUPT) { 395062306a36Sopenharmony_ci if (ASIC_IS_DCE3(rdev)) { 395162306a36Sopenharmony_ci tmp = RREG32(DC_HPD1_INT_CONTROL); 395262306a36Sopenharmony_ci tmp |= DC_HPDx_INT_ACK; 395362306a36Sopenharmony_ci WREG32(DC_HPD1_INT_CONTROL, tmp); 395462306a36Sopenharmony_ci } else { 395562306a36Sopenharmony_ci tmp = RREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL); 395662306a36Sopenharmony_ci tmp |= DC_HPDx_INT_ACK; 395762306a36Sopenharmony_ci WREG32(DC_HOT_PLUG_DETECT1_INT_CONTROL, tmp); 395862306a36Sopenharmony_ci } 395962306a36Sopenharmony_ci } 396062306a36Sopenharmony_ci if (rdev->irq.stat_regs.r600.disp_int & DC_HPD2_INTERRUPT) { 396162306a36Sopenharmony_ci if (ASIC_IS_DCE3(rdev)) { 396262306a36Sopenharmony_ci tmp = RREG32(DC_HPD2_INT_CONTROL); 396362306a36Sopenharmony_ci tmp |= DC_HPDx_INT_ACK; 396462306a36Sopenharmony_ci WREG32(DC_HPD2_INT_CONTROL, tmp); 396562306a36Sopenharmony_ci } else { 396662306a36Sopenharmony_ci tmp = RREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL); 396762306a36Sopenharmony_ci tmp |= DC_HPDx_INT_ACK; 396862306a36Sopenharmony_ci WREG32(DC_HOT_PLUG_DETECT2_INT_CONTROL, tmp); 396962306a36Sopenharmony_ci } 397062306a36Sopenharmony_ci } 397162306a36Sopenharmony_ci if (rdev->irq.stat_regs.r600.disp_int_cont & DC_HPD3_INTERRUPT) { 397262306a36Sopenharmony_ci if (ASIC_IS_DCE3(rdev)) { 397362306a36Sopenharmony_ci tmp = RREG32(DC_HPD3_INT_CONTROL); 397462306a36Sopenharmony_ci tmp |= DC_HPDx_INT_ACK; 397562306a36Sopenharmony_ci WREG32(DC_HPD3_INT_CONTROL, tmp); 397662306a36Sopenharmony_ci } else { 397762306a36Sopenharmony_ci tmp = RREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL); 397862306a36Sopenharmony_ci tmp |= DC_HPDx_INT_ACK; 397962306a36Sopenharmony_ci WREG32(DC_HOT_PLUG_DETECT3_INT_CONTROL, tmp); 398062306a36Sopenharmony_ci } 398162306a36Sopenharmony_ci } 398262306a36Sopenharmony_ci if (rdev->irq.stat_regs.r600.disp_int_cont & DC_HPD4_INTERRUPT) { 398362306a36Sopenharmony_ci tmp = RREG32(DC_HPD4_INT_CONTROL); 398462306a36Sopenharmony_ci tmp |= DC_HPDx_INT_ACK; 398562306a36Sopenharmony_ci WREG32(DC_HPD4_INT_CONTROL, tmp); 398662306a36Sopenharmony_ci } 398762306a36Sopenharmony_ci if (ASIC_IS_DCE32(rdev)) { 398862306a36Sopenharmony_ci if (rdev->irq.stat_regs.r600.disp_int_cont2 & DC_HPD5_INTERRUPT) { 398962306a36Sopenharmony_ci tmp = RREG32(DC_HPD5_INT_CONTROL); 399062306a36Sopenharmony_ci tmp |= DC_HPDx_INT_ACK; 399162306a36Sopenharmony_ci WREG32(DC_HPD5_INT_CONTROL, tmp); 399262306a36Sopenharmony_ci } 399362306a36Sopenharmony_ci if (rdev->irq.stat_regs.r600.disp_int_cont2 & DC_HPD6_INTERRUPT) { 399462306a36Sopenharmony_ci tmp = RREG32(DC_HPD6_INT_CONTROL); 399562306a36Sopenharmony_ci tmp |= DC_HPDx_INT_ACK; 399662306a36Sopenharmony_ci WREG32(DC_HPD6_INT_CONTROL, tmp); 399762306a36Sopenharmony_ci } 399862306a36Sopenharmony_ci if (rdev->irq.stat_regs.r600.hdmi0_status & AFMT_AZ_FORMAT_WTRIG) { 399962306a36Sopenharmony_ci tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET0); 400062306a36Sopenharmony_ci tmp |= AFMT_AZ_FORMAT_WTRIG_ACK; 400162306a36Sopenharmony_ci WREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET0, tmp); 400262306a36Sopenharmony_ci } 400362306a36Sopenharmony_ci if (rdev->irq.stat_regs.r600.hdmi1_status & AFMT_AZ_FORMAT_WTRIG) { 400462306a36Sopenharmony_ci tmp = RREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET1); 400562306a36Sopenharmony_ci tmp |= AFMT_AZ_FORMAT_WTRIG_ACK; 400662306a36Sopenharmony_ci WREG32(AFMT_AUDIO_PACKET_CONTROL + DCE3_HDMI_OFFSET1, tmp); 400762306a36Sopenharmony_ci } 400862306a36Sopenharmony_ci } else { 400962306a36Sopenharmony_ci if (rdev->irq.stat_regs.r600.hdmi0_status & HDMI0_AZ_FORMAT_WTRIG) { 401062306a36Sopenharmony_ci tmp = RREG32(HDMI0_AUDIO_PACKET_CONTROL); 401162306a36Sopenharmony_ci tmp |= HDMI0_AZ_FORMAT_WTRIG_ACK; 401262306a36Sopenharmony_ci WREG32(HDMI0_AUDIO_PACKET_CONTROL, tmp); 401362306a36Sopenharmony_ci } 401462306a36Sopenharmony_ci if (rdev->irq.stat_regs.r600.hdmi1_status & HDMI0_AZ_FORMAT_WTRIG) { 401562306a36Sopenharmony_ci if (ASIC_IS_DCE3(rdev)) { 401662306a36Sopenharmony_ci tmp = RREG32(DCE3_HDMI1_AUDIO_PACKET_CONTROL); 401762306a36Sopenharmony_ci tmp |= HDMI0_AZ_FORMAT_WTRIG_ACK; 401862306a36Sopenharmony_ci WREG32(DCE3_HDMI1_AUDIO_PACKET_CONTROL, tmp); 401962306a36Sopenharmony_ci } else { 402062306a36Sopenharmony_ci tmp = RREG32(HDMI1_AUDIO_PACKET_CONTROL); 402162306a36Sopenharmony_ci tmp |= HDMI0_AZ_FORMAT_WTRIG_ACK; 402262306a36Sopenharmony_ci WREG32(HDMI1_AUDIO_PACKET_CONTROL, tmp); 402362306a36Sopenharmony_ci } 402462306a36Sopenharmony_ci } 402562306a36Sopenharmony_ci } 402662306a36Sopenharmony_ci} 402762306a36Sopenharmony_ci 402862306a36Sopenharmony_civoid r600_irq_disable(struct radeon_device *rdev) 402962306a36Sopenharmony_ci{ 403062306a36Sopenharmony_ci r600_disable_interrupts(rdev); 403162306a36Sopenharmony_ci /* Wait and acknowledge irq */ 403262306a36Sopenharmony_ci mdelay(1); 403362306a36Sopenharmony_ci r600_irq_ack(rdev); 403462306a36Sopenharmony_ci r600_disable_interrupt_state(rdev); 403562306a36Sopenharmony_ci} 403662306a36Sopenharmony_ci 403762306a36Sopenharmony_cistatic u32 r600_get_ih_wptr(struct radeon_device *rdev) 403862306a36Sopenharmony_ci{ 403962306a36Sopenharmony_ci u32 wptr, tmp; 404062306a36Sopenharmony_ci 404162306a36Sopenharmony_ci if (rdev->wb.enabled) 404262306a36Sopenharmony_ci wptr = le32_to_cpu(rdev->wb.wb[R600_WB_IH_WPTR_OFFSET/4]); 404362306a36Sopenharmony_ci else 404462306a36Sopenharmony_ci wptr = RREG32(IH_RB_WPTR); 404562306a36Sopenharmony_ci 404662306a36Sopenharmony_ci if (wptr & RB_OVERFLOW) { 404762306a36Sopenharmony_ci wptr &= ~RB_OVERFLOW; 404862306a36Sopenharmony_ci /* When a ring buffer overflow happen start parsing interrupt 404962306a36Sopenharmony_ci * from the last not overwritten vector (wptr + 16). Hopefully 405062306a36Sopenharmony_ci * this should allow us to catchup. 405162306a36Sopenharmony_ci */ 405262306a36Sopenharmony_ci dev_warn(rdev->dev, "IH ring buffer overflow (0x%08X, 0x%08X, 0x%08X)\n", 405362306a36Sopenharmony_ci wptr, rdev->ih.rptr, (wptr + 16) & rdev->ih.ptr_mask); 405462306a36Sopenharmony_ci rdev->ih.rptr = (wptr + 16) & rdev->ih.ptr_mask; 405562306a36Sopenharmony_ci tmp = RREG32(IH_RB_CNTL); 405662306a36Sopenharmony_ci tmp |= IH_WPTR_OVERFLOW_CLEAR; 405762306a36Sopenharmony_ci WREG32(IH_RB_CNTL, tmp); 405862306a36Sopenharmony_ci } 405962306a36Sopenharmony_ci return (wptr & rdev->ih.ptr_mask); 406062306a36Sopenharmony_ci} 406162306a36Sopenharmony_ci 406262306a36Sopenharmony_ci/* r600 IV Ring 406362306a36Sopenharmony_ci * Each IV ring entry is 128 bits: 406462306a36Sopenharmony_ci * [7:0] - interrupt source id 406562306a36Sopenharmony_ci * [31:8] - reserved 406662306a36Sopenharmony_ci * [59:32] - interrupt source data 406762306a36Sopenharmony_ci * [127:60] - reserved 406862306a36Sopenharmony_ci * 406962306a36Sopenharmony_ci * The basic interrupt vector entries 407062306a36Sopenharmony_ci * are decoded as follows: 407162306a36Sopenharmony_ci * src_id src_data description 407262306a36Sopenharmony_ci * 1 0 D1 Vblank 407362306a36Sopenharmony_ci * 1 1 D1 Vline 407462306a36Sopenharmony_ci * 5 0 D2 Vblank 407562306a36Sopenharmony_ci * 5 1 D2 Vline 407662306a36Sopenharmony_ci * 19 0 FP Hot plug detection A 407762306a36Sopenharmony_ci * 19 1 FP Hot plug detection B 407862306a36Sopenharmony_ci * 19 2 DAC A auto-detection 407962306a36Sopenharmony_ci * 19 3 DAC B auto-detection 408062306a36Sopenharmony_ci * 21 4 HDMI block A 408162306a36Sopenharmony_ci * 21 5 HDMI block B 408262306a36Sopenharmony_ci * 176 - CP_INT RB 408362306a36Sopenharmony_ci * 177 - CP_INT IB1 408462306a36Sopenharmony_ci * 178 - CP_INT IB2 408562306a36Sopenharmony_ci * 181 - EOP Interrupt 408662306a36Sopenharmony_ci * 233 - GUI Idle 408762306a36Sopenharmony_ci * 408862306a36Sopenharmony_ci * Note, these are based on r600 and may need to be 408962306a36Sopenharmony_ci * adjusted or added to on newer asics 409062306a36Sopenharmony_ci */ 409162306a36Sopenharmony_ci 409262306a36Sopenharmony_ciint r600_irq_process(struct radeon_device *rdev) 409362306a36Sopenharmony_ci{ 409462306a36Sopenharmony_ci u32 wptr; 409562306a36Sopenharmony_ci u32 rptr; 409662306a36Sopenharmony_ci u32 src_id, src_data; 409762306a36Sopenharmony_ci u32 ring_index; 409862306a36Sopenharmony_ci bool queue_hotplug = false; 409962306a36Sopenharmony_ci bool queue_hdmi = false; 410062306a36Sopenharmony_ci bool queue_thermal = false; 410162306a36Sopenharmony_ci 410262306a36Sopenharmony_ci if (!rdev->ih.enabled || rdev->shutdown) 410362306a36Sopenharmony_ci return IRQ_NONE; 410462306a36Sopenharmony_ci 410562306a36Sopenharmony_ci /* No MSIs, need a dummy read to flush PCI DMAs */ 410662306a36Sopenharmony_ci if (!rdev->msi_enabled) 410762306a36Sopenharmony_ci RREG32(IH_RB_WPTR); 410862306a36Sopenharmony_ci 410962306a36Sopenharmony_ci wptr = r600_get_ih_wptr(rdev); 411062306a36Sopenharmony_ci 411162306a36Sopenharmony_cirestart_ih: 411262306a36Sopenharmony_ci /* is somebody else already processing irqs? */ 411362306a36Sopenharmony_ci if (atomic_xchg(&rdev->ih.lock, 1)) 411462306a36Sopenharmony_ci return IRQ_NONE; 411562306a36Sopenharmony_ci 411662306a36Sopenharmony_ci rptr = rdev->ih.rptr; 411762306a36Sopenharmony_ci DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr); 411862306a36Sopenharmony_ci 411962306a36Sopenharmony_ci /* Order reading of wptr vs. reading of IH ring data */ 412062306a36Sopenharmony_ci rmb(); 412162306a36Sopenharmony_ci 412262306a36Sopenharmony_ci /* display interrupts */ 412362306a36Sopenharmony_ci r600_irq_ack(rdev); 412462306a36Sopenharmony_ci 412562306a36Sopenharmony_ci while (rptr != wptr) { 412662306a36Sopenharmony_ci /* wptr/rptr are in bytes! */ 412762306a36Sopenharmony_ci ring_index = rptr / 4; 412862306a36Sopenharmony_ci src_id = le32_to_cpu(rdev->ih.ring[ring_index]) & 0xff; 412962306a36Sopenharmony_ci src_data = le32_to_cpu(rdev->ih.ring[ring_index + 1]) & 0xfffffff; 413062306a36Sopenharmony_ci 413162306a36Sopenharmony_ci switch (src_id) { 413262306a36Sopenharmony_ci case 1: /* D1 vblank/vline */ 413362306a36Sopenharmony_ci switch (src_data) { 413462306a36Sopenharmony_ci case 0: /* D1 vblank */ 413562306a36Sopenharmony_ci if (!(rdev->irq.stat_regs.r600.disp_int & LB_D1_VBLANK_INTERRUPT)) 413662306a36Sopenharmony_ci DRM_DEBUG("IH: D1 vblank - IH event w/o asserted irq bit?\n"); 413762306a36Sopenharmony_ci 413862306a36Sopenharmony_ci if (rdev->irq.crtc_vblank_int[0]) { 413962306a36Sopenharmony_ci drm_handle_vblank(rdev->ddev, 0); 414062306a36Sopenharmony_ci rdev->pm.vblank_sync = true; 414162306a36Sopenharmony_ci wake_up(&rdev->irq.vblank_queue); 414262306a36Sopenharmony_ci } 414362306a36Sopenharmony_ci if (atomic_read(&rdev->irq.pflip[0])) 414462306a36Sopenharmony_ci radeon_crtc_handle_vblank(rdev, 0); 414562306a36Sopenharmony_ci rdev->irq.stat_regs.r600.disp_int &= ~LB_D1_VBLANK_INTERRUPT; 414662306a36Sopenharmony_ci DRM_DEBUG("IH: D1 vblank\n"); 414762306a36Sopenharmony_ci 414862306a36Sopenharmony_ci break; 414962306a36Sopenharmony_ci case 1: /* D1 vline */ 415062306a36Sopenharmony_ci if (!(rdev->irq.stat_regs.r600.disp_int & LB_D1_VLINE_INTERRUPT)) 415162306a36Sopenharmony_ci DRM_DEBUG("IH: D1 vline - IH event w/o asserted irq bit?\n"); 415262306a36Sopenharmony_ci 415362306a36Sopenharmony_ci rdev->irq.stat_regs.r600.disp_int &= ~LB_D1_VLINE_INTERRUPT; 415462306a36Sopenharmony_ci DRM_DEBUG("IH: D1 vline\n"); 415562306a36Sopenharmony_ci 415662306a36Sopenharmony_ci break; 415762306a36Sopenharmony_ci default: 415862306a36Sopenharmony_ci DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); 415962306a36Sopenharmony_ci break; 416062306a36Sopenharmony_ci } 416162306a36Sopenharmony_ci break; 416262306a36Sopenharmony_ci case 5: /* D2 vblank/vline */ 416362306a36Sopenharmony_ci switch (src_data) { 416462306a36Sopenharmony_ci case 0: /* D2 vblank */ 416562306a36Sopenharmony_ci if (!(rdev->irq.stat_regs.r600.disp_int & LB_D2_VBLANK_INTERRUPT)) 416662306a36Sopenharmony_ci DRM_DEBUG("IH: D2 vblank - IH event w/o asserted irq bit?\n"); 416762306a36Sopenharmony_ci 416862306a36Sopenharmony_ci if (rdev->irq.crtc_vblank_int[1]) { 416962306a36Sopenharmony_ci drm_handle_vblank(rdev->ddev, 1); 417062306a36Sopenharmony_ci rdev->pm.vblank_sync = true; 417162306a36Sopenharmony_ci wake_up(&rdev->irq.vblank_queue); 417262306a36Sopenharmony_ci } 417362306a36Sopenharmony_ci if (atomic_read(&rdev->irq.pflip[1])) 417462306a36Sopenharmony_ci radeon_crtc_handle_vblank(rdev, 1); 417562306a36Sopenharmony_ci rdev->irq.stat_regs.r600.disp_int &= ~LB_D2_VBLANK_INTERRUPT; 417662306a36Sopenharmony_ci DRM_DEBUG("IH: D2 vblank\n"); 417762306a36Sopenharmony_ci 417862306a36Sopenharmony_ci break; 417962306a36Sopenharmony_ci case 1: /* D1 vline */ 418062306a36Sopenharmony_ci if (!(rdev->irq.stat_regs.r600.disp_int & LB_D2_VLINE_INTERRUPT)) 418162306a36Sopenharmony_ci DRM_DEBUG("IH: D2 vline - IH event w/o asserted irq bit?\n"); 418262306a36Sopenharmony_ci 418362306a36Sopenharmony_ci rdev->irq.stat_regs.r600.disp_int &= ~LB_D2_VLINE_INTERRUPT; 418462306a36Sopenharmony_ci DRM_DEBUG("IH: D2 vline\n"); 418562306a36Sopenharmony_ci 418662306a36Sopenharmony_ci break; 418762306a36Sopenharmony_ci default: 418862306a36Sopenharmony_ci DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); 418962306a36Sopenharmony_ci break; 419062306a36Sopenharmony_ci } 419162306a36Sopenharmony_ci break; 419262306a36Sopenharmony_ci case 9: /* D1 pflip */ 419362306a36Sopenharmony_ci DRM_DEBUG("IH: D1 flip\n"); 419462306a36Sopenharmony_ci if (radeon_use_pflipirq > 0) 419562306a36Sopenharmony_ci radeon_crtc_handle_flip(rdev, 0); 419662306a36Sopenharmony_ci break; 419762306a36Sopenharmony_ci case 11: /* D2 pflip */ 419862306a36Sopenharmony_ci DRM_DEBUG("IH: D2 flip\n"); 419962306a36Sopenharmony_ci if (radeon_use_pflipirq > 0) 420062306a36Sopenharmony_ci radeon_crtc_handle_flip(rdev, 1); 420162306a36Sopenharmony_ci break; 420262306a36Sopenharmony_ci case 19: /* HPD/DAC hotplug */ 420362306a36Sopenharmony_ci switch (src_data) { 420462306a36Sopenharmony_ci case 0: 420562306a36Sopenharmony_ci if (!(rdev->irq.stat_regs.r600.disp_int & DC_HPD1_INTERRUPT)) 420662306a36Sopenharmony_ci DRM_DEBUG("IH: HPD1 - IH event w/o asserted irq bit?\n"); 420762306a36Sopenharmony_ci 420862306a36Sopenharmony_ci rdev->irq.stat_regs.r600.disp_int &= ~DC_HPD1_INTERRUPT; 420962306a36Sopenharmony_ci queue_hotplug = true; 421062306a36Sopenharmony_ci DRM_DEBUG("IH: HPD1\n"); 421162306a36Sopenharmony_ci break; 421262306a36Sopenharmony_ci case 1: 421362306a36Sopenharmony_ci if (!(rdev->irq.stat_regs.r600.disp_int & DC_HPD2_INTERRUPT)) 421462306a36Sopenharmony_ci DRM_DEBUG("IH: HPD2 - IH event w/o asserted irq bit?\n"); 421562306a36Sopenharmony_ci 421662306a36Sopenharmony_ci rdev->irq.stat_regs.r600.disp_int &= ~DC_HPD2_INTERRUPT; 421762306a36Sopenharmony_ci queue_hotplug = true; 421862306a36Sopenharmony_ci DRM_DEBUG("IH: HPD2\n"); 421962306a36Sopenharmony_ci break; 422062306a36Sopenharmony_ci case 4: 422162306a36Sopenharmony_ci if (!(rdev->irq.stat_regs.r600.disp_int_cont & DC_HPD3_INTERRUPT)) 422262306a36Sopenharmony_ci DRM_DEBUG("IH: HPD3 - IH event w/o asserted irq bit?\n"); 422362306a36Sopenharmony_ci 422462306a36Sopenharmony_ci rdev->irq.stat_regs.r600.disp_int_cont &= ~DC_HPD3_INTERRUPT; 422562306a36Sopenharmony_ci queue_hotplug = true; 422662306a36Sopenharmony_ci DRM_DEBUG("IH: HPD3\n"); 422762306a36Sopenharmony_ci break; 422862306a36Sopenharmony_ci case 5: 422962306a36Sopenharmony_ci if (!(rdev->irq.stat_regs.r600.disp_int_cont & DC_HPD4_INTERRUPT)) 423062306a36Sopenharmony_ci DRM_DEBUG("IH: HPD4 - IH event w/o asserted irq bit?\n"); 423162306a36Sopenharmony_ci 423262306a36Sopenharmony_ci rdev->irq.stat_regs.r600.disp_int_cont &= ~DC_HPD4_INTERRUPT; 423362306a36Sopenharmony_ci queue_hotplug = true; 423462306a36Sopenharmony_ci DRM_DEBUG("IH: HPD4\n"); 423562306a36Sopenharmony_ci break; 423662306a36Sopenharmony_ci case 10: 423762306a36Sopenharmony_ci if (!(rdev->irq.stat_regs.r600.disp_int_cont2 & DC_HPD5_INTERRUPT)) 423862306a36Sopenharmony_ci DRM_DEBUG("IH: HPD5 - IH event w/o asserted irq bit?\n"); 423962306a36Sopenharmony_ci 424062306a36Sopenharmony_ci rdev->irq.stat_regs.r600.disp_int_cont2 &= ~DC_HPD5_INTERRUPT; 424162306a36Sopenharmony_ci queue_hotplug = true; 424262306a36Sopenharmony_ci DRM_DEBUG("IH: HPD5\n"); 424362306a36Sopenharmony_ci break; 424462306a36Sopenharmony_ci case 12: 424562306a36Sopenharmony_ci if (!(rdev->irq.stat_regs.r600.disp_int_cont2 & DC_HPD6_INTERRUPT)) 424662306a36Sopenharmony_ci DRM_DEBUG("IH: HPD6 - IH event w/o asserted irq bit?\n"); 424762306a36Sopenharmony_ci 424862306a36Sopenharmony_ci rdev->irq.stat_regs.r600.disp_int_cont2 &= ~DC_HPD6_INTERRUPT; 424962306a36Sopenharmony_ci queue_hotplug = true; 425062306a36Sopenharmony_ci DRM_DEBUG("IH: HPD6\n"); 425162306a36Sopenharmony_ci 425262306a36Sopenharmony_ci break; 425362306a36Sopenharmony_ci default: 425462306a36Sopenharmony_ci DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); 425562306a36Sopenharmony_ci break; 425662306a36Sopenharmony_ci } 425762306a36Sopenharmony_ci break; 425862306a36Sopenharmony_ci case 21: /* hdmi */ 425962306a36Sopenharmony_ci switch (src_data) { 426062306a36Sopenharmony_ci case 4: 426162306a36Sopenharmony_ci if (!(rdev->irq.stat_regs.r600.hdmi0_status & HDMI0_AZ_FORMAT_WTRIG)) 426262306a36Sopenharmony_ci DRM_DEBUG("IH: HDMI0 - IH event w/o asserted irq bit?\n"); 426362306a36Sopenharmony_ci 426462306a36Sopenharmony_ci rdev->irq.stat_regs.r600.hdmi0_status &= ~HDMI0_AZ_FORMAT_WTRIG; 426562306a36Sopenharmony_ci queue_hdmi = true; 426662306a36Sopenharmony_ci DRM_DEBUG("IH: HDMI0\n"); 426762306a36Sopenharmony_ci 426862306a36Sopenharmony_ci break; 426962306a36Sopenharmony_ci case 5: 427062306a36Sopenharmony_ci if (!(rdev->irq.stat_regs.r600.hdmi1_status & HDMI0_AZ_FORMAT_WTRIG)) 427162306a36Sopenharmony_ci DRM_DEBUG("IH: HDMI1 - IH event w/o asserted irq bit?\n"); 427262306a36Sopenharmony_ci 427362306a36Sopenharmony_ci rdev->irq.stat_regs.r600.hdmi1_status &= ~HDMI0_AZ_FORMAT_WTRIG; 427462306a36Sopenharmony_ci queue_hdmi = true; 427562306a36Sopenharmony_ci DRM_DEBUG("IH: HDMI1\n"); 427662306a36Sopenharmony_ci 427762306a36Sopenharmony_ci break; 427862306a36Sopenharmony_ci default: 427962306a36Sopenharmony_ci DRM_ERROR("Unhandled interrupt: %d %d\n", src_id, src_data); 428062306a36Sopenharmony_ci break; 428162306a36Sopenharmony_ci } 428262306a36Sopenharmony_ci break; 428362306a36Sopenharmony_ci case 124: /* UVD */ 428462306a36Sopenharmony_ci DRM_DEBUG("IH: UVD int: 0x%08x\n", src_data); 428562306a36Sopenharmony_ci radeon_fence_process(rdev, R600_RING_TYPE_UVD_INDEX); 428662306a36Sopenharmony_ci break; 428762306a36Sopenharmony_ci case 176: /* CP_INT in ring buffer */ 428862306a36Sopenharmony_ci case 177: /* CP_INT in IB1 */ 428962306a36Sopenharmony_ci case 178: /* CP_INT in IB2 */ 429062306a36Sopenharmony_ci DRM_DEBUG("IH: CP int: 0x%08x\n", src_data); 429162306a36Sopenharmony_ci radeon_fence_process(rdev, RADEON_RING_TYPE_GFX_INDEX); 429262306a36Sopenharmony_ci break; 429362306a36Sopenharmony_ci case 181: /* CP EOP event */ 429462306a36Sopenharmony_ci DRM_DEBUG("IH: CP EOP\n"); 429562306a36Sopenharmony_ci radeon_fence_process(rdev, RADEON_RING_TYPE_GFX_INDEX); 429662306a36Sopenharmony_ci break; 429762306a36Sopenharmony_ci case 224: /* DMA trap event */ 429862306a36Sopenharmony_ci DRM_DEBUG("IH: DMA trap\n"); 429962306a36Sopenharmony_ci radeon_fence_process(rdev, R600_RING_TYPE_DMA_INDEX); 430062306a36Sopenharmony_ci break; 430162306a36Sopenharmony_ci case 230: /* thermal low to high */ 430262306a36Sopenharmony_ci DRM_DEBUG("IH: thermal low to high\n"); 430362306a36Sopenharmony_ci rdev->pm.dpm.thermal.high_to_low = false; 430462306a36Sopenharmony_ci queue_thermal = true; 430562306a36Sopenharmony_ci break; 430662306a36Sopenharmony_ci case 231: /* thermal high to low */ 430762306a36Sopenharmony_ci DRM_DEBUG("IH: thermal high to low\n"); 430862306a36Sopenharmony_ci rdev->pm.dpm.thermal.high_to_low = true; 430962306a36Sopenharmony_ci queue_thermal = true; 431062306a36Sopenharmony_ci break; 431162306a36Sopenharmony_ci case 233: /* GUI IDLE */ 431262306a36Sopenharmony_ci DRM_DEBUG("IH: GUI idle\n"); 431362306a36Sopenharmony_ci break; 431462306a36Sopenharmony_ci default: 431562306a36Sopenharmony_ci DRM_DEBUG("Unhandled interrupt: %d %d\n", src_id, src_data); 431662306a36Sopenharmony_ci break; 431762306a36Sopenharmony_ci } 431862306a36Sopenharmony_ci 431962306a36Sopenharmony_ci /* wptr/rptr are in bytes! */ 432062306a36Sopenharmony_ci rptr += 16; 432162306a36Sopenharmony_ci rptr &= rdev->ih.ptr_mask; 432262306a36Sopenharmony_ci WREG32(IH_RB_RPTR, rptr); 432362306a36Sopenharmony_ci } 432462306a36Sopenharmony_ci if (queue_hotplug) 432562306a36Sopenharmony_ci schedule_delayed_work(&rdev->hotplug_work, 0); 432662306a36Sopenharmony_ci if (queue_hdmi) 432762306a36Sopenharmony_ci schedule_work(&rdev->audio_work); 432862306a36Sopenharmony_ci if (queue_thermal && rdev->pm.dpm_enabled) 432962306a36Sopenharmony_ci schedule_work(&rdev->pm.dpm.thermal.work); 433062306a36Sopenharmony_ci rdev->ih.rptr = rptr; 433162306a36Sopenharmony_ci atomic_set(&rdev->ih.lock, 0); 433262306a36Sopenharmony_ci 433362306a36Sopenharmony_ci /* make sure wptr hasn't changed while processing */ 433462306a36Sopenharmony_ci wptr = r600_get_ih_wptr(rdev); 433562306a36Sopenharmony_ci if (wptr != rptr) 433662306a36Sopenharmony_ci goto restart_ih; 433762306a36Sopenharmony_ci 433862306a36Sopenharmony_ci return IRQ_HANDLED; 433962306a36Sopenharmony_ci} 434062306a36Sopenharmony_ci 434162306a36Sopenharmony_ci/* 434262306a36Sopenharmony_ci * Debugfs info 434362306a36Sopenharmony_ci */ 434462306a36Sopenharmony_ci#if defined(CONFIG_DEBUG_FS) 434562306a36Sopenharmony_ci 434662306a36Sopenharmony_cistatic int r600_debugfs_mc_info_show(struct seq_file *m, void *unused) 434762306a36Sopenharmony_ci{ 434862306a36Sopenharmony_ci struct radeon_device *rdev = m->private; 434962306a36Sopenharmony_ci 435062306a36Sopenharmony_ci DREG32_SYS(m, rdev, R_000E50_SRBM_STATUS); 435162306a36Sopenharmony_ci DREG32_SYS(m, rdev, VM_L2_STATUS); 435262306a36Sopenharmony_ci return 0; 435362306a36Sopenharmony_ci} 435462306a36Sopenharmony_ci 435562306a36Sopenharmony_ciDEFINE_SHOW_ATTRIBUTE(r600_debugfs_mc_info); 435662306a36Sopenharmony_ci#endif 435762306a36Sopenharmony_ci 435862306a36Sopenharmony_cistatic void r600_debugfs_mc_info_init(struct radeon_device *rdev) 435962306a36Sopenharmony_ci{ 436062306a36Sopenharmony_ci#if defined(CONFIG_DEBUG_FS) 436162306a36Sopenharmony_ci struct dentry *root = rdev->ddev->primary->debugfs_root; 436262306a36Sopenharmony_ci 436362306a36Sopenharmony_ci debugfs_create_file("r600_mc_info", 0444, root, rdev, 436462306a36Sopenharmony_ci &r600_debugfs_mc_info_fops); 436562306a36Sopenharmony_ci 436662306a36Sopenharmony_ci#endif 436762306a36Sopenharmony_ci} 436862306a36Sopenharmony_ci 436962306a36Sopenharmony_ci/** 437062306a36Sopenharmony_ci * r600_mmio_hdp_flush - flush Host Data Path cache via MMIO 437162306a36Sopenharmony_ci * @rdev: radeon device structure 437262306a36Sopenharmony_ci * 437362306a36Sopenharmony_ci * Some R6XX/R7XX don't seem to take into account HDP flushes performed 437462306a36Sopenharmony_ci * through the ring buffer. This leads to corruption in rendering, see 437562306a36Sopenharmony_ci * http://bugzilla.kernel.org/show_bug.cgi?id=15186 . To avoid this, we 437662306a36Sopenharmony_ci * directly perform the HDP flush by writing the register through MMIO. 437762306a36Sopenharmony_ci */ 437862306a36Sopenharmony_civoid r600_mmio_hdp_flush(struct radeon_device *rdev) 437962306a36Sopenharmony_ci{ 438062306a36Sopenharmony_ci /* r7xx hw bug. write to HDP_DEBUG1 followed by fb read 438162306a36Sopenharmony_ci * rather than write to HDP_REG_COHERENCY_FLUSH_CNTL. 438262306a36Sopenharmony_ci * This seems to cause problems on some AGP cards. Just use the old 438362306a36Sopenharmony_ci * method for them. 438462306a36Sopenharmony_ci */ 438562306a36Sopenharmony_ci if ((rdev->family >= CHIP_RV770) && (rdev->family <= CHIP_RV740) && 438662306a36Sopenharmony_ci rdev->vram_scratch.ptr && !(rdev->flags & RADEON_IS_AGP)) { 438762306a36Sopenharmony_ci void __iomem *ptr = (void *)rdev->vram_scratch.ptr; 438862306a36Sopenharmony_ci 438962306a36Sopenharmony_ci WREG32(HDP_DEBUG1, 0); 439062306a36Sopenharmony_ci readl((void __iomem *)ptr); 439162306a36Sopenharmony_ci } else 439262306a36Sopenharmony_ci WREG32(R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1); 439362306a36Sopenharmony_ci} 439462306a36Sopenharmony_ci 439562306a36Sopenharmony_civoid r600_set_pcie_lanes(struct radeon_device *rdev, int lanes) 439662306a36Sopenharmony_ci{ 439762306a36Sopenharmony_ci u32 link_width_cntl, mask; 439862306a36Sopenharmony_ci 439962306a36Sopenharmony_ci if (rdev->flags & RADEON_IS_IGP) 440062306a36Sopenharmony_ci return; 440162306a36Sopenharmony_ci 440262306a36Sopenharmony_ci if (!(rdev->flags & RADEON_IS_PCIE)) 440362306a36Sopenharmony_ci return; 440462306a36Sopenharmony_ci 440562306a36Sopenharmony_ci /* x2 cards have a special sequence */ 440662306a36Sopenharmony_ci if (ASIC_IS_X2(rdev)) 440762306a36Sopenharmony_ci return; 440862306a36Sopenharmony_ci 440962306a36Sopenharmony_ci radeon_gui_idle(rdev); 441062306a36Sopenharmony_ci 441162306a36Sopenharmony_ci switch (lanes) { 441262306a36Sopenharmony_ci case 0: 441362306a36Sopenharmony_ci mask = RADEON_PCIE_LC_LINK_WIDTH_X0; 441462306a36Sopenharmony_ci break; 441562306a36Sopenharmony_ci case 1: 441662306a36Sopenharmony_ci mask = RADEON_PCIE_LC_LINK_WIDTH_X1; 441762306a36Sopenharmony_ci break; 441862306a36Sopenharmony_ci case 2: 441962306a36Sopenharmony_ci mask = RADEON_PCIE_LC_LINK_WIDTH_X2; 442062306a36Sopenharmony_ci break; 442162306a36Sopenharmony_ci case 4: 442262306a36Sopenharmony_ci mask = RADEON_PCIE_LC_LINK_WIDTH_X4; 442362306a36Sopenharmony_ci break; 442462306a36Sopenharmony_ci case 8: 442562306a36Sopenharmony_ci mask = RADEON_PCIE_LC_LINK_WIDTH_X8; 442662306a36Sopenharmony_ci break; 442762306a36Sopenharmony_ci case 12: 442862306a36Sopenharmony_ci /* not actually supported */ 442962306a36Sopenharmony_ci mask = RADEON_PCIE_LC_LINK_WIDTH_X12; 443062306a36Sopenharmony_ci break; 443162306a36Sopenharmony_ci case 16: 443262306a36Sopenharmony_ci mask = RADEON_PCIE_LC_LINK_WIDTH_X16; 443362306a36Sopenharmony_ci break; 443462306a36Sopenharmony_ci default: 443562306a36Sopenharmony_ci DRM_ERROR("invalid pcie lane request: %d\n", lanes); 443662306a36Sopenharmony_ci return; 443762306a36Sopenharmony_ci } 443862306a36Sopenharmony_ci 443962306a36Sopenharmony_ci link_width_cntl = RREG32_PCIE_PORT(RADEON_PCIE_LC_LINK_WIDTH_CNTL); 444062306a36Sopenharmony_ci link_width_cntl &= ~RADEON_PCIE_LC_LINK_WIDTH_MASK; 444162306a36Sopenharmony_ci link_width_cntl |= mask << RADEON_PCIE_LC_LINK_WIDTH_SHIFT; 444262306a36Sopenharmony_ci link_width_cntl |= (RADEON_PCIE_LC_RECONFIG_NOW | 444362306a36Sopenharmony_ci R600_PCIE_LC_RECONFIG_ARC_MISSING_ESCAPE); 444462306a36Sopenharmony_ci 444562306a36Sopenharmony_ci WREG32_PCIE_PORT(RADEON_PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl); 444662306a36Sopenharmony_ci} 444762306a36Sopenharmony_ci 444862306a36Sopenharmony_ciint r600_get_pcie_lanes(struct radeon_device *rdev) 444962306a36Sopenharmony_ci{ 445062306a36Sopenharmony_ci u32 link_width_cntl; 445162306a36Sopenharmony_ci 445262306a36Sopenharmony_ci if (rdev->flags & RADEON_IS_IGP) 445362306a36Sopenharmony_ci return 0; 445462306a36Sopenharmony_ci 445562306a36Sopenharmony_ci if (!(rdev->flags & RADEON_IS_PCIE)) 445662306a36Sopenharmony_ci return 0; 445762306a36Sopenharmony_ci 445862306a36Sopenharmony_ci /* x2 cards have a special sequence */ 445962306a36Sopenharmony_ci if (ASIC_IS_X2(rdev)) 446062306a36Sopenharmony_ci return 0; 446162306a36Sopenharmony_ci 446262306a36Sopenharmony_ci radeon_gui_idle(rdev); 446362306a36Sopenharmony_ci 446462306a36Sopenharmony_ci link_width_cntl = RREG32_PCIE_PORT(RADEON_PCIE_LC_LINK_WIDTH_CNTL); 446562306a36Sopenharmony_ci 446662306a36Sopenharmony_ci switch ((link_width_cntl & RADEON_PCIE_LC_LINK_WIDTH_RD_MASK) >> RADEON_PCIE_LC_LINK_WIDTH_RD_SHIFT) { 446762306a36Sopenharmony_ci case RADEON_PCIE_LC_LINK_WIDTH_X1: 446862306a36Sopenharmony_ci return 1; 446962306a36Sopenharmony_ci case RADEON_PCIE_LC_LINK_WIDTH_X2: 447062306a36Sopenharmony_ci return 2; 447162306a36Sopenharmony_ci case RADEON_PCIE_LC_LINK_WIDTH_X4: 447262306a36Sopenharmony_ci return 4; 447362306a36Sopenharmony_ci case RADEON_PCIE_LC_LINK_WIDTH_X8: 447462306a36Sopenharmony_ci return 8; 447562306a36Sopenharmony_ci case RADEON_PCIE_LC_LINK_WIDTH_X12: 447662306a36Sopenharmony_ci /* not actually supported */ 447762306a36Sopenharmony_ci return 12; 447862306a36Sopenharmony_ci case RADEON_PCIE_LC_LINK_WIDTH_X0: 447962306a36Sopenharmony_ci case RADEON_PCIE_LC_LINK_WIDTH_X16: 448062306a36Sopenharmony_ci default: 448162306a36Sopenharmony_ci return 16; 448262306a36Sopenharmony_ci } 448362306a36Sopenharmony_ci} 448462306a36Sopenharmony_ci 448562306a36Sopenharmony_cistatic void r600_pcie_gen2_enable(struct radeon_device *rdev) 448662306a36Sopenharmony_ci{ 448762306a36Sopenharmony_ci u32 link_width_cntl, lanes, speed_cntl, training_cntl, tmp; 448862306a36Sopenharmony_ci u16 link_cntl2; 448962306a36Sopenharmony_ci 449062306a36Sopenharmony_ci if (radeon_pcie_gen2 == 0) 449162306a36Sopenharmony_ci return; 449262306a36Sopenharmony_ci 449362306a36Sopenharmony_ci if (rdev->flags & RADEON_IS_IGP) 449462306a36Sopenharmony_ci return; 449562306a36Sopenharmony_ci 449662306a36Sopenharmony_ci if (!(rdev->flags & RADEON_IS_PCIE)) 449762306a36Sopenharmony_ci return; 449862306a36Sopenharmony_ci 449962306a36Sopenharmony_ci /* x2 cards have a special sequence */ 450062306a36Sopenharmony_ci if (ASIC_IS_X2(rdev)) 450162306a36Sopenharmony_ci return; 450262306a36Sopenharmony_ci 450362306a36Sopenharmony_ci /* only RV6xx+ chips are supported */ 450462306a36Sopenharmony_ci if (rdev->family <= CHIP_R600) 450562306a36Sopenharmony_ci return; 450662306a36Sopenharmony_ci 450762306a36Sopenharmony_ci if ((rdev->pdev->bus->max_bus_speed != PCIE_SPEED_5_0GT) && 450862306a36Sopenharmony_ci (rdev->pdev->bus->max_bus_speed != PCIE_SPEED_8_0GT)) 450962306a36Sopenharmony_ci return; 451062306a36Sopenharmony_ci 451162306a36Sopenharmony_ci speed_cntl = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL); 451262306a36Sopenharmony_ci if (speed_cntl & LC_CURRENT_DATA_RATE) { 451362306a36Sopenharmony_ci DRM_INFO("PCIE gen 2 link speeds already enabled\n"); 451462306a36Sopenharmony_ci return; 451562306a36Sopenharmony_ci } 451662306a36Sopenharmony_ci 451762306a36Sopenharmony_ci DRM_INFO("enabling PCIE gen 2 link speeds, disable with radeon.pcie_gen2=0\n"); 451862306a36Sopenharmony_ci 451962306a36Sopenharmony_ci /* 55 nm r6xx asics */ 452062306a36Sopenharmony_ci if ((rdev->family == CHIP_RV670) || 452162306a36Sopenharmony_ci (rdev->family == CHIP_RV620) || 452262306a36Sopenharmony_ci (rdev->family == CHIP_RV635)) { 452362306a36Sopenharmony_ci /* advertise upconfig capability */ 452462306a36Sopenharmony_ci link_width_cntl = RREG32_PCIE_PORT(PCIE_LC_LINK_WIDTH_CNTL); 452562306a36Sopenharmony_ci link_width_cntl &= ~LC_UPCONFIGURE_DIS; 452662306a36Sopenharmony_ci WREG32_PCIE_PORT(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl); 452762306a36Sopenharmony_ci link_width_cntl = RREG32_PCIE_PORT(PCIE_LC_LINK_WIDTH_CNTL); 452862306a36Sopenharmony_ci if (link_width_cntl & LC_RENEGOTIATION_SUPPORT) { 452962306a36Sopenharmony_ci lanes = (link_width_cntl & LC_LINK_WIDTH_RD_MASK) >> LC_LINK_WIDTH_RD_SHIFT; 453062306a36Sopenharmony_ci link_width_cntl &= ~(LC_LINK_WIDTH_MASK | 453162306a36Sopenharmony_ci LC_RECONFIG_ARC_MISSING_ESCAPE); 453262306a36Sopenharmony_ci link_width_cntl |= lanes | LC_RECONFIG_NOW | LC_RENEGOTIATE_EN; 453362306a36Sopenharmony_ci WREG32_PCIE_PORT(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl); 453462306a36Sopenharmony_ci } else { 453562306a36Sopenharmony_ci link_width_cntl |= LC_UPCONFIGURE_DIS; 453662306a36Sopenharmony_ci WREG32_PCIE_PORT(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl); 453762306a36Sopenharmony_ci } 453862306a36Sopenharmony_ci } 453962306a36Sopenharmony_ci 454062306a36Sopenharmony_ci speed_cntl = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL); 454162306a36Sopenharmony_ci if ((speed_cntl & LC_OTHER_SIDE_EVER_SENT_GEN2) && 454262306a36Sopenharmony_ci (speed_cntl & LC_OTHER_SIDE_SUPPORTS_GEN2)) { 454362306a36Sopenharmony_ci 454462306a36Sopenharmony_ci /* 55 nm r6xx asics */ 454562306a36Sopenharmony_ci if ((rdev->family == CHIP_RV670) || 454662306a36Sopenharmony_ci (rdev->family == CHIP_RV620) || 454762306a36Sopenharmony_ci (rdev->family == CHIP_RV635)) { 454862306a36Sopenharmony_ci WREG32(MM_CFGREGS_CNTL, 0x8); 454962306a36Sopenharmony_ci link_cntl2 = RREG32(0x4088); 455062306a36Sopenharmony_ci WREG32(MM_CFGREGS_CNTL, 0); 455162306a36Sopenharmony_ci /* not supported yet */ 455262306a36Sopenharmony_ci if (link_cntl2 & SELECTABLE_DEEMPHASIS) 455362306a36Sopenharmony_ci return; 455462306a36Sopenharmony_ci } 455562306a36Sopenharmony_ci 455662306a36Sopenharmony_ci speed_cntl &= ~LC_SPEED_CHANGE_ATTEMPTS_ALLOWED_MASK; 455762306a36Sopenharmony_ci speed_cntl |= (0x3 << LC_SPEED_CHANGE_ATTEMPTS_ALLOWED_SHIFT); 455862306a36Sopenharmony_ci speed_cntl &= ~LC_VOLTAGE_TIMER_SEL_MASK; 455962306a36Sopenharmony_ci speed_cntl &= ~LC_FORCE_DIS_HW_SPEED_CHANGE; 456062306a36Sopenharmony_ci speed_cntl |= LC_FORCE_EN_HW_SPEED_CHANGE; 456162306a36Sopenharmony_ci WREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL, speed_cntl); 456262306a36Sopenharmony_ci 456362306a36Sopenharmony_ci tmp = RREG32(0x541c); 456462306a36Sopenharmony_ci WREG32(0x541c, tmp | 0x8); 456562306a36Sopenharmony_ci WREG32(MM_CFGREGS_CNTL, MM_WR_TO_CFG_EN); 456662306a36Sopenharmony_ci link_cntl2 = RREG16(0x4088); 456762306a36Sopenharmony_ci link_cntl2 &= ~TARGET_LINK_SPEED_MASK; 456862306a36Sopenharmony_ci link_cntl2 |= 0x2; 456962306a36Sopenharmony_ci WREG16(0x4088, link_cntl2); 457062306a36Sopenharmony_ci WREG32(MM_CFGREGS_CNTL, 0); 457162306a36Sopenharmony_ci 457262306a36Sopenharmony_ci if ((rdev->family == CHIP_RV670) || 457362306a36Sopenharmony_ci (rdev->family == CHIP_RV620) || 457462306a36Sopenharmony_ci (rdev->family == CHIP_RV635)) { 457562306a36Sopenharmony_ci training_cntl = RREG32_PCIE_PORT(PCIE_LC_TRAINING_CNTL); 457662306a36Sopenharmony_ci training_cntl &= ~LC_POINT_7_PLUS_EN; 457762306a36Sopenharmony_ci WREG32_PCIE_PORT(PCIE_LC_TRAINING_CNTL, training_cntl); 457862306a36Sopenharmony_ci } else { 457962306a36Sopenharmony_ci speed_cntl = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL); 458062306a36Sopenharmony_ci speed_cntl &= ~LC_TARGET_LINK_SPEED_OVERRIDE_EN; 458162306a36Sopenharmony_ci WREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL, speed_cntl); 458262306a36Sopenharmony_ci } 458362306a36Sopenharmony_ci 458462306a36Sopenharmony_ci speed_cntl = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL); 458562306a36Sopenharmony_ci speed_cntl |= LC_GEN2_EN_STRAP; 458662306a36Sopenharmony_ci WREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL, speed_cntl); 458762306a36Sopenharmony_ci 458862306a36Sopenharmony_ci } else { 458962306a36Sopenharmony_ci link_width_cntl = RREG32_PCIE_PORT(PCIE_LC_LINK_WIDTH_CNTL); 459062306a36Sopenharmony_ci /* XXX: only disable it if gen1 bridge vendor == 0x111d or 0x1106 */ 459162306a36Sopenharmony_ci if (1) 459262306a36Sopenharmony_ci link_width_cntl |= LC_UPCONFIGURE_DIS; 459362306a36Sopenharmony_ci else 459462306a36Sopenharmony_ci link_width_cntl &= ~LC_UPCONFIGURE_DIS; 459562306a36Sopenharmony_ci WREG32_PCIE_PORT(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl); 459662306a36Sopenharmony_ci } 459762306a36Sopenharmony_ci} 459862306a36Sopenharmony_ci 459962306a36Sopenharmony_ci/** 460062306a36Sopenharmony_ci * r600_get_gpu_clock_counter - return GPU clock counter snapshot 460162306a36Sopenharmony_ci * 460262306a36Sopenharmony_ci * @rdev: radeon_device pointer 460362306a36Sopenharmony_ci * 460462306a36Sopenharmony_ci * Fetches a GPU clock counter snapshot (R6xx-cayman). 460562306a36Sopenharmony_ci * Returns the 64 bit clock counter snapshot. 460662306a36Sopenharmony_ci */ 460762306a36Sopenharmony_ciuint64_t r600_get_gpu_clock_counter(struct radeon_device *rdev) 460862306a36Sopenharmony_ci{ 460962306a36Sopenharmony_ci uint64_t clock; 461062306a36Sopenharmony_ci 461162306a36Sopenharmony_ci mutex_lock(&rdev->gpu_clock_mutex); 461262306a36Sopenharmony_ci WREG32(RLC_CAPTURE_GPU_CLOCK_COUNT, 1); 461362306a36Sopenharmony_ci clock = (uint64_t)RREG32(RLC_GPU_CLOCK_COUNT_LSB) | 461462306a36Sopenharmony_ci ((uint64_t)RREG32(RLC_GPU_CLOCK_COUNT_MSB) << 32ULL); 461562306a36Sopenharmony_ci mutex_unlock(&rdev->gpu_clock_mutex); 461662306a36Sopenharmony_ci return clock; 461762306a36Sopenharmony_ci} 4618