diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/rv770.c')
| -rw-r--r-- | drivers/gpu/drm/radeon/rv770.c | 1540 | 
1 files changed, 1177 insertions, 363 deletions
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index 245374e2b77..da8703d8d45 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c @@ -28,10 +28,10 @@  #include <linux/firmware.h>  #include <linux/platform_device.h>  #include <linux/slab.h> -#include "drmP.h" +#include <drm/drmP.h>  #include "radeon.h"  #include "radeon_asic.h" -#include "radeon_drm.h" +#include <drm/radeon_drm.h>  #include "rv770d.h"  #include "atom.h"  #include "avivod.h" @@ -41,20 +41,829 @@  static void rv770_gpu_init(struct radeon_device *rdev);  void rv770_fini(struct radeon_device *rdev); +static void rv770_pcie_gen2_enable(struct radeon_device *rdev); +int evergreen_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk); + +int rv770_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk) +{ +	unsigned fb_div = 0, vclk_div = 0, dclk_div = 0; +	int r; + +	/* RV740 uses evergreen uvd clk programming */ +	if (rdev->family == CHIP_RV740) +		return evergreen_set_uvd_clocks(rdev, vclk, dclk); + +	/* bypass vclk and dclk with bclk */ +	WREG32_P(CG_UPLL_FUNC_CNTL_2, +		 VCLK_SRC_SEL(1) | DCLK_SRC_SEL(1), +		 ~(VCLK_SRC_SEL_MASK | DCLK_SRC_SEL_MASK)); + +	if (!vclk || !dclk) { +		/* keep the Bypass mode, put PLL to sleep */ +		WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_SLEEP_MASK, ~UPLL_SLEEP_MASK); +		return 0; +	} + +	r = radeon_uvd_calc_upll_dividers(rdev, vclk, dclk, 50000, 160000, +					  43663, 0x03FFFFFE, 1, 30, ~0, +					  &fb_div, &vclk_div, &dclk_div); +	if (r) +		return r; + +	fb_div |= 1; +	vclk_div -= 1; +	dclk_div -= 1; + +	/* set UPLL_FB_DIV to 0x50000 */ +	WREG32_P(CG_UPLL_FUNC_CNTL_3, UPLL_FB_DIV(0x50000), ~UPLL_FB_DIV_MASK); + +	/* deassert UPLL_RESET and UPLL_SLEEP */ +	WREG32_P(CG_UPLL_FUNC_CNTL, 0, ~(UPLL_RESET_MASK | UPLL_SLEEP_MASK)); + +	/* assert BYPASS EN and FB_DIV[0] <- ??? why? */ +	WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_BYPASS_EN_MASK, ~UPLL_BYPASS_EN_MASK); +	WREG32_P(CG_UPLL_FUNC_CNTL_3, UPLL_FB_DIV(1), ~UPLL_FB_DIV(1)); + +	r = radeon_uvd_send_upll_ctlreq(rdev, CG_UPLL_FUNC_CNTL); +	if (r) +		return r; + +	/* assert PLL_RESET */ +	WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_RESET_MASK, ~UPLL_RESET_MASK); + +	/* set the required FB_DIV, REF_DIV, Post divder values */ +	WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_REF_DIV(1), ~UPLL_REF_DIV_MASK); +	WREG32_P(CG_UPLL_FUNC_CNTL_2, +		 UPLL_SW_HILEN(vclk_div >> 1) | +		 UPLL_SW_LOLEN((vclk_div >> 1) + (vclk_div & 1)) | +		 UPLL_SW_HILEN2(dclk_div >> 1) | +		 UPLL_SW_LOLEN2((dclk_div >> 1) + (dclk_div & 1)), +		 ~UPLL_SW_MASK); + +	WREG32_P(CG_UPLL_FUNC_CNTL_3, UPLL_FB_DIV(fb_div), +		 ~UPLL_FB_DIV_MASK); + +	/* give the PLL some time to settle */ +	mdelay(15); + +	/* deassert PLL_RESET */ +	WREG32_P(CG_UPLL_FUNC_CNTL, 0, ~UPLL_RESET_MASK); + +	mdelay(15); + +	/* deassert BYPASS EN and FB_DIV[0] <- ??? why? */ +	WREG32_P(CG_UPLL_FUNC_CNTL, 0, ~UPLL_BYPASS_EN_MASK); +	WREG32_P(CG_UPLL_FUNC_CNTL_3, 0, ~UPLL_FB_DIV(1)); + +	r = radeon_uvd_send_upll_ctlreq(rdev, CG_UPLL_FUNC_CNTL); +	if (r) +		return r; + +	/* switch VCLK and DCLK selection */ +	WREG32_P(CG_UPLL_FUNC_CNTL_2, +		 VCLK_SRC_SEL(2) | DCLK_SRC_SEL(2), +		 ~(VCLK_SRC_SEL_MASK | DCLK_SRC_SEL_MASK)); + +	mdelay(100); + +	return 0; +} + +static const u32 r7xx_golden_registers[] = +{ +	0x8d00, 0xffffffff, 0x0e0e0074, +	0x8d04, 0xffffffff, 0x013a2b34, +	0x9508, 0xffffffff, 0x00000002, +	0x8b20, 0xffffffff, 0, +	0x88c4, 0xffffffff, 0x000000c2, +	0x28350, 0xffffffff, 0, +	0x9058, 0xffffffff, 0x0fffc40f, +	0x240c, 0xffffffff, 0x00000380, +	0x733c, 0xffffffff, 0x00000002, +	0x2650, 0x00040000, 0, +	0x20bc, 0x00040000, 0, +	0x7300, 0xffffffff, 0x001000f0 +}; + +static const u32 r7xx_golden_dyn_gpr_registers[] = +{ +	0x8db0, 0xffffffff, 0x98989898, +	0x8db4, 0xffffffff, 0x98989898, +	0x8db8, 0xffffffff, 0x98989898, +	0x8dbc, 0xffffffff, 0x98989898, +	0x8dc0, 0xffffffff, 0x98989898, +	0x8dc4, 0xffffffff, 0x98989898, +	0x8dc8, 0xffffffff, 0x98989898, +	0x8dcc, 0xffffffff, 0x98989898, +	0x88c4, 0xffffffff, 0x00000082 +}; + +static const u32 rv770_golden_registers[] = +{ +	0x562c, 0xffffffff, 0, +	0x3f90, 0xffffffff, 0, +	0x9148, 0xffffffff, 0, +	0x3f94, 0xffffffff, 0, +	0x914c, 0xffffffff, 0, +	0x9698, 0x18000000, 0x18000000 +}; + +static const u32 rv770ce_golden_registers[] = +{ +	0x562c, 0xffffffff, 0, +	0x3f90, 0xffffffff, 0x00cc0000, +	0x9148, 0xffffffff, 0x00cc0000, +	0x3f94, 0xffffffff, 0x00cc0000, +	0x914c, 0xffffffff, 0x00cc0000, +	0x9b7c, 0xffffffff, 0x00fa0000, +	0x3f8c, 0xffffffff, 0x00fa0000, +	0x9698, 0x18000000, 0x18000000 +}; + +static const u32 rv770_mgcg_init[] = +{ +	0x8bcc, 0xffffffff, 0x130300f9, +	0x5448, 0xffffffff, 0x100, +	0x55e4, 0xffffffff, 0x100, +	0x160c, 0xffffffff, 0x100, +	0x5644, 0xffffffff, 0x100, +	0xc164, 0xffffffff, 0x100, +	0x8a18, 0xffffffff, 0x100, +	0x897c, 0xffffffff, 0x8000100, +	0x8b28, 0xffffffff, 0x3c000100, +	0x9144, 0xffffffff, 0x100, +	0x9a1c, 0xffffffff, 0x10000, +	0x9a50, 0xffffffff, 0x100, +	0x9a1c, 0xffffffff, 0x10001, +	0x9a50, 0xffffffff, 0x100, +	0x9a1c, 0xffffffff, 0x10002, +	0x9a50, 0xffffffff, 0x100, +	0x9a1c, 0xffffffff, 0x10003, +	0x9a50, 0xffffffff, 0x100, +	0x9a1c, 0xffffffff, 0x0, +	0x9870, 0xffffffff, 0x100, +	0x8d58, 0xffffffff, 0x100, +	0x9500, 0xffffffff, 0x0, +	0x9510, 0xffffffff, 0x100, +	0x9500, 0xffffffff, 0x1, +	0x9510, 0xffffffff, 0x100, +	0x9500, 0xffffffff, 0x2, +	0x9510, 0xffffffff, 0x100, +	0x9500, 0xffffffff, 0x3, +	0x9510, 0xffffffff, 0x100, +	0x9500, 0xffffffff, 0x4, +	0x9510, 0xffffffff, 0x100, +	0x9500, 0xffffffff, 0x5, +	0x9510, 0xffffffff, 0x100, +	0x9500, 0xffffffff, 0x6, +	0x9510, 0xffffffff, 0x100, +	0x9500, 0xffffffff, 0x7, +	0x9510, 0xffffffff, 0x100, +	0x9500, 0xffffffff, 0x8, +	0x9510, 0xffffffff, 0x100, +	0x9500, 0xffffffff, 0x9, +	0x9510, 0xffffffff, 0x100, +	0x9500, 0xffffffff, 0x8000, +	0x9490, 0xffffffff, 0x0, +	0x949c, 0xffffffff, 0x100, +	0x9490, 0xffffffff, 0x1, +	0x949c, 0xffffffff, 0x100, +	0x9490, 0xffffffff, 0x2, +	0x949c, 0xffffffff, 0x100, +	0x9490, 0xffffffff, 0x3, +	0x949c, 0xffffffff, 0x100, +	0x9490, 0xffffffff, 0x4, +	0x949c, 0xffffffff, 0x100, +	0x9490, 0xffffffff, 0x5, +	0x949c, 0xffffffff, 0x100, +	0x9490, 0xffffffff, 0x6, +	0x949c, 0xffffffff, 0x100, +	0x9490, 0xffffffff, 0x7, +	0x949c, 0xffffffff, 0x100, +	0x9490, 0xffffffff, 0x8, +	0x949c, 0xffffffff, 0x100, +	0x9490, 0xffffffff, 0x9, +	0x949c, 0xffffffff, 0x100, +	0x9490, 0xffffffff, 0x8000, +	0x9604, 0xffffffff, 0x0, +	0x9654, 0xffffffff, 0x100, +	0x9604, 0xffffffff, 0x1, +	0x9654, 0xffffffff, 0x100, +	0x9604, 0xffffffff, 0x2, +	0x9654, 0xffffffff, 0x100, +	0x9604, 0xffffffff, 0x3, +	0x9654, 0xffffffff, 0x100, +	0x9604, 0xffffffff, 0x4, +	0x9654, 0xffffffff, 0x100, +	0x9604, 0xffffffff, 0x5, +	0x9654, 0xffffffff, 0x100, +	0x9604, 0xffffffff, 0x6, +	0x9654, 0xffffffff, 0x100, +	0x9604, 0xffffffff, 0x7, +	0x9654, 0xffffffff, 0x100, +	0x9604, 0xffffffff, 0x8, +	0x9654, 0xffffffff, 0x100, +	0x9604, 0xffffffff, 0x9, +	0x9654, 0xffffffff, 0x100, +	0x9604, 0xffffffff, 0x80000000, +	0x9030, 0xffffffff, 0x100, +	0x9034, 0xffffffff, 0x100, +	0x9038, 0xffffffff, 0x100, +	0x903c, 0xffffffff, 0x100, +	0x9040, 0xffffffff, 0x100, +	0xa200, 0xffffffff, 0x100, +	0xa204, 0xffffffff, 0x100, +	0xa208, 0xffffffff, 0x100, +	0xa20c, 0xffffffff, 0x100, +	0x971c, 0xffffffff, 0x100, +	0x915c, 0xffffffff, 0x00020001, +	0x9160, 0xffffffff, 0x00040003, +	0x916c, 0xffffffff, 0x00060005, +	0x9170, 0xffffffff, 0x00080007, +	0x9174, 0xffffffff, 0x000a0009, +	0x9178, 0xffffffff, 0x000c000b, +	0x917c, 0xffffffff, 0x000e000d, +	0x9180, 0xffffffff, 0x0010000f, +	0x918c, 0xffffffff, 0x00120011, +	0x9190, 0xffffffff, 0x00140013, +	0x9194, 0xffffffff, 0x00020001, +	0x9198, 0xffffffff, 0x00040003, +	0x919c, 0xffffffff, 0x00060005, +	0x91a8, 0xffffffff, 0x00080007, +	0x91ac, 0xffffffff, 0x000a0009, +	0x91b0, 0xffffffff, 0x000c000b, +	0x91b4, 0xffffffff, 0x000e000d, +	0x91b8, 0xffffffff, 0x0010000f, +	0x91c4, 0xffffffff, 0x00120011, +	0x91c8, 0xffffffff, 0x00140013, +	0x91cc, 0xffffffff, 0x00020001, +	0x91d0, 0xffffffff, 0x00040003, +	0x91d4, 0xffffffff, 0x00060005, +	0x91e0, 0xffffffff, 0x00080007, +	0x91e4, 0xffffffff, 0x000a0009, +	0x91e8, 0xffffffff, 0x000c000b, +	0x91ec, 0xffffffff, 0x00020001, +	0x91f0, 0xffffffff, 0x00040003, +	0x91f4, 0xffffffff, 0x00060005, +	0x9200, 0xffffffff, 0x00080007, +	0x9204, 0xffffffff, 0x000a0009, +	0x9208, 0xffffffff, 0x000c000b, +	0x920c, 0xffffffff, 0x000e000d, +	0x9210, 0xffffffff, 0x0010000f, +	0x921c, 0xffffffff, 0x00120011, +	0x9220, 0xffffffff, 0x00140013, +	0x9224, 0xffffffff, 0x00020001, +	0x9228, 0xffffffff, 0x00040003, +	0x922c, 0xffffffff, 0x00060005, +	0x9238, 0xffffffff, 0x00080007, +	0x923c, 0xffffffff, 0x000a0009, +	0x9240, 0xffffffff, 0x000c000b, +	0x9244, 0xffffffff, 0x000e000d, +	0x9248, 0xffffffff, 0x0010000f, +	0x9254, 0xffffffff, 0x00120011, +	0x9258, 0xffffffff, 0x00140013, +	0x925c, 0xffffffff, 0x00020001, +	0x9260, 0xffffffff, 0x00040003, +	0x9264, 0xffffffff, 0x00060005, +	0x9270, 0xffffffff, 0x00080007, +	0x9274, 0xffffffff, 0x000a0009, +	0x9278, 0xffffffff, 0x000c000b, +	0x927c, 0xffffffff, 0x000e000d, +	0x9280, 0xffffffff, 0x0010000f, +	0x928c, 0xffffffff, 0x00120011, +	0x9290, 0xffffffff, 0x00140013, +	0x9294, 0xffffffff, 0x00020001, +	0x929c, 0xffffffff, 0x00040003, +	0x92a0, 0xffffffff, 0x00060005, +	0x92a4, 0xffffffff, 0x00080007 +}; + +static const u32 rv710_golden_registers[] = +{ +	0x3f90, 0x00ff0000, 0x00fc0000, +	0x9148, 0x00ff0000, 0x00fc0000, +	0x3f94, 0x00ff0000, 0x00fc0000, +	0x914c, 0x00ff0000, 0x00fc0000, +	0xb4c, 0x00000020, 0x00000020, +	0xa180, 0xffffffff, 0x00003f3f +}; + +static const u32 rv710_mgcg_init[] = +{ +	0x8bcc, 0xffffffff, 0x13030040, +	0x5448, 0xffffffff, 0x100, +	0x55e4, 0xffffffff, 0x100, +	0x160c, 0xffffffff, 0x100, +	0x5644, 0xffffffff, 0x100, +	0xc164, 0xffffffff, 0x100, +	0x8a18, 0xffffffff, 0x100, +	0x897c, 0xffffffff, 0x8000100, +	0x8b28, 0xffffffff, 0x3c000100, +	0x9144, 0xffffffff, 0x100, +	0x9a1c, 0xffffffff, 0x10000, +	0x9a50, 0xffffffff, 0x100, +	0x9a1c, 0xffffffff, 0x0, +	0x9870, 0xffffffff, 0x100, +	0x8d58, 0xffffffff, 0x100, +	0x9500, 0xffffffff, 0x0, +	0x9510, 0xffffffff, 0x100, +	0x9500, 0xffffffff, 0x1, +	0x9510, 0xffffffff, 0x100, +	0x9500, 0xffffffff, 0x8000, +	0x9490, 0xffffffff, 0x0, +	0x949c, 0xffffffff, 0x100, +	0x9490, 0xffffffff, 0x1, +	0x949c, 0xffffffff, 0x100, +	0x9490, 0xffffffff, 0x8000, +	0x9604, 0xffffffff, 0x0, +	0x9654, 0xffffffff, 0x100, +	0x9604, 0xffffffff, 0x1, +	0x9654, 0xffffffff, 0x100, +	0x9604, 0xffffffff, 0x80000000, +	0x9030, 0xffffffff, 0x100, +	0x9034, 0xffffffff, 0x100, +	0x9038, 0xffffffff, 0x100, +	0x903c, 0xffffffff, 0x100, +	0x9040, 0xffffffff, 0x100, +	0xa200, 0xffffffff, 0x100, +	0xa204, 0xffffffff, 0x100, +	0xa208, 0xffffffff, 0x100, +	0xa20c, 0xffffffff, 0x100, +	0x971c, 0xffffffff, 0x100, +	0x915c, 0xffffffff, 0x00020001, +	0x9174, 0xffffffff, 0x00000003, +	0x9178, 0xffffffff, 0x00050001, +	0x917c, 0xffffffff, 0x00030002, +	0x918c, 0xffffffff, 0x00000004, +	0x9190, 0xffffffff, 0x00070006, +	0x9194, 0xffffffff, 0x00050001, +	0x9198, 0xffffffff, 0x00030002, +	0x91a8, 0xffffffff, 0x00000004, +	0x91ac, 0xffffffff, 0x00070006, +	0x91e8, 0xffffffff, 0x00000001, +	0x9294, 0xffffffff, 0x00000001, +	0x929c, 0xffffffff, 0x00000002, +	0x92a0, 0xffffffff, 0x00040003, +	0x9150, 0xffffffff, 0x4d940000 +}; + +static const u32 rv730_golden_registers[] = +{ +	0x3f90, 0x00ff0000, 0x00f00000, +	0x9148, 0x00ff0000, 0x00f00000, +	0x3f94, 0x00ff0000, 0x00f00000, +	0x914c, 0x00ff0000, 0x00f00000, +	0x900c, 0xffffffff, 0x003b033f, +	0xb4c, 0x00000020, 0x00000020, +	0xa180, 0xffffffff, 0x00003f3f +}; + +static const u32 rv730_mgcg_init[] = +{ +	0x8bcc, 0xffffffff, 0x130300f9, +	0x5448, 0xffffffff, 0x100, +	0x55e4, 0xffffffff, 0x100, +	0x160c, 0xffffffff, 0x100, +	0x5644, 0xffffffff, 0x100, +	0xc164, 0xffffffff, 0x100, +	0x8a18, 0xffffffff, 0x100, +	0x897c, 0xffffffff, 0x8000100, +	0x8b28, 0xffffffff, 0x3c000100, +	0x9144, 0xffffffff, 0x100, +	0x9a1c, 0xffffffff, 0x10000, +	0x9a50, 0xffffffff, 0x100, +	0x9a1c, 0xffffffff, 0x10001, +	0x9a50, 0xffffffff, 0x100, +	0x9a1c, 0xffffffff, 0x0, +	0x9870, 0xffffffff, 0x100, +	0x8d58, 0xffffffff, 0x100, +	0x9500, 0xffffffff, 0x0, +	0x9510, 0xffffffff, 0x100, +	0x9500, 0xffffffff, 0x1, +	0x9510, 0xffffffff, 0x100, +	0x9500, 0xffffffff, 0x2, +	0x9510, 0xffffffff, 0x100, +	0x9500, 0xffffffff, 0x3, +	0x9510, 0xffffffff, 0x100, +	0x9500, 0xffffffff, 0x4, +	0x9510, 0xffffffff, 0x100, +	0x9500, 0xffffffff, 0x5, +	0x9510, 0xffffffff, 0x100, +	0x9500, 0xffffffff, 0x6, +	0x9510, 0xffffffff, 0x100, +	0x9500, 0xffffffff, 0x7, +	0x9510, 0xffffffff, 0x100, +	0x9500, 0xffffffff, 0x8000, +	0x9490, 0xffffffff, 0x0, +	0x949c, 0xffffffff, 0x100, +	0x9490, 0xffffffff, 0x1, +	0x949c, 0xffffffff, 0x100, +	0x9490, 0xffffffff, 0x2, +	0x949c, 0xffffffff, 0x100, +	0x9490, 0xffffffff, 0x3, +	0x949c, 0xffffffff, 0x100, +	0x9490, 0xffffffff, 0x4, +	0x949c, 0xffffffff, 0x100, +	0x9490, 0xffffffff, 0x5, +	0x949c, 0xffffffff, 0x100, +	0x9490, 0xffffffff, 0x6, +	0x949c, 0xffffffff, 0x100, +	0x9490, 0xffffffff, 0x7, +	0x949c, 0xffffffff, 0x100, +	0x9490, 0xffffffff, 0x8000, +	0x9604, 0xffffffff, 0x0, +	0x9654, 0xffffffff, 0x100, +	0x9604, 0xffffffff, 0x1, +	0x9654, 0xffffffff, 0x100, +	0x9604, 0xffffffff, 0x2, +	0x9654, 0xffffffff, 0x100, +	0x9604, 0xffffffff, 0x3, +	0x9654, 0xffffffff, 0x100, +	0x9604, 0xffffffff, 0x4, +	0x9654, 0xffffffff, 0x100, +	0x9604, 0xffffffff, 0x5, +	0x9654, 0xffffffff, 0x100, +	0x9604, 0xffffffff, 0x6, +	0x9654, 0xffffffff, 0x100, +	0x9604, 0xffffffff, 0x7, +	0x9654, 0xffffffff, 0x100, +	0x9604, 0xffffffff, 0x80000000, +	0x9030, 0xffffffff, 0x100, +	0x9034, 0xffffffff, 0x100, +	0x9038, 0xffffffff, 0x100, +	0x903c, 0xffffffff, 0x100, +	0x9040, 0xffffffff, 0x100, +	0xa200, 0xffffffff, 0x100, +	0xa204, 0xffffffff, 0x100, +	0xa208, 0xffffffff, 0x100, +	0xa20c, 0xffffffff, 0x100, +	0x971c, 0xffffffff, 0x100, +	0x915c, 0xffffffff, 0x00020001, +	0x916c, 0xffffffff, 0x00040003, +	0x9170, 0xffffffff, 0x00000005, +	0x9178, 0xffffffff, 0x00050001, +	0x917c, 0xffffffff, 0x00030002, +	0x918c, 0xffffffff, 0x00000004, +	0x9190, 0xffffffff, 0x00070006, +	0x9194, 0xffffffff, 0x00050001, +	0x9198, 0xffffffff, 0x00030002, +	0x91a8, 0xffffffff, 0x00000004, +	0x91ac, 0xffffffff, 0x00070006, +	0x91b0, 0xffffffff, 0x00050001, +	0x91b4, 0xffffffff, 0x00030002, +	0x91c4, 0xffffffff, 0x00000004, +	0x91c8, 0xffffffff, 0x00070006, +	0x91cc, 0xffffffff, 0x00050001, +	0x91d0, 0xffffffff, 0x00030002, +	0x91e0, 0xffffffff, 0x00000004, +	0x91e4, 0xffffffff, 0x00070006, +	0x91e8, 0xffffffff, 0x00000001, +	0x91ec, 0xffffffff, 0x00050001, +	0x91f0, 0xffffffff, 0x00030002, +	0x9200, 0xffffffff, 0x00000004, +	0x9204, 0xffffffff, 0x00070006, +	0x9208, 0xffffffff, 0x00050001, +	0x920c, 0xffffffff, 0x00030002, +	0x921c, 0xffffffff, 0x00000004, +	0x9220, 0xffffffff, 0x00070006, +	0x9224, 0xffffffff, 0x00050001, +	0x9228, 0xffffffff, 0x00030002, +	0x9238, 0xffffffff, 0x00000004, +	0x923c, 0xffffffff, 0x00070006, +	0x9240, 0xffffffff, 0x00050001, +	0x9244, 0xffffffff, 0x00030002, +	0x9254, 0xffffffff, 0x00000004, +	0x9258, 0xffffffff, 0x00070006, +	0x9294, 0xffffffff, 0x00000001, +	0x929c, 0xffffffff, 0x00000002, +	0x92a0, 0xffffffff, 0x00040003, +	0x92a4, 0xffffffff, 0x00000005 +}; + +static const u32 rv740_golden_registers[] = +{ +	0x88c4, 0xffffffff, 0x00000082, +	0x28a50, 0xfffffffc, 0x00000004, +	0x2650, 0x00040000, 0, +	0x20bc, 0x00040000, 0, +	0x733c, 0xffffffff, 0x00000002, +	0x7300, 0xffffffff, 0x001000f0, +	0x3f90, 0x00ff0000, 0, +	0x9148, 0x00ff0000, 0, +	0x3f94, 0x00ff0000, 0, +	0x914c, 0x00ff0000, 0, +	0x240c, 0xffffffff, 0x00000380, +	0x8a14, 0x00000007, 0x00000007, +	0x8b24, 0xffffffff, 0x00ff0fff, +	0x28a4c, 0xffffffff, 0x00004000, +	0xa180, 0xffffffff, 0x00003f3f, +	0x8d00, 0xffffffff, 0x0e0e003a, +	0x8d04, 0xffffffff, 0x013a0e2a, +	0x8c00, 0xffffffff, 0xe400000f, +	0x8db0, 0xffffffff, 0x98989898, +	0x8db4, 0xffffffff, 0x98989898, +	0x8db8, 0xffffffff, 0x98989898, +	0x8dbc, 0xffffffff, 0x98989898, +	0x8dc0, 0xffffffff, 0x98989898, +	0x8dc4, 0xffffffff, 0x98989898, +	0x8dc8, 0xffffffff, 0x98989898, +	0x8dcc, 0xffffffff, 0x98989898, +	0x9058, 0xffffffff, 0x0fffc40f, +	0x900c, 0xffffffff, 0x003b033f, +	0x28350, 0xffffffff, 0, +	0x8cf0, 0x1fffffff, 0x08e00420, +	0x9508, 0xffffffff, 0x00000002, +	0x88c4, 0xffffffff, 0x000000c2, +	0x9698, 0x18000000, 0x18000000 +}; + +static const u32 rv740_mgcg_init[] = +{ +	0x8bcc, 0xffffffff, 0x13030100, +	0x5448, 0xffffffff, 0x100, +	0x55e4, 0xffffffff, 0x100, +	0x160c, 0xffffffff, 0x100, +	0x5644, 0xffffffff, 0x100, +	0xc164, 0xffffffff, 0x100, +	0x8a18, 0xffffffff, 0x100, +	0x897c, 0xffffffff, 0x100, +	0x8b28, 0xffffffff, 0x100, +	0x9144, 0xffffffff, 0x100, +	0x9a1c, 0xffffffff, 0x10000, +	0x9a50, 0xffffffff, 0x100, +	0x9a1c, 0xffffffff, 0x10001, +	0x9a50, 0xffffffff, 0x100, +	0x9a1c, 0xffffffff, 0x10002, +	0x9a50, 0xffffffff, 0x100, +	0x9a1c, 0xffffffff, 0x10003, +	0x9a50, 0xffffffff, 0x100, +	0x9a1c, 0xffffffff, 0x0, +	0x9870, 0xffffffff, 0x100, +	0x8d58, 0xffffffff, 0x100, +	0x9500, 0xffffffff, 0x0, +	0x9510, 0xffffffff, 0x100, +	0x9500, 0xffffffff, 0x1, +	0x9510, 0xffffffff, 0x100, +	0x9500, 0xffffffff, 0x2, +	0x9510, 0xffffffff, 0x100, +	0x9500, 0xffffffff, 0x3, +	0x9510, 0xffffffff, 0x100, +	0x9500, 0xffffffff, 0x4, +	0x9510, 0xffffffff, 0x100, +	0x9500, 0xffffffff, 0x5, +	0x9510, 0xffffffff, 0x100, +	0x9500, 0xffffffff, 0x6, +	0x9510, 0xffffffff, 0x100, +	0x9500, 0xffffffff, 0x7, +	0x9510, 0xffffffff, 0x100, +	0x9500, 0xffffffff, 0x8000, +	0x9490, 0xffffffff, 0x0, +	0x949c, 0xffffffff, 0x100, +	0x9490, 0xffffffff, 0x1, +	0x949c, 0xffffffff, 0x100, +	0x9490, 0xffffffff, 0x2, +	0x949c, 0xffffffff, 0x100, +	0x9490, 0xffffffff, 0x3, +	0x949c, 0xffffffff, 0x100, +	0x9490, 0xffffffff, 0x4, +	0x949c, 0xffffffff, 0x100, +	0x9490, 0xffffffff, 0x5, +	0x949c, 0xffffffff, 0x100, +	0x9490, 0xffffffff, 0x6, +	0x949c, 0xffffffff, 0x100, +	0x9490, 0xffffffff, 0x7, +	0x949c, 0xffffffff, 0x100, +	0x9490, 0xffffffff, 0x8000, +	0x9604, 0xffffffff, 0x0, +	0x9654, 0xffffffff, 0x100, +	0x9604, 0xffffffff, 0x1, +	0x9654, 0xffffffff, 0x100, +	0x9604, 0xffffffff, 0x2, +	0x9654, 0xffffffff, 0x100, +	0x9604, 0xffffffff, 0x3, +	0x9654, 0xffffffff, 0x100, +	0x9604, 0xffffffff, 0x4, +	0x9654, 0xffffffff, 0x100, +	0x9604, 0xffffffff, 0x5, +	0x9654, 0xffffffff, 0x100, +	0x9604, 0xffffffff, 0x6, +	0x9654, 0xffffffff, 0x100, +	0x9604, 0xffffffff, 0x7, +	0x9654, 0xffffffff, 0x100, +	0x9604, 0xffffffff, 0x80000000, +	0x9030, 0xffffffff, 0x100, +	0x9034, 0xffffffff, 0x100, +	0x9038, 0xffffffff, 0x100, +	0x903c, 0xffffffff, 0x100, +	0x9040, 0xffffffff, 0x100, +	0xa200, 0xffffffff, 0x100, +	0xa204, 0xffffffff, 0x100, +	0xa208, 0xffffffff, 0x100, +	0xa20c, 0xffffffff, 0x100, +	0x971c, 0xffffffff, 0x100, +	0x915c, 0xffffffff, 0x00020001, +	0x9160, 0xffffffff, 0x00040003, +	0x916c, 0xffffffff, 0x00060005, +	0x9170, 0xffffffff, 0x00080007, +	0x9174, 0xffffffff, 0x000a0009, +	0x9178, 0xffffffff, 0x000c000b, +	0x917c, 0xffffffff, 0x000e000d, +	0x9180, 0xffffffff, 0x0010000f, +	0x918c, 0xffffffff, 0x00120011, +	0x9190, 0xffffffff, 0x00140013, +	0x9194, 0xffffffff, 0x00020001, +	0x9198, 0xffffffff, 0x00040003, +	0x919c, 0xffffffff, 0x00060005, +	0x91a8, 0xffffffff, 0x00080007, +	0x91ac, 0xffffffff, 0x000a0009, +	0x91b0, 0xffffffff, 0x000c000b, +	0x91b4, 0xffffffff, 0x000e000d, +	0x91b8, 0xffffffff, 0x0010000f, +	0x91c4, 0xffffffff, 0x00120011, +	0x91c8, 0xffffffff, 0x00140013, +	0x91cc, 0xffffffff, 0x00020001, +	0x91d0, 0xffffffff, 0x00040003, +	0x91d4, 0xffffffff, 0x00060005, +	0x91e0, 0xffffffff, 0x00080007, +	0x91e4, 0xffffffff, 0x000a0009, +	0x91e8, 0xffffffff, 0x000c000b, +	0x91ec, 0xffffffff, 0x00020001, +	0x91f0, 0xffffffff, 0x00040003, +	0x91f4, 0xffffffff, 0x00060005, +	0x9200, 0xffffffff, 0x00080007, +	0x9204, 0xffffffff, 0x000a0009, +	0x9208, 0xffffffff, 0x000c000b, +	0x920c, 0xffffffff, 0x000e000d, +	0x9210, 0xffffffff, 0x0010000f, +	0x921c, 0xffffffff, 0x00120011, +	0x9220, 0xffffffff, 0x00140013, +	0x9224, 0xffffffff, 0x00020001, +	0x9228, 0xffffffff, 0x00040003, +	0x922c, 0xffffffff, 0x00060005, +	0x9238, 0xffffffff, 0x00080007, +	0x923c, 0xffffffff, 0x000a0009, +	0x9240, 0xffffffff, 0x000c000b, +	0x9244, 0xffffffff, 0x000e000d, +	0x9248, 0xffffffff, 0x0010000f, +	0x9254, 0xffffffff, 0x00120011, +	0x9258, 0xffffffff, 0x00140013, +	0x9294, 0xffffffff, 0x00020001, +	0x929c, 0xffffffff, 0x00040003, +	0x92a0, 0xffffffff, 0x00060005, +	0x92a4, 0xffffffff, 0x00080007 +}; + +static void rv770_init_golden_registers(struct radeon_device *rdev) +{ +	switch (rdev->family) { +	case CHIP_RV770: +		radeon_program_register_sequence(rdev, +						 r7xx_golden_registers, +						 (const u32)ARRAY_SIZE(r7xx_golden_registers)); +		radeon_program_register_sequence(rdev, +						 r7xx_golden_dyn_gpr_registers, +						 (const u32)ARRAY_SIZE(r7xx_golden_dyn_gpr_registers)); +		if (rdev->pdev->device == 0x994e) +			radeon_program_register_sequence(rdev, +							 rv770ce_golden_registers, +							 (const u32)ARRAY_SIZE(rv770ce_golden_registers)); +		else +			radeon_program_register_sequence(rdev, +							 rv770_golden_registers, +							 (const u32)ARRAY_SIZE(rv770_golden_registers)); +		radeon_program_register_sequence(rdev, +						 rv770_mgcg_init, +						 (const u32)ARRAY_SIZE(rv770_mgcg_init)); +		break; +	case CHIP_RV730: +		radeon_program_register_sequence(rdev, +						 r7xx_golden_registers, +						 (const u32)ARRAY_SIZE(r7xx_golden_registers)); +		radeon_program_register_sequence(rdev, +						 r7xx_golden_dyn_gpr_registers, +						 (const u32)ARRAY_SIZE(r7xx_golden_dyn_gpr_registers)); +		radeon_program_register_sequence(rdev, +						 rv730_golden_registers, +						 (const u32)ARRAY_SIZE(rv730_golden_registers)); +		radeon_program_register_sequence(rdev, +						 rv730_mgcg_init, +						 (const u32)ARRAY_SIZE(rv730_mgcg_init)); +		break; +	case CHIP_RV710: +		radeon_program_register_sequence(rdev, +						 r7xx_golden_registers, +						 (const u32)ARRAY_SIZE(r7xx_golden_registers)); +		radeon_program_register_sequence(rdev, +						 r7xx_golden_dyn_gpr_registers, +						 (const u32)ARRAY_SIZE(r7xx_golden_dyn_gpr_registers)); +		radeon_program_register_sequence(rdev, +						 rv710_golden_registers, +						 (const u32)ARRAY_SIZE(rv710_golden_registers)); +		radeon_program_register_sequence(rdev, +						 rv710_mgcg_init, +						 (const u32)ARRAY_SIZE(rv710_mgcg_init)); +		break; +	case CHIP_RV740: +		radeon_program_register_sequence(rdev, +						 rv740_golden_registers, +						 (const u32)ARRAY_SIZE(rv740_golden_registers)); +		radeon_program_register_sequence(rdev, +						 rv740_mgcg_init, +						 (const u32)ARRAY_SIZE(rv740_mgcg_init)); +		break; +	default: +		break; +	} +} + +#define PCIE_BUS_CLK                10000 +#define TCLK                        (PCIE_BUS_CLK / 10) + +/** + * rv770_get_xclk - get the xclk + * + * @rdev: radeon_device pointer + * + * Returns the reference clock used by the gfx engine + * (r7xx-cayman). + */ +u32 rv770_get_xclk(struct radeon_device *rdev) +{ +	u32 reference_clock = rdev->clock.spll.reference_freq; +	u32 tmp = RREG32(CG_CLKPIN_CNTL); + +	if (tmp & MUX_TCLK_TO_XCLK) +		return TCLK; + +	if (tmp & XTALIN_DIVIDE) +		return reference_clock / 4; + +	return reference_clock; +} + +void rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base) +{ +	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; +	u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset); +	int i; + +	/* Lock the graphics update lock */ +	tmp |= AVIVO_D1GRPH_UPDATE_LOCK; +	WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp); + +	/* update the scanout addresses */ +	if (radeon_crtc->crtc_id) { +		WREG32(D2GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, upper_32_bits(crtc_base)); +		WREG32(D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, upper_32_bits(crtc_base)); +	} else { +		WREG32(D1GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, upper_32_bits(crtc_base)); +		WREG32(D1GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, upper_32_bits(crtc_base)); +	} +	WREG32(D1GRPH_SECONDARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, +	       (u32)crtc_base); +	WREG32(D1GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset, +	       (u32)crtc_base); + +	/* Wait for update_pending to go high. */ +	for (i = 0; i < rdev->usec_timeout; i++) { +		if (RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING) +			break; +		udelay(1); +	} +	DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n"); + +	/* Unlock the lock, so double-buffering can take place inside vblank */ +	tmp &= ~AVIVO_D1GRPH_UPDATE_LOCK; +	WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp); +} + +bool rv770_page_flip_pending(struct radeon_device *rdev, int crtc_id) +{ +	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id]; + +	/* Return current update_pending status: */ +	return !!(RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & +		AVIVO_D1GRPH_SURFACE_UPDATE_PENDING); +}  /* get temperature in millidegrees */ -u32 rv770_get_temp(struct radeon_device *rdev) +int rv770_get_temp(struct radeon_device *rdev)  {  	u32 temp = (RREG32(CG_MULT_THERMAL_STATUS) & ASIC_T_MASK) >>  		ASIC_T_SHIFT; -	u32 actual_temp = 0; - -	if ((temp >> 9) & 1) -		actual_temp = 0; -	else -		actual_temp = (temp >> 1) & 0xff; - -	return actual_temp * 1000; +	int actual_temp; + +	if (temp & 0x400) +		actual_temp = -256; +	else if (temp & 0x200) +		actual_temp = 255; +	else if (temp & 0x100) { +		actual_temp = temp & 0x1ff; +		actual_temp |= ~0x1ff; +	} else +		actual_temp = temp & 0xff; + +	return (actual_temp * 1000) / 2;  }  void rv770_pm_misc(struct radeon_device *rdev) @@ -65,8 +874,11 @@ void rv770_pm_misc(struct radeon_device *rdev)  	struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage;  	if ((voltage->type == VOLTAGE_SW) && voltage->voltage) { +		/* 0xff01 is a flag rather then an actual voltage */ +		if (voltage->voltage == 0xff01) +			return;  		if (voltage->voltage != rdev->pm.current_vddc) { -			radeon_atom_set_voltage(rdev, voltage->voltage); +			radeon_atom_set_voltage(rdev, voltage->voltage, SET_VOLTAGE_TYPE_ASIC_VDDC);  			rdev->pm.current_vddc = voltage->voltage;  			DRM_DEBUG("Setting: v: %d\n", voltage->voltage);  		} @@ -76,12 +888,12 @@ void rv770_pm_misc(struct radeon_device *rdev)  /*   * GART   */ -int rv770_pcie_gart_enable(struct radeon_device *rdev) +static int rv770_pcie_gart_enable(struct radeon_device *rdev)  {  	u32 tmp;  	int r, i; -	if (rdev->gart.table.vram.robj == NULL) { +	if (rdev->gart.robj == NULL) {  		dev_err(rdev->dev, "No VRAM object for PCIE GART.\n");  		return -EINVAL;  	} @@ -103,6 +915,8 @@ int rv770_pcie_gart_enable(struct radeon_device *rdev)  	WREG32(MC_VM_MD_L1_TLB0_CNTL, tmp);  	WREG32(MC_VM_MD_L1_TLB1_CNTL, tmp);  	WREG32(MC_VM_MD_L1_TLB2_CNTL, tmp); +	if (rdev->family == CHIP_RV740) +		WREG32(MC_VM_MD_L1_TLB3_CNTL, tmp);  	WREG32(MC_VM_MB_L1_TLB0_CNTL, tmp);  	WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp);  	WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp); @@ -118,14 +932,17 @@ int rv770_pcie_gart_enable(struct radeon_device *rdev)  		WREG32(VM_CONTEXT0_CNTL + (i * 4), 0);  	r600_pcie_gart_tlb_flush(rdev); +	DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n", +		 (unsigned)(rdev->mc.gtt_size >> 20), +		 (unsigned long long)rdev->gart.table_addr);  	rdev->gart.ready = true;  	return 0;  } -void rv770_pcie_gart_disable(struct radeon_device *rdev) +static void rv770_pcie_gart_disable(struct radeon_device *rdev)  {  	u32 tmp; -	int i, r; +	int i;  	/* Disable all tables */  	for (i = 0; i < 7; i++) @@ -145,17 +962,10 @@ void rv770_pcie_gart_disable(struct radeon_device *rdev)  	WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp);  	WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp);  	WREG32(MC_VM_MB_L1_TLB3_CNTL, tmp); -	if (rdev->gart.table.vram.robj) { -		r = radeon_bo_reserve(rdev->gart.table.vram.robj, false); -		if (likely(r == 0)) { -			radeon_bo_kunmap(rdev->gart.table.vram.robj); -			radeon_bo_unpin(rdev->gart.table.vram.robj); -			radeon_bo_unreserve(rdev->gart.table.vram.robj); -		} -	} +	radeon_gart_table_vram_unpin(rdev);  } -void rv770_pcie_gart_fini(struct radeon_device *rdev) +static void rv770_pcie_gart_fini(struct radeon_device *rdev)  {  	radeon_gart_fini(rdev);  	rv770_pcie_gart_disable(rdev); @@ -163,7 +973,7 @@ void rv770_pcie_gart_fini(struct radeon_device *rdev)  } -void rv770_agp_enable(struct radeon_device *rdev) +static void rv770_agp_enable(struct radeon_device *rdev)  {  	u32 tmp;  	int i; @@ -236,7 +1046,7 @@ static void rv770_mc_program(struct radeon_device *rdev)  		WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR,  			rdev->mc.vram_end >> 12);  	} -	WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, 0); +	WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, rdev->vram_scratch.gpu_addr >> 12);  	tmp = ((rdev->mc.vram_end >> 24) & 0xFFFF) << 16;  	tmp |= ((rdev->mc.vram_start >> 24) & 0xFFFF);  	WREG32(MC_VM_FB_LOCATION, tmp); @@ -267,9 +1077,11 @@ static void rv770_mc_program(struct radeon_device *rdev)   */  void r700_cp_stop(struct radeon_device *rdev)  { -	rdev->mc.active_vram_size = rdev->mc.visible_vram_size; +	if (rdev->asic->copy.copy_ring_index == RADEON_RING_TYPE_GFX_INDEX) +		radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size);  	WREG32(CP_ME_CNTL, (CP_ME_HALT | CP_PFP_HALT));  	WREG32(SCRATCH_UMSK, 0); +	rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false;  }  static int rv770_cp_load_microcode(struct radeon_device *rdev) @@ -281,7 +1093,11 @@ static int rv770_cp_load_microcode(struct radeon_device *rdev)  		return -EINVAL;  	r700_cp_stop(rdev); -	WREG32(CP_RB_CNTL, RB_NO_UPDATE | (15 << 8) | (3 << 0)); +	WREG32(CP_RB_CNTL, +#ifdef __BIG_ENDIAN +	       BUF_SWAP_32BIT | +#endif +	       RB_NO_UPDATE | RB_BLKSZ(15) | RB_BUFSZ(3));  	/* Reset cp */  	WREG32(GRBM_SOFT_RESET, SOFT_RESET_CP); @@ -308,187 +1124,44 @@ static int rv770_cp_load_microcode(struct radeon_device *rdev)  void r700_cp_fini(struct radeon_device *rdev)  { +	struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];  	r700_cp_stop(rdev); -	radeon_ring_fini(rdev); +	radeon_ring_fini(rdev, ring); +	radeon_scratch_free(rdev, ring->rptr_save_reg);  } -/* - * Core functions - */ -static u32 r700_get_tile_pipe_to_backend_map(struct radeon_device *rdev, -					     u32 num_tile_pipes, -					     u32 num_backends, -					     u32 backend_disable_mask) +void rv770_set_clk_bypass_mode(struct radeon_device *rdev)  { -	u32 backend_map = 0; -	u32 enabled_backends_mask; -	u32 enabled_backends_count; -	u32 cur_pipe; -	u32 swizzle_pipe[R7XX_MAX_PIPES]; -	u32 cur_backend; -	u32 i; -	bool force_no_swizzle; - -	if (num_tile_pipes > R7XX_MAX_PIPES) -		num_tile_pipes = R7XX_MAX_PIPES; -	if (num_tile_pipes < 1) -		num_tile_pipes = 1; -	if (num_backends > R7XX_MAX_BACKENDS) -		num_backends = R7XX_MAX_BACKENDS; -	if (num_backends < 1) -		num_backends = 1; - -	enabled_backends_mask = 0; -	enabled_backends_count = 0; -	for (i = 0; i < R7XX_MAX_BACKENDS; ++i) { -		if (((backend_disable_mask >> i) & 1) == 0) { -			enabled_backends_mask |= (1 << i); -			++enabled_backends_count; -		} -		if (enabled_backends_count == num_backends) -			break; -	} - -	if (enabled_backends_count == 0) { -		enabled_backends_mask = 1; -		enabled_backends_count = 1; -	} +	u32 tmp, i; -	if (enabled_backends_count != num_backends) -		num_backends = enabled_backends_count; +	if (rdev->flags & RADEON_IS_IGP) +		return; -	switch (rdev->family) { -	case CHIP_RV770: -	case CHIP_RV730: -		force_no_swizzle = false; -		break; -	case CHIP_RV710: -	case CHIP_RV740: -	default: -		force_no_swizzle = true; -		break; -	} +	tmp = RREG32(CG_SPLL_FUNC_CNTL_2); +	tmp &= SCLK_MUX_SEL_MASK; +	tmp |= SCLK_MUX_SEL(1) | SCLK_MUX_UPDATE; +	WREG32(CG_SPLL_FUNC_CNTL_2, tmp); -	memset((uint8_t *)&swizzle_pipe[0], 0, sizeof(u32) * R7XX_MAX_PIPES); -	switch (num_tile_pipes) { -	case 1: -		swizzle_pipe[0] = 0; -		break; -	case 2: -		swizzle_pipe[0] = 0; -		swizzle_pipe[1] = 1; -		break; -	case 3: -		if (force_no_swizzle) { -			swizzle_pipe[0] = 0; -			swizzle_pipe[1] = 1; -			swizzle_pipe[2] = 2; -		} else { -			swizzle_pipe[0] = 0; -			swizzle_pipe[1] = 2; -			swizzle_pipe[2] = 1; -		} -		break; -	case 4: -		if (force_no_swizzle) { -			swizzle_pipe[0] = 0; -			swizzle_pipe[1] = 1; -			swizzle_pipe[2] = 2; -			swizzle_pipe[3] = 3; -		} else { -			swizzle_pipe[0] = 0; -			swizzle_pipe[1] = 2; -			swizzle_pipe[2] = 3; -			swizzle_pipe[3] = 1; -		} -		break; -	case 5: -		if (force_no_swizzle) { -			swizzle_pipe[0] = 0; -			swizzle_pipe[1] = 1; -			swizzle_pipe[2] = 2; -			swizzle_pipe[3] = 3; -			swizzle_pipe[4] = 4; -		} else { -			swizzle_pipe[0] = 0; -			swizzle_pipe[1] = 2; -			swizzle_pipe[2] = 4; -			swizzle_pipe[3] = 1; -			swizzle_pipe[4] = 3; -		} -		break; -	case 6: -		if (force_no_swizzle) { -			swizzle_pipe[0] = 0; -			swizzle_pipe[1] = 1; -			swizzle_pipe[2] = 2; -			swizzle_pipe[3] = 3; -			swizzle_pipe[4] = 4; -			swizzle_pipe[5] = 5; -		} else { -			swizzle_pipe[0] = 0; -			swizzle_pipe[1] = 2; -			swizzle_pipe[2] = 4; -			swizzle_pipe[3] = 5; -			swizzle_pipe[4] = 3; -			swizzle_pipe[5] = 1; -		} -		break; -	case 7: -		if (force_no_swizzle) { -			swizzle_pipe[0] = 0; -			swizzle_pipe[1] = 1; -			swizzle_pipe[2] = 2; -			swizzle_pipe[3] = 3; -			swizzle_pipe[4] = 4; -			swizzle_pipe[5] = 5; -			swizzle_pipe[6] = 6; -		} else { -			swizzle_pipe[0] = 0; -			swizzle_pipe[1] = 2; -			swizzle_pipe[2] = 4; -			swizzle_pipe[3] = 6; -			swizzle_pipe[4] = 3; -			swizzle_pipe[5] = 1; -			swizzle_pipe[6] = 5; -		} -		break; -	case 8: -		if (force_no_swizzle) { -			swizzle_pipe[0] = 0; -			swizzle_pipe[1] = 1; -			swizzle_pipe[2] = 2; -			swizzle_pipe[3] = 3; -			swizzle_pipe[4] = 4; -			swizzle_pipe[5] = 5; -			swizzle_pipe[6] = 6; -			swizzle_pipe[7] = 7; -		} else { -			swizzle_pipe[0] = 0; -			swizzle_pipe[1] = 2; -			swizzle_pipe[2] = 4; -			swizzle_pipe[3] = 6; -			swizzle_pipe[4] = 3; -			swizzle_pipe[5] = 1; -			swizzle_pipe[6] = 7; -			swizzle_pipe[7] = 5; -		} -		break; +	for (i = 0; i < rdev->usec_timeout; i++) { +		if (RREG32(CG_SPLL_STATUS) & SPLL_CHG_STATUS) +			break; +		udelay(1);  	} -	cur_backend = 0; -	for (cur_pipe = 0; cur_pipe < num_tile_pipes; ++cur_pipe) { -		while (((1 << cur_backend) & enabled_backends_mask) == 0) -			cur_backend = (cur_backend + 1) % R7XX_MAX_BACKENDS; - -		backend_map |= (u32)(((cur_backend & 3) << (swizzle_pipe[cur_pipe] * 2))); +	tmp &= ~SCLK_MUX_UPDATE; +	WREG32(CG_SPLL_FUNC_CNTL_2, tmp); -		cur_backend = (cur_backend + 1) % R7XX_MAX_BACKENDS; -	} - -	return backend_map; +	tmp = RREG32(MPLL_CNTL_MODE); +	if ((rdev->family == CHIP_RV710) || (rdev->family == CHIP_RV730)) +		tmp &= ~RV730_MPLL_MCLK_SEL; +	else +		tmp &= ~MPLL_MCLK_SEL; +	WREG32(MPLL_CNTL_MODE, tmp);  } +/* + * Core functions + */  static void rv770_gpu_init(struct radeon_device *rdev)  {  	int i, j, num_qd_pipes; @@ -504,14 +1177,17 @@ static void rv770_gpu_init(struct radeon_device *rdev)  	u32 sq_thread_resource_mgmt;  	u32 hdp_host_path_cntl;  	u32 sq_dyn_gpr_size_simd_ab_0; -	u32 backend_map;  	u32 gb_tiling_config = 0;  	u32 cc_rb_backend_disable = 0;  	u32 cc_gc_shader_pipe_config = 0;  	u32 mc_arb_ramcfg; -	u32 db_debug4; +	u32 db_debug4, tmp; +	u32 inactive_pipes, shader_pipe_config; +	u32 disabled_rb_mask; +	unsigned active_number;  	/* setup chip specs */ +	rdev->config.rv770.tiling_group_size = 256;  	switch (rdev->family) {  	case CHIP_RV770:  		rdev->config.rv770.max_pipes = 4; @@ -622,33 +1298,73 @@ static void rv770_gpu_init(struct radeon_device *rdev)  	/* setup tiling, simd, pipe config */  	mc_arb_ramcfg = RREG32(MC_ARB_RAMCFG); +	shader_pipe_config = RREG32(CC_GC_SHADER_PIPE_CONFIG); +	inactive_pipes = (shader_pipe_config & INACTIVE_QD_PIPES_MASK) >> INACTIVE_QD_PIPES_SHIFT; +	for (i = 0, tmp = 1, active_number = 0; i < R7XX_MAX_PIPES; i++) { +		if (!(inactive_pipes & tmp)) { +			active_number++; +		} +		tmp <<= 1; +	} +	if (active_number == 1) { +		WREG32(SPI_CONFIG_CNTL, DISABLE_INTERP_1); +	} else { +		WREG32(SPI_CONFIG_CNTL, 0); +	} + +	cc_rb_backend_disable = RREG32(CC_RB_BACKEND_DISABLE) & 0x00ff0000; +	tmp = R7XX_MAX_BACKENDS - r600_count_pipe_bits(cc_rb_backend_disable >> 16); +	if (tmp < rdev->config.rv770.max_backends) { +		rdev->config.rv770.max_backends = tmp; +	} + +	cc_gc_shader_pipe_config = RREG32(CC_GC_SHADER_PIPE_CONFIG) & 0xffffff00; +	tmp = R7XX_MAX_PIPES - r600_count_pipe_bits((cc_gc_shader_pipe_config >> 8) & R7XX_MAX_PIPES_MASK); +	if (tmp < rdev->config.rv770.max_pipes) { +		rdev->config.rv770.max_pipes = tmp; +	} +	tmp = R7XX_MAX_SIMDS - r600_count_pipe_bits((cc_gc_shader_pipe_config >> 16) & R7XX_MAX_SIMDS_MASK); +	if (tmp < rdev->config.rv770.max_simds) { +		rdev->config.rv770.max_simds = tmp; +	} +	tmp = rdev->config.rv770.max_simds - +		r600_count_pipe_bits((cc_gc_shader_pipe_config >> 16) & R7XX_MAX_SIMDS_MASK); +	rdev->config.rv770.active_simds = tmp; +  	switch (rdev->config.rv770.max_tile_pipes) {  	case 1:  	default: -		gb_tiling_config |= PIPE_TILING(0); +		gb_tiling_config = PIPE_TILING(0);  		break;  	case 2: -		gb_tiling_config |= PIPE_TILING(1); +		gb_tiling_config = PIPE_TILING(1);  		break;  	case 4: -		gb_tiling_config |= PIPE_TILING(2); +		gb_tiling_config = PIPE_TILING(2);  		break;  	case 8: -		gb_tiling_config |= PIPE_TILING(3); +		gb_tiling_config = PIPE_TILING(3);  		break;  	}  	rdev->config.rv770.tiling_npipes = rdev->config.rv770.max_tile_pipes; +	disabled_rb_mask = (RREG32(CC_RB_BACKEND_DISABLE) >> 16) & R7XX_MAX_BACKENDS_MASK; +	tmp = (gb_tiling_config & PIPE_TILING__MASK) >> PIPE_TILING__SHIFT; +	tmp = r6xx_remap_render_backend(rdev, tmp, rdev->config.rv770.max_backends, +					R7XX_MAX_BACKENDS, disabled_rb_mask); +	gb_tiling_config |= tmp << 16; +	rdev->config.rv770.backend_map = tmp; +  	if (rdev->family == CHIP_RV770)  		gb_tiling_config |= BANK_TILING(1); -	else -		gb_tiling_config |= BANK_TILING((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT); +	else { +		if ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) +			gb_tiling_config |= BANK_TILING(1); +		else +			gb_tiling_config |= BANK_TILING(0); +	}  	rdev->config.rv770.tiling_nbanks = 4 << ((gb_tiling_config >> 4) & 0x3);  	gb_tiling_config |= GROUP_SIZE((mc_arb_ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT); -	if ((mc_arb_ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT) -		rdev->config.rv770.tiling_group_size = 512; -	else -		rdev->config.rv770.tiling_group_size = 256;  	if (((mc_arb_ramcfg & NOOFROWS_MASK) >> NOOFROWS_SHIFT) > 3) {  		gb_tiling_config |= ROW_TILING(3);  		gb_tiling_config |= SAMPLE_SPLIT(3); @@ -660,46 +1376,26 @@ static void rv770_gpu_init(struct radeon_device *rdev)  	}  	gb_tiling_config |= BANK_SWAPS(1); - -	cc_rb_backend_disable = RREG32(CC_RB_BACKEND_DISABLE) & 0x00ff0000; -	cc_rb_backend_disable |= -		BACKEND_DISABLE((R7XX_MAX_BACKENDS_MASK << rdev->config.rv770.max_backends) & R7XX_MAX_BACKENDS_MASK); - -	cc_gc_shader_pipe_config = RREG32(CC_GC_SHADER_PIPE_CONFIG) & 0xffffff00; -	cc_gc_shader_pipe_config |= -		INACTIVE_QD_PIPES((R7XX_MAX_PIPES_MASK << rdev->config.rv770.max_pipes) & R7XX_MAX_PIPES_MASK); -	cc_gc_shader_pipe_config |= -		INACTIVE_SIMDS((R7XX_MAX_SIMDS_MASK << rdev->config.rv770.max_simds) & R7XX_MAX_SIMDS_MASK); - -	if (rdev->family == CHIP_RV740) -		backend_map = 0x28; -	else -		backend_map = r700_get_tile_pipe_to_backend_map(rdev, -								rdev->config.rv770.max_tile_pipes, -								(R7XX_MAX_BACKENDS - -								 r600_count_pipe_bits((cc_rb_backend_disable & -										       R7XX_MAX_BACKENDS_MASK) >> 16)), -								(cc_rb_backend_disable >> 16)); -  	rdev->config.rv770.tile_config = gb_tiling_config; -	gb_tiling_config |= BACKEND_MAP(backend_map);  	WREG32(GB_TILING_CONFIG, gb_tiling_config);  	WREG32(DCP_TILING_CONFIG, (gb_tiling_config & 0xffff));  	WREG32(HDP_TILING_CONFIG, (gb_tiling_config & 0xffff)); - -	WREG32(CC_RB_BACKEND_DISABLE,      cc_rb_backend_disable); -	WREG32(CC_GC_SHADER_PIPE_CONFIG,   cc_gc_shader_pipe_config); -	WREG32(GC_USER_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config); -	WREG32(CC_SYS_RB_BACKEND_DISABLE,  cc_rb_backend_disable); +	WREG32(DMA_TILING_CONFIG, (gb_tiling_config & 0xffff)); +	WREG32(DMA_TILING_CONFIG2, (gb_tiling_config & 0xffff)); +	if (rdev->family == CHIP_RV730) { +		WREG32(UVD_UDEC_DB_TILING_CONFIG, (gb_tiling_config & 0xffff)); +		WREG32(UVD_UDEC_DBW_TILING_CONFIG, (gb_tiling_config & 0xffff)); +		WREG32(UVD_UDEC_TILING_CONFIG, (gb_tiling_config & 0xffff)); +	}  	WREG32(CGTS_SYS_TCC_DISABLE, 0);  	WREG32(CGTS_TCC_DISABLE, 0);  	WREG32(CGTS_USER_SYS_TCC_DISABLE, 0);  	WREG32(CGTS_USER_TCC_DISABLE, 0); -	num_qd_pipes = -		R7XX_MAX_PIPES - r600_count_pipe_bits((cc_gc_shader_pipe_config & INACTIVE_QD_PIPES_MASK) >> 8); + +	num_qd_pipes = R7XX_MAX_PIPES - r600_count_pipe_bits((cc_gc_shader_pipe_config & INACTIVE_QD_PIPES_MASK) >> 8);  	WREG32(VGT_OUT_DEALLOC_CNTL, (num_qd_pipes * 4) & DEALLOC_DIST_MASK);  	WREG32(VGT_VERTEX_REUSE_BLOCK_CNTL, ((num_qd_pipes * 4) - 2) & VTX_REUSE_DEPTH_MASK); @@ -727,6 +1423,9 @@ static void rv770_gpu_init(struct radeon_device *rdev)  				       ACK_FLUSH_CTL(3) |  				       SYNC_FLUSH_CTL)); +	if (rdev->family != CHIP_RV770) +		WREG32(SMX_SAR_CTL0, 0x00003f3f); +  	db_debug3 = RREG32(DB_DEBUG3);  	db_debug3 &= ~DB_CLK_OFF_DELAY(0x1f);  	switch (rdev->family) { @@ -760,8 +1459,6 @@ static void rv770_gpu_init(struct radeon_device *rdev)  	WREG32(VGT_NUM_INSTANCES, 1); -	WREG32(SPI_CONFIG_CNTL, GPR_WRITE_PRIORITY(0)); -  	WREG32(SPI_CONFIG_CNTL_1, VTX_DONE_DELAY(4));  	WREG32(CP_PERFMON_CNTL, 0); @@ -905,58 +1602,49 @@ static void rv770_gpu_init(struct radeon_device *rdev)  	WREG32(PA_CL_ENHANCE, (CLIP_VTX_REORDER_ENA |  					  NUM_CLIP_SEQ(3))); - +	WREG32(VC_ENHANCE, 0);  } -static int rv770_vram_scratch_init(struct radeon_device *rdev) +void r700_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc)  { -	int r; -	u64 gpu_addr; +	u64 size_bf, size_af; -	if (rdev->vram_scratch.robj == NULL) { -		r = radeon_bo_create(rdev, NULL, RADEON_GPU_PAGE_SIZE, -					true, RADEON_GEM_DOMAIN_VRAM, -					&rdev->vram_scratch.robj); -		if (r) { -			return r; -		} +	if (mc->mc_vram_size > 0xE0000000) { +		/* leave room for at least 512M GTT */ +		dev_warn(rdev->dev, "limiting VRAM\n"); +		mc->real_vram_size = 0xE0000000; +		mc->mc_vram_size = 0xE0000000;  	} - -	r = radeon_bo_reserve(rdev->vram_scratch.robj, false); -	if (unlikely(r != 0)) -		return r; -	r = radeon_bo_pin(rdev->vram_scratch.robj, -			  RADEON_GEM_DOMAIN_VRAM, &gpu_addr); -	if (r) { -		radeon_bo_unreserve(rdev->vram_scratch.robj); -		return r; -	} -	r = radeon_bo_kmap(rdev->vram_scratch.robj, -				(void **)&rdev->vram_scratch.ptr); -	if (r) -		radeon_bo_unpin(rdev->vram_scratch.robj); -	radeon_bo_unreserve(rdev->vram_scratch.robj); - -	return r; -} - -static void rv770_vram_scratch_fini(struct radeon_device *rdev) -{ -	int r; - -	if (rdev->vram_scratch.robj == NULL) { -		return; -	} -	r = radeon_bo_reserve(rdev->vram_scratch.robj, false); -	if (likely(r == 0)) { -		radeon_bo_kunmap(rdev->vram_scratch.robj); -		radeon_bo_unpin(rdev->vram_scratch.robj); -		radeon_bo_unreserve(rdev->vram_scratch.robj); +	if (rdev->flags & RADEON_IS_AGP) { +		size_bf = mc->gtt_start; +		size_af = mc->mc_mask - mc->gtt_end; +		if (size_bf > size_af) { +			if (mc->mc_vram_size > size_bf) { +				dev_warn(rdev->dev, "limiting VRAM\n"); +				mc->real_vram_size = size_bf; +				mc->mc_vram_size = size_bf; +			} +			mc->vram_start = mc->gtt_start - mc->mc_vram_size; +		} else { +			if (mc->mc_vram_size > size_af) { +				dev_warn(rdev->dev, "limiting VRAM\n"); +				mc->real_vram_size = size_af; +				mc->mc_vram_size = size_af; +			} +			mc->vram_start = mc->gtt_end + 1; +		} +		mc->vram_end = mc->vram_start + mc->mc_vram_size - 1; +		dev_info(rdev->dev, "VRAM: %lluM 0x%08llX - 0x%08llX (%lluM used)\n", +				mc->mc_vram_size >> 20, mc->vram_start, +				mc->vram_end, mc->real_vram_size >> 20); +	} else { +		radeon_vram_location(rdev, &rdev->mc, 0); +		rdev->mc.gtt_base_align = 0; +		radeon_gtt_location(rdev, mc);  	} -	radeon_bo_unref(&rdev->vram_scratch.robj);  } -int rv770_mc_init(struct radeon_device *rdev) +static int rv770_mc_init(struct radeon_device *rdev)  {  	u32 tmp;  	int chansize, numchan; @@ -995,8 +1683,7 @@ int rv770_mc_init(struct radeon_device *rdev)  	rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE);  	rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE);  	rdev->mc.visible_vram_size = rdev->mc.aper_size; -	rdev->mc.active_vram_size = rdev->mc.visible_vram_size; -	r600_vram_gtt_location(rdev, &rdev->mc); +	r700_vram_gtt_location(rdev, &rdev->mc);  	radeon_update_bandwidth_info(rdev);  	return 0; @@ -1004,17 +1691,19 @@ int rv770_mc_init(struct radeon_device *rdev)  static int rv770_startup(struct radeon_device *rdev)  { +	struct radeon_ring *ring;  	int r; -	if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) { -		r = r600_init_microcode(rdev); -		if (r) { -			DRM_ERROR("Failed to load firmware!\n"); -			return r; -		} -	} +	/* enable pcie gen2 link */ +	rv770_pcie_gen2_enable(rdev); + +	/* scratch needs to be initialized before MC */ +	r = r600_vram_scratch_init(rdev); +	if (r) +		return r;  	rv770_mc_program(rdev); +  	if (rdev->flags & RADEON_IS_AGP) {  		rv770_agp_enable(rdev);  	} else { @@ -1022,23 +1711,44 @@ static int rv770_startup(struct radeon_device *rdev)  		if (r)  			return r;  	} -	r = rv770_vram_scratch_init(rdev); -	if (r) -		return r; +  	rv770_gpu_init(rdev); -	r = r600_blit_init(rdev); -	if (r) { -		r600_blit_fini(rdev); -		rdev->asic->copy = NULL; -		dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r); -	}  	/* allocate wb buffer */  	r = radeon_wb_init(rdev);  	if (r)  		return r; +	r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX); +	if (r) { +		dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r); +		return r; +	} + +	r = radeon_fence_driver_start_ring(rdev, R600_RING_TYPE_DMA_INDEX); +	if (r) { +		dev_err(rdev->dev, "failed initializing DMA fences (%d).\n", r); +		return r; +	} + +	r = uvd_v2_2_resume(rdev); +	if (!r) { +		r = radeon_fence_driver_start_ring(rdev, +						   R600_RING_TYPE_UVD_INDEX); +		if (r) +			dev_err(rdev->dev, "UVD fences init error (%d).\n", r); +	} + +	if (r) +		rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_size = 0; +  	/* Enable IRQ */ +	if (!rdev->irq.installed) { +		r = radeon_irq_kms_init(rdev); +		if (r) +			return r; +	} +  	r = r600_irq_init(rdev);  	if (r) {  		DRM_ERROR("radeon: IH init failed (%d).\n", r); @@ -1047,9 +1757,18 @@ static int rv770_startup(struct radeon_device *rdev)  	}  	r600_irq_set(rdev); -	r = radeon_ring_init(rdev, rdev->cp.ring_size); +	ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX]; +	r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET, +			     RADEON_CP_PACKET2);  	if (r)  		return r; + +	ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX]; +	r = radeon_ring_init(rdev, ring, ring->ring_size, R600_WB_DMA_RPTR_OFFSET, +			     DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0)); +	if (r) +		return r; +  	r = rv770_cp_load_microcode(rdev);  	if (r)  		return r; @@ -1057,6 +1776,33 @@ static int rv770_startup(struct radeon_device *rdev)  	if (r)  		return r; +	r = r600_dma_resume(rdev); +	if (r) +		return r; + +	ring = &rdev->ring[R600_RING_TYPE_UVD_INDEX]; +	if (ring->ring_size) { +		r = radeon_ring_init(rdev, ring, ring->ring_size, 0, +				     RADEON_CP_PACKET2); +		if (!r) +			r = uvd_v1_0_init(rdev); + +		if (r) +			DRM_ERROR("radeon: failed initializing UVD (%d).\n", r); +	} + +	r = radeon_ib_pool_init(rdev); +	if (r) { +		dev_err(rdev->dev, "IB initialization failed (%d).\n", r); +		return r; +	} + +	r = r600_audio_init(rdev); +	if (r) { +		DRM_ERROR("radeon: audio init failed\n"); +		return r; +	} +  	return 0;  } @@ -1071,21 +1817,17 @@ int rv770_resume(struct radeon_device *rdev)  	/* post card */  	atom_asic_init(rdev->mode_info.atom_context); -	r = rv770_startup(rdev); -	if (r) { -		DRM_ERROR("r600 startup failed on resume\n"); -		return r; -	} +	/* init golden registers */ +	rv770_init_golden_registers(rdev); -	r = r600_ib_test(rdev); -	if (r) { -		DRM_ERROR("radeon: failled testing IB (%d).\n", r); -		return r; -	} +	if (rdev->pm.pm_method == PM_METHOD_DPM) +		radeon_pm_resume(rdev); -	r = r600_audio_init(rdev); +	rdev->accel_working = true; +	r = rv770_startup(rdev);  	if (r) { -		dev_err(rdev->dev, "radeon: audio init failed\n"); +		DRM_ERROR("r600 startup failed on resume\n"); +		rdev->accel_working = false;  		return r;  	} @@ -1095,23 +1837,16 @@ int rv770_resume(struct radeon_device *rdev)  int rv770_suspend(struct radeon_device *rdev)  { -	int r; - +	radeon_pm_suspend(rdev);  	r600_audio_fini(rdev); -	/* FIXME: we should wait for ring to be empty */ +	uvd_v1_0_fini(rdev); +	radeon_uvd_suspend(rdev);  	r700_cp_stop(rdev); -	rdev->cp.ready = false; +	r600_dma_stop(rdev);  	r600_irq_suspend(rdev);  	radeon_wb_disable(rdev);  	rv770_pcie_gart_disable(rdev); -	/* unpin shaders bo */ -	if (rdev->r600_blit.shader_obj) { -		r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); -		if (likely(r == 0)) { -			radeon_bo_unpin(rdev->r600_blit.shader_obj); -			radeon_bo_unreserve(rdev->r600_blit.shader_obj); -		} -	} +  	return 0;  } @@ -1125,13 +1860,6 @@ int rv770_init(struct radeon_device *rdev)  {  	int r; -	r = radeon_dummy_page_init(rdev); -	if (r) -		return r; -	/* This don't do much */ -	r = radeon_gem_init(rdev); -	if (r) -		return r;  	/* Read BIOS */  	if (!radeon_get_bios(rdev)) {  		if (ASIC_IS_AVIVO(rdev)) @@ -1146,7 +1874,7 @@ int rv770_init(struct radeon_device *rdev)  	if (r)  		return r;  	/* Post card if necessary */ -	if (!r600_card_posted(rdev)) { +	if (!radeon_card_posted(rdev)) {  		if (!rdev->bios) {  			dev_err(rdev->dev, "Card not posted and no BIOS - ignoring\n");  			return -EINVAL; @@ -1154,6 +1882,8 @@ int rv770_init(struct radeon_device *rdev)  		DRM_INFO("GPU not posted. posting now...\n");  		atom_asic_init(rdev->mode_info.atom_context);  	} +	/* init golden registers */ +	rv770_init_golden_registers(rdev);  	/* Initialize scratch registers */  	r600_scratch_init(rdev);  	/* Initialize surface registers */ @@ -1178,12 +1908,29 @@ int rv770_init(struct radeon_device *rdev)  	if (r)  		return r; -	r = radeon_irq_kms_init(rdev); -	if (r) -		return r; +	if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) { +		r = r600_init_microcode(rdev); +		if (r) { +			DRM_ERROR("Failed to load firmware!\n"); +			return r; +		} +	} + +	/* Initialize power management */ +	radeon_pm_init(rdev); + +	rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ring_obj = NULL; +	r600_ring_init(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX], 1024 * 1024); -	rdev->cp.ring_obj = NULL; -	r600_ring_init(rdev, 1024 * 1024); +	rdev->ring[R600_RING_TYPE_DMA_INDEX].ring_obj = NULL; +	r600_ring_init(rdev, &rdev->ring[R600_RING_TYPE_DMA_INDEX], 64 * 1024); + +	r = radeon_uvd_init(rdev); +	if (!r) { +		rdev->ring[R600_RING_TYPE_UVD_INDEX].ring_obj = NULL; +		r600_ring_init(rdev, &rdev->ring[R600_RING_TYPE_UVD_INDEX], +			       4096); +	}  	rdev->ih.ring_obj = NULL;  	r600_ih_ring_init(rdev, 64 * 1024); @@ -1197,44 +1944,31 @@ int rv770_init(struct radeon_device *rdev)  	if (r) {  		dev_err(rdev->dev, "disabling GPU acceleration\n");  		r700_cp_fini(rdev); +		r600_dma_fini(rdev);  		r600_irq_fini(rdev);  		radeon_wb_fini(rdev); +		radeon_ib_pool_fini(rdev);  		radeon_irq_kms_fini(rdev);  		rv770_pcie_gart_fini(rdev);  		rdev->accel_working = false;  	} -	if (rdev->accel_working) { -		r = radeon_ib_pool_init(rdev); -		if (r) { -			dev_err(rdev->dev, "IB initialization failed (%d).\n", r); -			rdev->accel_working = false; -		} else { -			r = r600_ib_test(rdev); -			if (r) { -				dev_err(rdev->dev, "IB test failed (%d).\n", r); -				rdev->accel_working = false; -			} -		} -	} - -	r = r600_audio_init(rdev); -	if (r) { -		dev_err(rdev->dev, "radeon: audio init failed\n"); -		return r; -	}  	return 0;  }  void rv770_fini(struct radeon_device *rdev)  { -	r600_blit_fini(rdev); +	radeon_pm_fini(rdev);  	r700_cp_fini(rdev); +	r600_dma_fini(rdev);  	r600_irq_fini(rdev);  	radeon_wb_fini(rdev); +	radeon_ib_pool_fini(rdev);  	radeon_irq_kms_fini(rdev); +	uvd_v1_0_fini(rdev); +	radeon_uvd_fini(rdev);  	rv770_pcie_gart_fini(rdev); -	rv770_vram_scratch_fini(rdev); +	r600_vram_scratch_fini(rdev);  	radeon_gem_fini(rdev);  	radeon_fence_driver_fini(rdev);  	radeon_agp_fini(rdev); @@ -1242,5 +1976,85 @@ void rv770_fini(struct radeon_device *rdev)  	radeon_atombios_fini(rdev);  	kfree(rdev->bios);  	rdev->bios = NULL; -	radeon_dummy_page_fini(rdev); +} + +static void rv770_pcie_gen2_enable(struct radeon_device *rdev) +{ +	u32 link_width_cntl, lanes, speed_cntl, tmp; +	u16 link_cntl2; + +	if (radeon_pcie_gen2 == 0) +		return; + +	if (rdev->flags & RADEON_IS_IGP) +		return; + +	if (!(rdev->flags & RADEON_IS_PCIE)) +		return; + +	/* x2 cards have a special sequence */ +	if (ASIC_IS_X2(rdev)) +		return; + +	if ((rdev->pdev->bus->max_bus_speed != PCIE_SPEED_5_0GT) && +		(rdev->pdev->bus->max_bus_speed != PCIE_SPEED_8_0GT)) +		return; + +	DRM_INFO("enabling PCIE gen 2 link speeds, disable with radeon.pcie_gen2=0\n"); + +	/* advertise upconfig capability */ +	link_width_cntl = RREG32_PCIE_PORT(PCIE_LC_LINK_WIDTH_CNTL); +	link_width_cntl &= ~LC_UPCONFIGURE_DIS; +	WREG32_PCIE_PORT(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl); +	link_width_cntl = RREG32_PCIE_PORT(PCIE_LC_LINK_WIDTH_CNTL); +	if (link_width_cntl & LC_RENEGOTIATION_SUPPORT) { +		lanes = (link_width_cntl & LC_LINK_WIDTH_RD_MASK) >> LC_LINK_WIDTH_RD_SHIFT; +		link_width_cntl &= ~(LC_LINK_WIDTH_MASK | +				     LC_RECONFIG_ARC_MISSING_ESCAPE); +		link_width_cntl |= lanes | LC_RECONFIG_NOW | +			LC_RENEGOTIATE_EN | LC_UPCONFIGURE_SUPPORT; +		WREG32_PCIE_PORT(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl); +	} else { +		link_width_cntl |= LC_UPCONFIGURE_DIS; +		WREG32_PCIE_PORT(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl); +	} + +	speed_cntl = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL); +	if ((speed_cntl & LC_OTHER_SIDE_EVER_SENT_GEN2) && +	    (speed_cntl & LC_OTHER_SIDE_SUPPORTS_GEN2)) { + +		tmp = RREG32(0x541c); +		WREG32(0x541c, tmp | 0x8); +		WREG32(MM_CFGREGS_CNTL, MM_WR_TO_CFG_EN); +		link_cntl2 = RREG16(0x4088); +		link_cntl2 &= ~TARGET_LINK_SPEED_MASK; +		link_cntl2 |= 0x2; +		WREG16(0x4088, link_cntl2); +		WREG32(MM_CFGREGS_CNTL, 0); + +		speed_cntl = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL); +		speed_cntl &= ~LC_TARGET_LINK_SPEED_OVERRIDE_EN; +		WREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL, speed_cntl); + +		speed_cntl = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL); +		speed_cntl |= LC_CLR_FAILED_SPD_CHANGE_CNT; +		WREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL, speed_cntl); + +		speed_cntl = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL); +		speed_cntl &= ~LC_CLR_FAILED_SPD_CHANGE_CNT; +		WREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL, speed_cntl); + +		speed_cntl = RREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL); +		speed_cntl |= LC_GEN2_EN_STRAP; +		WREG32_PCIE_PORT(PCIE_LC_SPEED_CNTL, speed_cntl); + +	} else { +		link_width_cntl = RREG32_PCIE_PORT(PCIE_LC_LINK_WIDTH_CNTL); +		/* XXX: only disable it if gen1 bridge vendor == 0x111d or 0x1106 */ +		if (1) +			link_width_cntl |= LC_UPCONFIGURE_DIS; +		else +			link_width_cntl &= ~LC_UPCONFIGURE_DIS; +		WREG32_PCIE_PORT(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl); +	}  }  | 
