xref: /dragonfly/sys/dev/drm/radeon/rv770.c (revision b403bed8)
1926deccbSFrançois Tigeot /*
2926deccbSFrançois Tigeot  * Copyright 2008 Advanced Micro Devices, Inc.
3926deccbSFrançois Tigeot  * Copyright 2008 Red Hat Inc.
4926deccbSFrançois Tigeot  * Copyright 2009 Jerome Glisse.
5926deccbSFrançois Tigeot  *
6926deccbSFrançois Tigeot  * Permission is hereby granted, free of charge, to any person obtaining a
7926deccbSFrançois Tigeot  * copy of this software and associated documentation files (the "Software"),
8926deccbSFrançois Tigeot  * to deal in the Software without restriction, including without limitation
9926deccbSFrançois Tigeot  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10926deccbSFrançois Tigeot  * and/or sell copies of the Software, and to permit persons to whom the
11926deccbSFrançois Tigeot  * Software is furnished to do so, subject to the following conditions:
12926deccbSFrançois Tigeot  *
13926deccbSFrançois Tigeot  * The above copyright notice and this permission notice shall be included in
14926deccbSFrançois Tigeot  * all copies or substantial portions of the Software.
15926deccbSFrançois Tigeot  *
16926deccbSFrançois Tigeot  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17926deccbSFrançois Tigeot  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18926deccbSFrançois Tigeot  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19926deccbSFrançois Tigeot  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20926deccbSFrançois Tigeot  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21926deccbSFrançois Tigeot  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22926deccbSFrançois Tigeot  * OTHER DEALINGS IN THE SOFTWARE.
23926deccbSFrançois Tigeot  *
24926deccbSFrançois Tigeot  * Authors: Dave Airlie
25926deccbSFrançois Tigeot  *          Alex Deucher
26926deccbSFrançois Tigeot  *          Jerome Glisse
27926deccbSFrançois Tigeot  *
28926deccbSFrançois Tigeot  * $FreeBSD: head/sys/dev/drm2/radeon/rv770.c 254885 2013-08-25 19:37:15Z dumbbell $
29926deccbSFrançois Tigeot  */
30926deccbSFrançois Tigeot 
31926deccbSFrançois Tigeot #include <drm/drmP.h>
32926deccbSFrançois Tigeot #include "radeon.h"
33926deccbSFrançois Tigeot #include "radeon_asic.h"
34926deccbSFrançois Tigeot #include <uapi_drm/radeon_drm.h>
35926deccbSFrançois Tigeot #include "rv770d.h"
36926deccbSFrançois Tigeot #include "atom.h"
37926deccbSFrançois Tigeot #include "avivod.h"
38926deccbSFrançois Tigeot 
39926deccbSFrançois Tigeot #define R700_PFP_UCODE_SIZE 848
40926deccbSFrançois Tigeot #define R700_PM4_UCODE_SIZE 1360
41926deccbSFrançois Tigeot 
42926deccbSFrançois Tigeot static void rv770_gpu_init(struct radeon_device *rdev);
43926deccbSFrançois Tigeot static void rv770_pcie_gen2_enable(struct radeon_device *rdev);
44926deccbSFrançois Tigeot 
45*b403bed8SMichael Neumann #define PCIE_BUS_CLK                10000
46*b403bed8SMichael Neumann #define TCLK                        (PCIE_BUS_CLK / 10)
47*b403bed8SMichael Neumann 
48*b403bed8SMichael Neumann /**
49*b403bed8SMichael Neumann  * rv770_get_xclk - get the xclk
50*b403bed8SMichael Neumann  *
51*b403bed8SMichael Neumann  * @rdev: radeon_device pointer
52*b403bed8SMichael Neumann  *
53*b403bed8SMichael Neumann  * Returns the reference clock used by the gfx engine
54*b403bed8SMichael Neumann  * (r7xx-cayman).
55*b403bed8SMichael Neumann  */
56*b403bed8SMichael Neumann u32 rv770_get_xclk(struct radeon_device *rdev)
57*b403bed8SMichael Neumann {
58*b403bed8SMichael Neumann 	u32 reference_clock = rdev->clock.spll.reference_freq;
59*b403bed8SMichael Neumann 	u32 tmp = RREG32(CG_CLKPIN_CNTL);
60*b403bed8SMichael Neumann 
61*b403bed8SMichael Neumann 	if (tmp & MUX_TCLK_TO_XCLK)
62*b403bed8SMichael Neumann 		return TCLK;
63*b403bed8SMichael Neumann 
64*b403bed8SMichael Neumann 	if (tmp & XTALIN_DIVIDE)
65*b403bed8SMichael Neumann 		return reference_clock / 4;
66*b403bed8SMichael Neumann 
67*b403bed8SMichael Neumann 	return reference_clock;
68*b403bed8SMichael Neumann }
69*b403bed8SMichael Neumann 
70926deccbSFrançois Tigeot u32 rv770_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base)
71926deccbSFrançois Tigeot {
72926deccbSFrançois Tigeot 	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
73926deccbSFrançois Tigeot 	u32 tmp = RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset);
74926deccbSFrançois Tigeot 	int i;
75926deccbSFrançois Tigeot 
76926deccbSFrançois Tigeot 	/* Lock the graphics update lock */
77926deccbSFrançois Tigeot 	tmp |= AVIVO_D1GRPH_UPDATE_LOCK;
78926deccbSFrançois Tigeot 	WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp);
79926deccbSFrançois Tigeot 
80926deccbSFrançois Tigeot 	/* update the scanout addresses */
81926deccbSFrançois Tigeot 	if (radeon_crtc->crtc_id) {
82926deccbSFrançois Tigeot 		WREG32(D2GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, upper_32_bits(crtc_base));
83926deccbSFrançois Tigeot 		WREG32(D2GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, upper_32_bits(crtc_base));
84926deccbSFrançois Tigeot 	} else {
85926deccbSFrançois Tigeot 		WREG32(D1GRPH_SECONDARY_SURFACE_ADDRESS_HIGH, upper_32_bits(crtc_base));
86926deccbSFrançois Tigeot 		WREG32(D1GRPH_PRIMARY_SURFACE_ADDRESS_HIGH, upper_32_bits(crtc_base));
87926deccbSFrançois Tigeot 	}
88926deccbSFrançois Tigeot 	WREG32(D1GRPH_SECONDARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
89926deccbSFrançois Tigeot 	       (u32)crtc_base);
90926deccbSFrançois Tigeot 	WREG32(D1GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
91926deccbSFrançois Tigeot 	       (u32)crtc_base);
92926deccbSFrançois Tigeot 
93926deccbSFrançois Tigeot 	/* Wait for update_pending to go high. */
94926deccbSFrançois Tigeot 	for (i = 0; i < rdev->usec_timeout; i++) {
95926deccbSFrançois Tigeot 		if (RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING)
96926deccbSFrançois Tigeot 			break;
97926deccbSFrançois Tigeot 		DRM_UDELAY(1);
98926deccbSFrançois Tigeot 	}
99926deccbSFrançois Tigeot 	DRM_DEBUG("Update pending now high. Unlocking vupdate_lock.\n");
100926deccbSFrançois Tigeot 
101926deccbSFrançois Tigeot 	/* Unlock the lock, so double-buffering can take place inside vblank */
102926deccbSFrançois Tigeot 	tmp &= ~AVIVO_D1GRPH_UPDATE_LOCK;
103926deccbSFrançois Tigeot 	WREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset, tmp);
104926deccbSFrançois Tigeot 
105926deccbSFrançois Tigeot 	/* Return current update_pending status: */
106926deccbSFrançois Tigeot 	return RREG32(AVIVO_D1GRPH_UPDATE + radeon_crtc->crtc_offset) & AVIVO_D1GRPH_SURFACE_UPDATE_PENDING;
107926deccbSFrançois Tigeot }
108926deccbSFrançois Tigeot 
109926deccbSFrançois Tigeot /* get temperature in millidegrees */
110926deccbSFrançois Tigeot int rv770_get_temp(struct radeon_device *rdev)
111926deccbSFrançois Tigeot {
112926deccbSFrançois Tigeot 	u32 temp = (RREG32(CG_MULT_THERMAL_STATUS) & ASIC_T_MASK) >>
113926deccbSFrançois Tigeot 		ASIC_T_SHIFT;
114926deccbSFrançois Tigeot 	int actual_temp;
115926deccbSFrançois Tigeot 
116926deccbSFrançois Tigeot 	if (temp & 0x400)
117926deccbSFrançois Tigeot 		actual_temp = -256;
118926deccbSFrançois Tigeot 	else if (temp & 0x200)
119926deccbSFrançois Tigeot 		actual_temp = 255;
120926deccbSFrançois Tigeot 	else if (temp & 0x100) {
121926deccbSFrançois Tigeot 		actual_temp = temp & 0x1ff;
122926deccbSFrançois Tigeot 		actual_temp |= ~0x1ff;
123926deccbSFrançois Tigeot 	} else
124926deccbSFrançois Tigeot 		actual_temp = temp & 0xff;
125926deccbSFrançois Tigeot 
126926deccbSFrançois Tigeot 	return (actual_temp * 1000) / 2;
127926deccbSFrançois Tigeot }
128926deccbSFrançois Tigeot 
129926deccbSFrançois Tigeot void rv770_pm_misc(struct radeon_device *rdev)
130926deccbSFrançois Tigeot {
131926deccbSFrançois Tigeot 	int req_ps_idx = rdev->pm.requested_power_state_index;
132926deccbSFrançois Tigeot 	int req_cm_idx = rdev->pm.requested_clock_mode_index;
133926deccbSFrançois Tigeot 	struct radeon_power_state *ps = &rdev->pm.power_state[req_ps_idx];
134926deccbSFrançois Tigeot 	struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage;
135926deccbSFrançois Tigeot 
136926deccbSFrançois Tigeot 	if ((voltage->type == VOLTAGE_SW) && voltage->voltage) {
137926deccbSFrançois Tigeot 		/* 0xff01 is a flag rather then an actual voltage */
138926deccbSFrançois Tigeot 		if (voltage->voltage == 0xff01)
139926deccbSFrançois Tigeot 			return;
140926deccbSFrançois Tigeot 		if (voltage->voltage != rdev->pm.current_vddc) {
141926deccbSFrançois Tigeot 			radeon_atom_set_voltage(rdev, voltage->voltage, SET_VOLTAGE_TYPE_ASIC_VDDC);
142926deccbSFrançois Tigeot 			rdev->pm.current_vddc = voltage->voltage;
143926deccbSFrançois Tigeot 			DRM_DEBUG("Setting: v: %d\n", voltage->voltage);
144926deccbSFrançois Tigeot 		}
145926deccbSFrançois Tigeot 	}
146926deccbSFrançois Tigeot }
147926deccbSFrançois Tigeot 
148926deccbSFrançois Tigeot /*
149926deccbSFrançois Tigeot  * GART
150926deccbSFrançois Tigeot  */
151926deccbSFrançois Tigeot static int rv770_pcie_gart_enable(struct radeon_device *rdev)
152926deccbSFrançois Tigeot {
153926deccbSFrançois Tigeot 	u32 tmp;
154926deccbSFrançois Tigeot 	int r, i;
155926deccbSFrançois Tigeot 
156926deccbSFrançois Tigeot 	if (rdev->gart.robj == NULL) {
157926deccbSFrançois Tigeot 		dev_err(rdev->dev, "No VRAM object for PCIE GART.\n");
158926deccbSFrançois Tigeot 		return -EINVAL;
159926deccbSFrançois Tigeot 	}
160926deccbSFrançois Tigeot 	r = radeon_gart_table_vram_pin(rdev);
161926deccbSFrançois Tigeot 	if (r)
162926deccbSFrançois Tigeot 		return r;
163926deccbSFrançois Tigeot 	radeon_gart_restore(rdev);
164926deccbSFrançois Tigeot 	/* Setup L2 cache */
165926deccbSFrançois Tigeot 	WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | ENABLE_L2_FRAGMENT_PROCESSING |
166926deccbSFrançois Tigeot 				ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE |
167926deccbSFrançois Tigeot 				EFFECTIVE_L2_QUEUE_SIZE(7));
168926deccbSFrançois Tigeot 	WREG32(VM_L2_CNTL2, 0);
169926deccbSFrançois Tigeot 	WREG32(VM_L2_CNTL3, BANK_SELECT(0) | CACHE_UPDATE_MODE(2));
170926deccbSFrançois Tigeot 	/* Setup TLB control */
171926deccbSFrançois Tigeot 	tmp = ENABLE_L1_TLB | ENABLE_L1_FRAGMENT_PROCESSING |
172926deccbSFrançois Tigeot 		SYSTEM_ACCESS_MODE_NOT_IN_SYS |
173926deccbSFrançois Tigeot 		SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU |
174926deccbSFrançois Tigeot 		EFFECTIVE_L1_TLB_SIZE(5) | EFFECTIVE_L1_QUEUE_SIZE(5);
175926deccbSFrançois Tigeot 	WREG32(MC_VM_MD_L1_TLB0_CNTL, tmp);
176926deccbSFrançois Tigeot 	WREG32(MC_VM_MD_L1_TLB1_CNTL, tmp);
177926deccbSFrançois Tigeot 	WREG32(MC_VM_MD_L1_TLB2_CNTL, tmp);
178926deccbSFrançois Tigeot 	if (rdev->family == CHIP_RV740)
179926deccbSFrançois Tigeot 		WREG32(MC_VM_MD_L1_TLB3_CNTL, tmp);
180926deccbSFrançois Tigeot 	WREG32(MC_VM_MB_L1_TLB0_CNTL, tmp);
181926deccbSFrançois Tigeot 	WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp);
182926deccbSFrançois Tigeot 	WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp);
183926deccbSFrançois Tigeot 	WREG32(MC_VM_MB_L1_TLB3_CNTL, tmp);
184926deccbSFrançois Tigeot 	WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR, rdev->mc.gtt_start >> 12);
185926deccbSFrançois Tigeot 	WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, rdev->mc.gtt_end >> 12);
186926deccbSFrançois Tigeot 	WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, rdev->gart.table_addr >> 12);
187926deccbSFrançois Tigeot 	WREG32(VM_CONTEXT0_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(0) |
188926deccbSFrançois Tigeot 				RANGE_PROTECTION_FAULT_ENABLE_DEFAULT);
189926deccbSFrançois Tigeot 	WREG32(VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR,
190926deccbSFrançois Tigeot 			(u32)(rdev->dummy_page.addr >> 12));
191926deccbSFrançois Tigeot 	for (i = 1; i < 7; i++)
192926deccbSFrançois Tigeot 		WREG32(VM_CONTEXT0_CNTL + (i * 4), 0);
193926deccbSFrançois Tigeot 
194926deccbSFrançois Tigeot 	r600_pcie_gart_tlb_flush(rdev);
195926deccbSFrançois Tigeot 	DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n",
196926deccbSFrançois Tigeot 		 (unsigned)(rdev->mc.gtt_size >> 20),
197926deccbSFrançois Tigeot 		 (unsigned long long)rdev->gart.table_addr);
198926deccbSFrançois Tigeot 	rdev->gart.ready = true;
199926deccbSFrançois Tigeot 	return 0;
200926deccbSFrançois Tigeot }
201926deccbSFrançois Tigeot 
202926deccbSFrançois Tigeot static void rv770_pcie_gart_disable(struct radeon_device *rdev)
203926deccbSFrançois Tigeot {
204926deccbSFrançois Tigeot 	u32 tmp;
205926deccbSFrançois Tigeot 	int i;
206926deccbSFrançois Tigeot 
207926deccbSFrançois Tigeot 	/* Disable all tables */
208926deccbSFrançois Tigeot 	for (i = 0; i < 7; i++)
209926deccbSFrançois Tigeot 		WREG32(VM_CONTEXT0_CNTL + (i * 4), 0);
210926deccbSFrançois Tigeot 
211926deccbSFrançois Tigeot 	/* Setup L2 cache */
212926deccbSFrançois Tigeot 	WREG32(VM_L2_CNTL, ENABLE_L2_FRAGMENT_PROCESSING |
213926deccbSFrançois Tigeot 				EFFECTIVE_L2_QUEUE_SIZE(7));
214926deccbSFrançois Tigeot 	WREG32(VM_L2_CNTL2, 0);
215926deccbSFrançois Tigeot 	WREG32(VM_L2_CNTL3, BANK_SELECT(0) | CACHE_UPDATE_MODE(2));
216926deccbSFrançois Tigeot 	/* Setup TLB control */
217926deccbSFrançois Tigeot 	tmp = EFFECTIVE_L1_TLB_SIZE(5) | EFFECTIVE_L1_QUEUE_SIZE(5);
218926deccbSFrançois Tigeot 	WREG32(MC_VM_MD_L1_TLB0_CNTL, tmp);
219926deccbSFrançois Tigeot 	WREG32(MC_VM_MD_L1_TLB1_CNTL, tmp);
220926deccbSFrançois Tigeot 	WREG32(MC_VM_MD_L1_TLB2_CNTL, tmp);
221926deccbSFrançois Tigeot 	WREG32(MC_VM_MB_L1_TLB0_CNTL, tmp);
222926deccbSFrançois Tigeot 	WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp);
223926deccbSFrançois Tigeot 	WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp);
224926deccbSFrançois Tigeot 	WREG32(MC_VM_MB_L1_TLB3_CNTL, tmp);
225926deccbSFrançois Tigeot 	radeon_gart_table_vram_unpin(rdev);
226926deccbSFrançois Tigeot }
227926deccbSFrançois Tigeot 
228926deccbSFrançois Tigeot static void rv770_pcie_gart_fini(struct radeon_device *rdev)
229926deccbSFrançois Tigeot {
230926deccbSFrançois Tigeot 	radeon_gart_fini(rdev);
231926deccbSFrançois Tigeot 	rv770_pcie_gart_disable(rdev);
232926deccbSFrançois Tigeot 	radeon_gart_table_vram_free(rdev);
233926deccbSFrançois Tigeot }
234926deccbSFrançois Tigeot 
235926deccbSFrançois Tigeot 
236926deccbSFrançois Tigeot static void rv770_agp_enable(struct radeon_device *rdev)
237926deccbSFrançois Tigeot {
238926deccbSFrançois Tigeot 	u32 tmp;
239926deccbSFrançois Tigeot 	int i;
240926deccbSFrançois Tigeot 
241926deccbSFrançois Tigeot 	/* Setup L2 cache */
242926deccbSFrançois Tigeot 	WREG32(VM_L2_CNTL, ENABLE_L2_CACHE | ENABLE_L2_FRAGMENT_PROCESSING |
243926deccbSFrançois Tigeot 				ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE |
244926deccbSFrançois Tigeot 				EFFECTIVE_L2_QUEUE_SIZE(7));
245926deccbSFrançois Tigeot 	WREG32(VM_L2_CNTL2, 0);
246926deccbSFrançois Tigeot 	WREG32(VM_L2_CNTL3, BANK_SELECT(0) | CACHE_UPDATE_MODE(2));
247926deccbSFrançois Tigeot 	/* Setup TLB control */
248926deccbSFrançois Tigeot 	tmp = ENABLE_L1_TLB | ENABLE_L1_FRAGMENT_PROCESSING |
249926deccbSFrançois Tigeot 		SYSTEM_ACCESS_MODE_NOT_IN_SYS |
250926deccbSFrançois Tigeot 		SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU |
251926deccbSFrançois Tigeot 		EFFECTIVE_L1_TLB_SIZE(5) | EFFECTIVE_L1_QUEUE_SIZE(5);
252926deccbSFrançois Tigeot 	WREG32(MC_VM_MD_L1_TLB0_CNTL, tmp);
253926deccbSFrançois Tigeot 	WREG32(MC_VM_MD_L1_TLB1_CNTL, tmp);
254926deccbSFrançois Tigeot 	WREG32(MC_VM_MD_L1_TLB2_CNTL, tmp);
255926deccbSFrançois Tigeot 	WREG32(MC_VM_MB_L1_TLB0_CNTL, tmp);
256926deccbSFrançois Tigeot 	WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp);
257926deccbSFrançois Tigeot 	WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp);
258926deccbSFrançois Tigeot 	WREG32(MC_VM_MB_L1_TLB3_CNTL, tmp);
259926deccbSFrançois Tigeot 	for (i = 0; i < 7; i++)
260926deccbSFrançois Tigeot 		WREG32(VM_CONTEXT0_CNTL + (i * 4), 0);
261926deccbSFrançois Tigeot }
262926deccbSFrançois Tigeot 
263926deccbSFrançois Tigeot static void rv770_mc_program(struct radeon_device *rdev)
264926deccbSFrançois Tigeot {
265926deccbSFrançois Tigeot 	struct rv515_mc_save save;
266926deccbSFrançois Tigeot 	u32 tmp;
267926deccbSFrançois Tigeot 	int i, j;
268926deccbSFrançois Tigeot 
269926deccbSFrançois Tigeot 	/* Initialize HDP */
270926deccbSFrançois Tigeot 	for (i = 0, j = 0; i < 32; i++, j += 0x18) {
271926deccbSFrançois Tigeot 		WREG32((0x2c14 + j), 0x00000000);
272926deccbSFrançois Tigeot 		WREG32((0x2c18 + j), 0x00000000);
273926deccbSFrançois Tigeot 		WREG32((0x2c1c + j), 0x00000000);
274926deccbSFrançois Tigeot 		WREG32((0x2c20 + j), 0x00000000);
275926deccbSFrançois Tigeot 		WREG32((0x2c24 + j), 0x00000000);
276926deccbSFrançois Tigeot 	}
277926deccbSFrançois Tigeot 	/* r7xx hw bug.  Read from HDP_DEBUG1 rather
278926deccbSFrançois Tigeot 	 * than writing to HDP_REG_COHERENCY_FLUSH_CNTL
279926deccbSFrançois Tigeot 	 */
280926deccbSFrançois Tigeot 	tmp = RREG32(HDP_DEBUG1);
281926deccbSFrançois Tigeot 
282926deccbSFrançois Tigeot 	rv515_mc_stop(rdev, &save);
283926deccbSFrançois Tigeot 	if (r600_mc_wait_for_idle(rdev)) {
284926deccbSFrançois Tigeot 		dev_warn(rdev->dev, "Wait for MC idle timedout !\n");
285926deccbSFrançois Tigeot 	}
286926deccbSFrançois Tigeot 	/* Lockout access through VGA aperture*/
287926deccbSFrançois Tigeot 	WREG32(VGA_HDP_CONTROL, VGA_MEMORY_DISABLE);
288926deccbSFrançois Tigeot 	/* Update configuration */
289926deccbSFrançois Tigeot 	if (rdev->flags & RADEON_IS_AGP) {
290926deccbSFrançois Tigeot 		if (rdev->mc.vram_start < rdev->mc.gtt_start) {
291926deccbSFrançois Tigeot 			/* VRAM before AGP */
292926deccbSFrançois Tigeot 			WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR,
293926deccbSFrançois Tigeot 				rdev->mc.vram_start >> 12);
294926deccbSFrançois Tigeot 			WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR,
295926deccbSFrançois Tigeot 				rdev->mc.gtt_end >> 12);
296926deccbSFrançois Tigeot 		} else {
297926deccbSFrançois Tigeot 			/* VRAM after AGP */
298926deccbSFrançois Tigeot 			WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR,
299926deccbSFrançois Tigeot 				rdev->mc.gtt_start >> 12);
300926deccbSFrançois Tigeot 			WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR,
301926deccbSFrançois Tigeot 				rdev->mc.vram_end >> 12);
302926deccbSFrançois Tigeot 		}
303926deccbSFrançois Tigeot 	} else {
304926deccbSFrançois Tigeot 		WREG32(MC_VM_SYSTEM_APERTURE_LOW_ADDR,
305926deccbSFrançois Tigeot 			rdev->mc.vram_start >> 12);
306926deccbSFrançois Tigeot 		WREG32(MC_VM_SYSTEM_APERTURE_HIGH_ADDR,
307926deccbSFrançois Tigeot 			rdev->mc.vram_end >> 12);
308926deccbSFrançois Tigeot 	}
309926deccbSFrançois Tigeot 	WREG32(MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, rdev->vram_scratch.gpu_addr >> 12);
310926deccbSFrançois Tigeot 	tmp = ((rdev->mc.vram_end >> 24) & 0xFFFF) << 16;
311926deccbSFrançois Tigeot 	tmp |= ((rdev->mc.vram_start >> 24) & 0xFFFF);
312926deccbSFrançois Tigeot 	WREG32(MC_VM_FB_LOCATION, tmp);
313926deccbSFrançois Tigeot 	WREG32(HDP_NONSURFACE_BASE, (rdev->mc.vram_start >> 8));
314926deccbSFrançois Tigeot 	WREG32(HDP_NONSURFACE_INFO, (2 << 7));
315926deccbSFrançois Tigeot 	WREG32(HDP_NONSURFACE_SIZE, 0x3FFFFFFF);
316926deccbSFrançois Tigeot 	if (rdev->flags & RADEON_IS_AGP) {
317926deccbSFrançois Tigeot 		WREG32(MC_VM_AGP_TOP, rdev->mc.gtt_end >> 16);
318926deccbSFrançois Tigeot 		WREG32(MC_VM_AGP_BOT, rdev->mc.gtt_start >> 16);
319926deccbSFrançois Tigeot 		WREG32(MC_VM_AGP_BASE, rdev->mc.agp_base >> 22);
320926deccbSFrançois Tigeot 	} else {
321926deccbSFrançois Tigeot 		WREG32(MC_VM_AGP_BASE, 0);
322926deccbSFrançois Tigeot 		WREG32(MC_VM_AGP_TOP, 0x0FFFFFFF);
323926deccbSFrançois Tigeot 		WREG32(MC_VM_AGP_BOT, 0x0FFFFFFF);
324926deccbSFrançois Tigeot 	}
325926deccbSFrançois Tigeot 	if (r600_mc_wait_for_idle(rdev)) {
326926deccbSFrançois Tigeot 		dev_warn(rdev->dev, "Wait for MC idle timedout !\n");
327926deccbSFrançois Tigeot 	}
328926deccbSFrançois Tigeot 	rv515_mc_resume(rdev, &save);
329926deccbSFrançois Tigeot 	/* we need to own VRAM, so turn off the VGA renderer here
330926deccbSFrançois Tigeot 	 * to stop it overwriting our objects */
331926deccbSFrançois Tigeot 	rv515_vga_render_disable(rdev);
332926deccbSFrançois Tigeot }
333926deccbSFrançois Tigeot 
334926deccbSFrançois Tigeot 
335926deccbSFrançois Tigeot /*
336926deccbSFrançois Tigeot  * CP.
337926deccbSFrançois Tigeot  */
338926deccbSFrançois Tigeot void r700_cp_stop(struct radeon_device *rdev)
339926deccbSFrançois Tigeot {
340926deccbSFrançois Tigeot 	radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size);
341926deccbSFrançois Tigeot 	WREG32(CP_ME_CNTL, (CP_ME_HALT | CP_PFP_HALT));
342926deccbSFrançois Tigeot 	WREG32(SCRATCH_UMSK, 0);
343926deccbSFrançois Tigeot 	rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ready = false;
344926deccbSFrançois Tigeot }
345926deccbSFrançois Tigeot 
346926deccbSFrançois Tigeot static int rv770_cp_load_microcode(struct radeon_device *rdev)
347926deccbSFrançois Tigeot {
348926deccbSFrançois Tigeot 	const __be32 *fw_data;
349926deccbSFrançois Tigeot 	int i;
350926deccbSFrançois Tigeot 
351926deccbSFrançois Tigeot 	if (!rdev->me_fw || !rdev->pfp_fw)
352926deccbSFrançois Tigeot 		return -EINVAL;
353926deccbSFrançois Tigeot 
354926deccbSFrançois Tigeot 	r700_cp_stop(rdev);
355926deccbSFrançois Tigeot 	WREG32(CP_RB_CNTL,
356926deccbSFrançois Tigeot #ifdef __BIG_ENDIAN
357926deccbSFrançois Tigeot 	       BUF_SWAP_32BIT |
358926deccbSFrançois Tigeot #endif
359926deccbSFrançois Tigeot 	       RB_NO_UPDATE | RB_BLKSZ(15) | RB_BUFSZ(3));
360926deccbSFrançois Tigeot 
361926deccbSFrançois Tigeot 	/* Reset cp */
362926deccbSFrançois Tigeot 	WREG32(GRBM_SOFT_RESET, SOFT_RESET_CP);
363926deccbSFrançois Tigeot 	RREG32(GRBM_SOFT_RESET);
364926deccbSFrançois Tigeot 	DRM_MDELAY(15);
365926deccbSFrançois Tigeot 	WREG32(GRBM_SOFT_RESET, 0);
366926deccbSFrançois Tigeot 
367926deccbSFrançois Tigeot 	fw_data = (const __be32 *)rdev->pfp_fw->data;
368926deccbSFrançois Tigeot 	WREG32(CP_PFP_UCODE_ADDR, 0);
369926deccbSFrançois Tigeot 	for (i = 0; i < R700_PFP_UCODE_SIZE; i++)
370926deccbSFrançois Tigeot 		WREG32(CP_PFP_UCODE_DATA, be32_to_cpup(fw_data++));
371926deccbSFrançois Tigeot 	WREG32(CP_PFP_UCODE_ADDR, 0);
372926deccbSFrançois Tigeot 
373926deccbSFrançois Tigeot 	fw_data = (const __be32 *)rdev->me_fw->data;
374926deccbSFrançois Tigeot 	WREG32(CP_ME_RAM_WADDR, 0);
375926deccbSFrançois Tigeot 	for (i = 0; i < R700_PM4_UCODE_SIZE; i++)
376926deccbSFrançois Tigeot 		WREG32(CP_ME_RAM_DATA, be32_to_cpup(fw_data++));
377926deccbSFrançois Tigeot 
378926deccbSFrançois Tigeot 	WREG32(CP_PFP_UCODE_ADDR, 0);
379926deccbSFrançois Tigeot 	WREG32(CP_ME_RAM_WADDR, 0);
380926deccbSFrançois Tigeot 	WREG32(CP_ME_RAM_RADDR, 0);
381926deccbSFrançois Tigeot 	return 0;
382926deccbSFrançois Tigeot }
383926deccbSFrançois Tigeot 
384926deccbSFrançois Tigeot void r700_cp_fini(struct radeon_device *rdev)
385926deccbSFrançois Tigeot {
386926deccbSFrançois Tigeot 	struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
387926deccbSFrançois Tigeot 	r700_cp_stop(rdev);
388926deccbSFrançois Tigeot 	radeon_ring_fini(rdev, ring);
389926deccbSFrançois Tigeot 	radeon_scratch_free(rdev, ring->rptr_save_reg);
390926deccbSFrançois Tigeot }
391926deccbSFrançois Tigeot 
392926deccbSFrançois Tigeot /*
393926deccbSFrançois Tigeot  * Core functions
394926deccbSFrançois Tigeot  */
395926deccbSFrançois Tigeot static void rv770_gpu_init(struct radeon_device *rdev)
396926deccbSFrançois Tigeot {
397926deccbSFrançois Tigeot 	int i, j, num_qd_pipes;
398926deccbSFrançois Tigeot 	u32 ta_aux_cntl;
399926deccbSFrançois Tigeot 	u32 sx_debug_1;
400926deccbSFrançois Tigeot 	u32 smx_dc_ctl0;
401926deccbSFrançois Tigeot 	u32 db_debug3;
402926deccbSFrançois Tigeot 	u32 num_gs_verts_per_thread;
403926deccbSFrançois Tigeot 	u32 vgt_gs_per_es;
404926deccbSFrançois Tigeot 	u32 gs_prim_buffer_depth = 0;
405926deccbSFrançois Tigeot 	u32 sq_ms_fifo_sizes;
406926deccbSFrançois Tigeot 	u32 sq_config;
407926deccbSFrançois Tigeot 	u32 sq_thread_resource_mgmt;
408926deccbSFrançois Tigeot 	u32 hdp_host_path_cntl;
409926deccbSFrançois Tigeot 	u32 sq_dyn_gpr_size_simd_ab_0;
410926deccbSFrançois Tigeot 	u32 gb_tiling_config = 0;
411926deccbSFrançois Tigeot 	u32 cc_rb_backend_disable = 0;
412926deccbSFrançois Tigeot 	u32 cc_gc_shader_pipe_config = 0;
413926deccbSFrançois Tigeot 	u32 mc_arb_ramcfg;
414926deccbSFrançois Tigeot 	u32 db_debug4, tmp;
415926deccbSFrançois Tigeot 	u32 inactive_pipes, shader_pipe_config;
416926deccbSFrançois Tigeot 	u32 disabled_rb_mask;
417926deccbSFrançois Tigeot 	unsigned active_number;
418926deccbSFrançois Tigeot 
419926deccbSFrançois Tigeot 	/* setup chip specs */
420926deccbSFrançois Tigeot 	rdev->config.rv770.tiling_group_size = 256;
421926deccbSFrançois Tigeot 	switch (rdev->family) {
422926deccbSFrançois Tigeot 	case CHIP_RV770:
423926deccbSFrançois Tigeot 		rdev->config.rv770.max_pipes = 4;
424926deccbSFrançois Tigeot 		rdev->config.rv770.max_tile_pipes = 8;
425926deccbSFrançois Tigeot 		rdev->config.rv770.max_simds = 10;
426926deccbSFrançois Tigeot 		rdev->config.rv770.max_backends = 4;
427926deccbSFrançois Tigeot 		rdev->config.rv770.max_gprs = 256;
428926deccbSFrançois Tigeot 		rdev->config.rv770.max_threads = 248;
429926deccbSFrançois Tigeot 		rdev->config.rv770.max_stack_entries = 512;
430926deccbSFrançois Tigeot 		rdev->config.rv770.max_hw_contexts = 8;
431926deccbSFrançois Tigeot 		rdev->config.rv770.max_gs_threads = 16 * 2;
432926deccbSFrançois Tigeot 		rdev->config.rv770.sx_max_export_size = 128;
433926deccbSFrançois Tigeot 		rdev->config.rv770.sx_max_export_pos_size = 16;
434926deccbSFrançois Tigeot 		rdev->config.rv770.sx_max_export_smx_size = 112;
435926deccbSFrançois Tigeot 		rdev->config.rv770.sq_num_cf_insts = 2;
436926deccbSFrançois Tigeot 
437926deccbSFrançois Tigeot 		rdev->config.rv770.sx_num_of_sets = 7;
438926deccbSFrançois Tigeot 		rdev->config.rv770.sc_prim_fifo_size = 0xF9;
439926deccbSFrançois Tigeot 		rdev->config.rv770.sc_hiz_tile_fifo_size = 0x30;
440926deccbSFrançois Tigeot 		rdev->config.rv770.sc_earlyz_tile_fifo_fize = 0x130;
441926deccbSFrançois Tigeot 		break;
442926deccbSFrançois Tigeot 	case CHIP_RV730:
443926deccbSFrançois Tigeot 		rdev->config.rv770.max_pipes = 2;
444926deccbSFrançois Tigeot 		rdev->config.rv770.max_tile_pipes = 4;
445926deccbSFrançois Tigeot 		rdev->config.rv770.max_simds = 8;
446926deccbSFrançois Tigeot 		rdev->config.rv770.max_backends = 2;
447926deccbSFrançois Tigeot 		rdev->config.rv770.max_gprs = 128;
448926deccbSFrançois Tigeot 		rdev->config.rv770.max_threads = 248;
449926deccbSFrançois Tigeot 		rdev->config.rv770.max_stack_entries = 256;
450926deccbSFrançois Tigeot 		rdev->config.rv770.max_hw_contexts = 8;
451926deccbSFrançois Tigeot 		rdev->config.rv770.max_gs_threads = 16 * 2;
452926deccbSFrançois Tigeot 		rdev->config.rv770.sx_max_export_size = 256;
453926deccbSFrançois Tigeot 		rdev->config.rv770.sx_max_export_pos_size = 32;
454926deccbSFrançois Tigeot 		rdev->config.rv770.sx_max_export_smx_size = 224;
455926deccbSFrançois Tigeot 		rdev->config.rv770.sq_num_cf_insts = 2;
456926deccbSFrançois Tigeot 
457926deccbSFrançois Tigeot 		rdev->config.rv770.sx_num_of_sets = 7;
458926deccbSFrançois Tigeot 		rdev->config.rv770.sc_prim_fifo_size = 0xf9;
459926deccbSFrançois Tigeot 		rdev->config.rv770.sc_hiz_tile_fifo_size = 0x30;
460926deccbSFrançois Tigeot 		rdev->config.rv770.sc_earlyz_tile_fifo_fize = 0x130;
461926deccbSFrançois Tigeot 		if (rdev->config.rv770.sx_max_export_pos_size > 16) {
462926deccbSFrançois Tigeot 			rdev->config.rv770.sx_max_export_pos_size -= 16;
463926deccbSFrançois Tigeot 			rdev->config.rv770.sx_max_export_smx_size += 16;
464926deccbSFrançois Tigeot 		}
465926deccbSFrançois Tigeot 		break;
466926deccbSFrançois Tigeot 	case CHIP_RV710:
467926deccbSFrançois Tigeot 		rdev->config.rv770.max_pipes = 2;
468926deccbSFrançois Tigeot 		rdev->config.rv770.max_tile_pipes = 2;
469926deccbSFrançois Tigeot 		rdev->config.rv770.max_simds = 2;
470926deccbSFrançois Tigeot 		rdev->config.rv770.max_backends = 1;
471926deccbSFrançois Tigeot 		rdev->config.rv770.max_gprs = 256;
472926deccbSFrançois Tigeot 		rdev->config.rv770.max_threads = 192;
473926deccbSFrançois Tigeot 		rdev->config.rv770.max_stack_entries = 256;
474926deccbSFrançois Tigeot 		rdev->config.rv770.max_hw_contexts = 4;
475926deccbSFrançois Tigeot 		rdev->config.rv770.max_gs_threads = 8 * 2;
476926deccbSFrançois Tigeot 		rdev->config.rv770.sx_max_export_size = 128;
477926deccbSFrançois Tigeot 		rdev->config.rv770.sx_max_export_pos_size = 16;
478926deccbSFrançois Tigeot 		rdev->config.rv770.sx_max_export_smx_size = 112;
479926deccbSFrançois Tigeot 		rdev->config.rv770.sq_num_cf_insts = 1;
480926deccbSFrançois Tigeot 
481926deccbSFrançois Tigeot 		rdev->config.rv770.sx_num_of_sets = 7;
482926deccbSFrançois Tigeot 		rdev->config.rv770.sc_prim_fifo_size = 0x40;
483926deccbSFrançois Tigeot 		rdev->config.rv770.sc_hiz_tile_fifo_size = 0x30;
484926deccbSFrançois Tigeot 		rdev->config.rv770.sc_earlyz_tile_fifo_fize = 0x130;
485926deccbSFrançois Tigeot 		break;
486926deccbSFrançois Tigeot 	case CHIP_RV740:
487926deccbSFrançois Tigeot 		rdev->config.rv770.max_pipes = 4;
488926deccbSFrançois Tigeot 		rdev->config.rv770.max_tile_pipes = 4;
489926deccbSFrançois Tigeot 		rdev->config.rv770.max_simds = 8;
490926deccbSFrançois Tigeot 		rdev->config.rv770.max_backends = 4;
491926deccbSFrançois Tigeot 		rdev->config.rv770.max_gprs = 256;
492926deccbSFrançois Tigeot 		rdev->config.rv770.max_threads = 248;
493926deccbSFrançois Tigeot 		rdev->config.rv770.max_stack_entries = 512;
494926deccbSFrançois Tigeot 		rdev->config.rv770.max_hw_contexts = 8;
495926deccbSFrançois Tigeot 		rdev->config.rv770.max_gs_threads = 16 * 2;
496926deccbSFrançois Tigeot 		rdev->config.rv770.sx_max_export_size = 256;
497926deccbSFrançois Tigeot 		rdev->config.rv770.sx_max_export_pos_size = 32;
498926deccbSFrançois Tigeot 		rdev->config.rv770.sx_max_export_smx_size = 224;
499926deccbSFrançois Tigeot 		rdev->config.rv770.sq_num_cf_insts = 2;
500926deccbSFrançois Tigeot 
501926deccbSFrançois Tigeot 		rdev->config.rv770.sx_num_of_sets = 7;
502926deccbSFrançois Tigeot 		rdev->config.rv770.sc_prim_fifo_size = 0x100;
503926deccbSFrançois Tigeot 		rdev->config.rv770.sc_hiz_tile_fifo_size = 0x30;
504926deccbSFrançois Tigeot 		rdev->config.rv770.sc_earlyz_tile_fifo_fize = 0x130;
505926deccbSFrançois Tigeot 
506926deccbSFrançois Tigeot 		if (rdev->config.rv770.sx_max_export_pos_size > 16) {
507926deccbSFrançois Tigeot 			rdev->config.rv770.sx_max_export_pos_size -= 16;
508926deccbSFrançois Tigeot 			rdev->config.rv770.sx_max_export_smx_size += 16;
509926deccbSFrançois Tigeot 		}
510926deccbSFrançois Tigeot 		break;
511926deccbSFrançois Tigeot 	default:
512926deccbSFrançois Tigeot 		break;
513926deccbSFrançois Tigeot 	}
514926deccbSFrançois Tigeot 
515926deccbSFrançois Tigeot 	/* Initialize HDP */
516926deccbSFrançois Tigeot 	j = 0;
517926deccbSFrançois Tigeot 	for (i = 0; i < 32; i++) {
518926deccbSFrançois Tigeot 		WREG32((0x2c14 + j), 0x00000000);
519926deccbSFrançois Tigeot 		WREG32((0x2c18 + j), 0x00000000);
520926deccbSFrançois Tigeot 		WREG32((0x2c1c + j), 0x00000000);
521926deccbSFrançois Tigeot 		WREG32((0x2c20 + j), 0x00000000);
522926deccbSFrançois Tigeot 		WREG32((0x2c24 + j), 0x00000000);
523926deccbSFrançois Tigeot 		j += 0x18;
524926deccbSFrançois Tigeot 	}
525926deccbSFrançois Tigeot 
526926deccbSFrançois Tigeot 	WREG32(GRBM_CNTL, GRBM_READ_TIMEOUT(0xff));
527926deccbSFrançois Tigeot 
528926deccbSFrançois Tigeot 	/* setup tiling, simd, pipe config */
529926deccbSFrançois Tigeot 	mc_arb_ramcfg = RREG32(MC_ARB_RAMCFG);
530926deccbSFrançois Tigeot 
531926deccbSFrançois Tigeot 	shader_pipe_config = RREG32(CC_GC_SHADER_PIPE_CONFIG);
532926deccbSFrançois Tigeot 	inactive_pipes = (shader_pipe_config & INACTIVE_QD_PIPES_MASK) >> INACTIVE_QD_PIPES_SHIFT;
533926deccbSFrançois Tigeot 	for (i = 0, tmp = 1, active_number = 0; i < R7XX_MAX_PIPES; i++) {
534926deccbSFrançois Tigeot 		if (!(inactive_pipes & tmp)) {
535926deccbSFrançois Tigeot 			active_number++;
536926deccbSFrançois Tigeot 		}
537926deccbSFrançois Tigeot 		tmp <<= 1;
538926deccbSFrançois Tigeot 	}
539926deccbSFrançois Tigeot 	if (active_number == 1) {
540926deccbSFrançois Tigeot 		WREG32(SPI_CONFIG_CNTL, DISABLE_INTERP_1);
541926deccbSFrançois Tigeot 	} else {
542926deccbSFrançois Tigeot 		WREG32(SPI_CONFIG_CNTL, 0);
543926deccbSFrançois Tigeot 	}
544926deccbSFrançois Tigeot 
545926deccbSFrançois Tigeot 	cc_rb_backend_disable = RREG32(CC_RB_BACKEND_DISABLE) & 0x00ff0000;
546926deccbSFrançois Tigeot 	tmp = R7XX_MAX_BACKENDS - r600_count_pipe_bits(cc_rb_backend_disable >> 16);
547926deccbSFrançois Tigeot 	if (tmp < rdev->config.rv770.max_backends) {
548926deccbSFrançois Tigeot 		rdev->config.rv770.max_backends = tmp;
549926deccbSFrançois Tigeot 	}
550926deccbSFrançois Tigeot 
551926deccbSFrançois Tigeot 	cc_gc_shader_pipe_config = RREG32(CC_GC_SHADER_PIPE_CONFIG) & 0xffffff00;
552926deccbSFrançois Tigeot 	tmp = R7XX_MAX_PIPES - r600_count_pipe_bits((cc_gc_shader_pipe_config >> 8) & R7XX_MAX_PIPES_MASK);
553926deccbSFrançois Tigeot 	if (tmp < rdev->config.rv770.max_pipes) {
554926deccbSFrançois Tigeot 		rdev->config.rv770.max_pipes = tmp;
555926deccbSFrançois Tigeot 	}
556926deccbSFrançois Tigeot 	tmp = R7XX_MAX_SIMDS - r600_count_pipe_bits((cc_gc_shader_pipe_config >> 16) & R7XX_MAX_SIMDS_MASK);
557926deccbSFrançois Tigeot 	if (tmp < rdev->config.rv770.max_simds) {
558926deccbSFrançois Tigeot 		rdev->config.rv770.max_simds = tmp;
559926deccbSFrançois Tigeot 	}
560926deccbSFrançois Tigeot 
561926deccbSFrançois Tigeot 	switch (rdev->config.rv770.max_tile_pipes) {
562926deccbSFrançois Tigeot 	case 1:
563926deccbSFrançois Tigeot 	default:
564926deccbSFrançois Tigeot 		gb_tiling_config = PIPE_TILING(0);
565926deccbSFrançois Tigeot 		break;
566926deccbSFrançois Tigeot 	case 2:
567926deccbSFrançois Tigeot 		gb_tiling_config = PIPE_TILING(1);
568926deccbSFrançois Tigeot 		break;
569926deccbSFrançois Tigeot 	case 4:
570926deccbSFrançois Tigeot 		gb_tiling_config = PIPE_TILING(2);
571926deccbSFrançois Tigeot 		break;
572926deccbSFrançois Tigeot 	case 8:
573926deccbSFrançois Tigeot 		gb_tiling_config = PIPE_TILING(3);
574926deccbSFrançois Tigeot 		break;
575926deccbSFrançois Tigeot 	}
576926deccbSFrançois Tigeot 	rdev->config.rv770.tiling_npipes = rdev->config.rv770.max_tile_pipes;
577926deccbSFrançois Tigeot 
578926deccbSFrançois Tigeot 	disabled_rb_mask = (RREG32(CC_RB_BACKEND_DISABLE) >> 16) & R7XX_MAX_BACKENDS_MASK;
579926deccbSFrançois Tigeot 	tmp = (gb_tiling_config & PIPE_TILING__MASK) >> PIPE_TILING__SHIFT;
580926deccbSFrançois Tigeot 	tmp = r6xx_remap_render_backend(rdev, tmp, rdev->config.rv770.max_backends,
581926deccbSFrançois Tigeot 					R7XX_MAX_BACKENDS, disabled_rb_mask);
582926deccbSFrançois Tigeot 	gb_tiling_config |= tmp << 16;
583926deccbSFrançois Tigeot 	rdev->config.rv770.backend_map = tmp;
584926deccbSFrançois Tigeot 
585926deccbSFrançois Tigeot 	if (rdev->family == CHIP_RV770)
586926deccbSFrançois Tigeot 		gb_tiling_config |= BANK_TILING(1);
587926deccbSFrançois Tigeot 	else {
588926deccbSFrançois Tigeot 		if ((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT)
589926deccbSFrançois Tigeot 			gb_tiling_config |= BANK_TILING(1);
590926deccbSFrançois Tigeot 		else
591926deccbSFrançois Tigeot 			gb_tiling_config |= BANK_TILING(0);
592926deccbSFrançois Tigeot 	}
593926deccbSFrançois Tigeot 	rdev->config.rv770.tiling_nbanks = 4 << ((gb_tiling_config >> 4) & 0x3);
594926deccbSFrançois Tigeot 	gb_tiling_config |= GROUP_SIZE((mc_arb_ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT);
595926deccbSFrançois Tigeot 	if (((mc_arb_ramcfg & NOOFROWS_MASK) >> NOOFROWS_SHIFT) > 3) {
596926deccbSFrançois Tigeot 		gb_tiling_config |= ROW_TILING(3);
597926deccbSFrançois Tigeot 		gb_tiling_config |= SAMPLE_SPLIT(3);
598926deccbSFrançois Tigeot 	} else {
599926deccbSFrançois Tigeot 		gb_tiling_config |=
600926deccbSFrançois Tigeot 			ROW_TILING(((mc_arb_ramcfg & NOOFROWS_MASK) >> NOOFROWS_SHIFT));
601926deccbSFrançois Tigeot 		gb_tiling_config |=
602926deccbSFrançois Tigeot 			SAMPLE_SPLIT(((mc_arb_ramcfg & NOOFROWS_MASK) >> NOOFROWS_SHIFT));
603926deccbSFrançois Tigeot 	}
604926deccbSFrançois Tigeot 
605926deccbSFrançois Tigeot 	gb_tiling_config |= BANK_SWAPS(1);
606926deccbSFrançois Tigeot 	rdev->config.rv770.tile_config = gb_tiling_config;
607926deccbSFrançois Tigeot 
608926deccbSFrançois Tigeot 	WREG32(GB_TILING_CONFIG, gb_tiling_config);
609926deccbSFrançois Tigeot 	WREG32(DCP_TILING_CONFIG, (gb_tiling_config & 0xffff));
610926deccbSFrançois Tigeot 	WREG32(HDP_TILING_CONFIG, (gb_tiling_config & 0xffff));
611926deccbSFrançois Tigeot 	WREG32(DMA_TILING_CONFIG, (gb_tiling_config & 0xffff));
612926deccbSFrançois Tigeot 	WREG32(DMA_TILING_CONFIG2, (gb_tiling_config & 0xffff));
613926deccbSFrançois Tigeot 
614926deccbSFrançois Tigeot 	WREG32(CGTS_SYS_TCC_DISABLE, 0);
615926deccbSFrançois Tigeot 	WREG32(CGTS_TCC_DISABLE, 0);
616926deccbSFrançois Tigeot 	WREG32(CGTS_USER_SYS_TCC_DISABLE, 0);
617926deccbSFrançois Tigeot 	WREG32(CGTS_USER_TCC_DISABLE, 0);
618926deccbSFrançois Tigeot 
619926deccbSFrançois Tigeot 
620926deccbSFrançois Tigeot 	num_qd_pipes = R7XX_MAX_PIPES - r600_count_pipe_bits((cc_gc_shader_pipe_config & INACTIVE_QD_PIPES_MASK) >> 8);
621926deccbSFrançois Tigeot 	WREG32(VGT_OUT_DEALLOC_CNTL, (num_qd_pipes * 4) & DEALLOC_DIST_MASK);
622926deccbSFrançois Tigeot 	WREG32(VGT_VERTEX_REUSE_BLOCK_CNTL, ((num_qd_pipes * 4) - 2) & VTX_REUSE_DEPTH_MASK);
623926deccbSFrançois Tigeot 
624926deccbSFrançois Tigeot 	/* set HW defaults for 3D engine */
625926deccbSFrançois Tigeot 	WREG32(CP_QUEUE_THRESHOLDS, (ROQ_IB1_START(0x16) |
626926deccbSFrançois Tigeot 				     ROQ_IB2_START(0x2b)));
627926deccbSFrançois Tigeot 
628926deccbSFrançois Tigeot 	WREG32(CP_MEQ_THRESHOLDS, STQ_SPLIT(0x30));
629926deccbSFrançois Tigeot 
630926deccbSFrançois Tigeot 	ta_aux_cntl = RREG32(TA_CNTL_AUX);
631926deccbSFrançois Tigeot 	WREG32(TA_CNTL_AUX, ta_aux_cntl | DISABLE_CUBE_ANISO);
632926deccbSFrançois Tigeot 
633926deccbSFrançois Tigeot 	sx_debug_1 = RREG32(SX_DEBUG_1);
634926deccbSFrançois Tigeot 	sx_debug_1 |= ENABLE_NEW_SMX_ADDRESS;
635926deccbSFrançois Tigeot 	WREG32(SX_DEBUG_1, sx_debug_1);
636926deccbSFrançois Tigeot 
637926deccbSFrançois Tigeot 	smx_dc_ctl0 = RREG32(SMX_DC_CTL0);
638926deccbSFrançois Tigeot 	smx_dc_ctl0 &= ~CACHE_DEPTH(0x1ff);
639926deccbSFrançois Tigeot 	smx_dc_ctl0 |= CACHE_DEPTH((rdev->config.rv770.sx_num_of_sets * 64) - 1);
640926deccbSFrançois Tigeot 	WREG32(SMX_DC_CTL0, smx_dc_ctl0);
641926deccbSFrançois Tigeot 
642926deccbSFrançois Tigeot 	if (rdev->family != CHIP_RV740)
643926deccbSFrançois Tigeot 		WREG32(SMX_EVENT_CTL, (ES_FLUSH_CTL(4) |
644926deccbSFrançois Tigeot 				       GS_FLUSH_CTL(4) |
645926deccbSFrançois Tigeot 				       ACK_FLUSH_CTL(3) |
646926deccbSFrançois Tigeot 				       SYNC_FLUSH_CTL));
647926deccbSFrançois Tigeot 
648926deccbSFrançois Tigeot 	if (rdev->family != CHIP_RV770)
649926deccbSFrançois Tigeot 		WREG32(SMX_SAR_CTL0, 0x00003f3f);
650926deccbSFrançois Tigeot 
651926deccbSFrançois Tigeot 	db_debug3 = RREG32(DB_DEBUG3);
652926deccbSFrançois Tigeot 	db_debug3 &= ~DB_CLK_OFF_DELAY(0x1f);
653926deccbSFrançois Tigeot 	switch (rdev->family) {
654926deccbSFrançois Tigeot 	case CHIP_RV770:
655926deccbSFrançois Tigeot 	case CHIP_RV740:
656926deccbSFrançois Tigeot 		db_debug3 |= DB_CLK_OFF_DELAY(0x1f);
657926deccbSFrançois Tigeot 		break;
658926deccbSFrançois Tigeot 	case CHIP_RV710:
659926deccbSFrançois Tigeot 	case CHIP_RV730:
660926deccbSFrançois Tigeot 	default:
661926deccbSFrançois Tigeot 		db_debug3 |= DB_CLK_OFF_DELAY(2);
662926deccbSFrançois Tigeot 		break;
663926deccbSFrançois Tigeot 	}
664926deccbSFrançois Tigeot 	WREG32(DB_DEBUG3, db_debug3);
665926deccbSFrançois Tigeot 
666926deccbSFrançois Tigeot 	if (rdev->family != CHIP_RV770) {
667926deccbSFrançois Tigeot 		db_debug4 = RREG32(DB_DEBUG4);
668926deccbSFrançois Tigeot 		db_debug4 |= DISABLE_TILE_COVERED_FOR_PS_ITER;
669926deccbSFrançois Tigeot 		WREG32(DB_DEBUG4, db_debug4);
670926deccbSFrançois Tigeot 	}
671926deccbSFrançois Tigeot 
672926deccbSFrançois Tigeot 	WREG32(SX_EXPORT_BUFFER_SIZES, (COLOR_BUFFER_SIZE((rdev->config.rv770.sx_max_export_size / 4) - 1) |
673926deccbSFrançois Tigeot 					POSITION_BUFFER_SIZE((rdev->config.rv770.sx_max_export_pos_size / 4) - 1) |
674926deccbSFrançois Tigeot 					SMX_BUFFER_SIZE((rdev->config.rv770.sx_max_export_smx_size / 4) - 1)));
675926deccbSFrançois Tigeot 
676926deccbSFrançois Tigeot 	WREG32(PA_SC_FIFO_SIZE, (SC_PRIM_FIFO_SIZE(rdev->config.rv770.sc_prim_fifo_size) |
677926deccbSFrançois Tigeot 				 SC_HIZ_TILE_FIFO_SIZE(rdev->config.rv770.sc_hiz_tile_fifo_size) |
678926deccbSFrançois Tigeot 				 SC_EARLYZ_TILE_FIFO_SIZE(rdev->config.rv770.sc_earlyz_tile_fifo_fize)));
679926deccbSFrançois Tigeot 
680926deccbSFrançois Tigeot 	WREG32(PA_SC_MULTI_CHIP_CNTL, 0);
681926deccbSFrançois Tigeot 
682926deccbSFrançois Tigeot 	WREG32(VGT_NUM_INSTANCES, 1);
683926deccbSFrançois Tigeot 
684926deccbSFrançois Tigeot 	WREG32(SPI_CONFIG_CNTL_1, VTX_DONE_DELAY(4));
685926deccbSFrançois Tigeot 
686926deccbSFrançois Tigeot 	WREG32(CP_PERFMON_CNTL, 0);
687926deccbSFrançois Tigeot 
688926deccbSFrançois Tigeot 	sq_ms_fifo_sizes = (CACHE_FIFO_SIZE(16 * rdev->config.rv770.sq_num_cf_insts) |
689926deccbSFrançois Tigeot 			    DONE_FIFO_HIWATER(0xe0) |
690926deccbSFrançois Tigeot 			    ALU_UPDATE_FIFO_HIWATER(0x8));
691926deccbSFrançois Tigeot 	switch (rdev->family) {
692926deccbSFrançois Tigeot 	case CHIP_RV770:
693926deccbSFrançois Tigeot 	case CHIP_RV730:
694926deccbSFrançois Tigeot 	case CHIP_RV710:
695926deccbSFrançois Tigeot 		sq_ms_fifo_sizes |= FETCH_FIFO_HIWATER(0x1);
696926deccbSFrançois Tigeot 		break;
697926deccbSFrançois Tigeot 	case CHIP_RV740:
698926deccbSFrançois Tigeot 	default:
699926deccbSFrançois Tigeot 		sq_ms_fifo_sizes |= FETCH_FIFO_HIWATER(0x4);
700926deccbSFrançois Tigeot 		break;
701926deccbSFrançois Tigeot 	}
702926deccbSFrançois Tigeot 	WREG32(SQ_MS_FIFO_SIZES, sq_ms_fifo_sizes);
703926deccbSFrançois Tigeot 
704926deccbSFrançois Tigeot 	/* SQ_CONFIG, SQ_GPR_RESOURCE_MGMT, SQ_THREAD_RESOURCE_MGMT, SQ_STACK_RESOURCE_MGMT
705926deccbSFrançois Tigeot 	 * should be adjusted as needed by the 2D/3D drivers.  This just sets default values
706926deccbSFrançois Tigeot 	 */
707926deccbSFrançois Tigeot 	sq_config = RREG32(SQ_CONFIG);
708926deccbSFrançois Tigeot 	sq_config &= ~(PS_PRIO(3) |
709926deccbSFrançois Tigeot 		       VS_PRIO(3) |
710926deccbSFrançois Tigeot 		       GS_PRIO(3) |
711926deccbSFrançois Tigeot 		       ES_PRIO(3));
712926deccbSFrançois Tigeot 	sq_config |= (DX9_CONSTS |
713926deccbSFrançois Tigeot 		      VC_ENABLE |
714926deccbSFrançois Tigeot 		      EXPORT_SRC_C |
715926deccbSFrançois Tigeot 		      PS_PRIO(0) |
716926deccbSFrançois Tigeot 		      VS_PRIO(1) |
717926deccbSFrançois Tigeot 		      GS_PRIO(2) |
718926deccbSFrançois Tigeot 		      ES_PRIO(3));
719926deccbSFrançois Tigeot 	if (rdev->family == CHIP_RV710)
720926deccbSFrançois Tigeot 		/* no vertex cache */
721926deccbSFrançois Tigeot 		sq_config &= ~VC_ENABLE;
722926deccbSFrançois Tigeot 
723926deccbSFrançois Tigeot 	WREG32(SQ_CONFIG, sq_config);
724926deccbSFrançois Tigeot 
725926deccbSFrançois Tigeot 	WREG32(SQ_GPR_RESOURCE_MGMT_1,  (NUM_PS_GPRS((rdev->config.rv770.max_gprs * 24)/64) |
726926deccbSFrançois Tigeot 					 NUM_VS_GPRS((rdev->config.rv770.max_gprs * 24)/64) |
727926deccbSFrançois Tigeot 					 NUM_CLAUSE_TEMP_GPRS(((rdev->config.rv770.max_gprs * 24)/64)/2)));
728926deccbSFrançois Tigeot 
729926deccbSFrançois Tigeot 	WREG32(SQ_GPR_RESOURCE_MGMT_2,  (NUM_GS_GPRS((rdev->config.rv770.max_gprs * 7)/64) |
730926deccbSFrançois Tigeot 					 NUM_ES_GPRS((rdev->config.rv770.max_gprs * 7)/64)));
731926deccbSFrançois Tigeot 
732926deccbSFrançois Tigeot 	sq_thread_resource_mgmt = (NUM_PS_THREADS((rdev->config.rv770.max_threads * 4)/8) |
733926deccbSFrançois Tigeot 				   NUM_VS_THREADS((rdev->config.rv770.max_threads * 2)/8) |
734926deccbSFrançois Tigeot 				   NUM_ES_THREADS((rdev->config.rv770.max_threads * 1)/8));
735926deccbSFrançois Tigeot 	if (((rdev->config.rv770.max_threads * 1) / 8) > rdev->config.rv770.max_gs_threads)
736926deccbSFrançois Tigeot 		sq_thread_resource_mgmt |= NUM_GS_THREADS(rdev->config.rv770.max_gs_threads);
737926deccbSFrançois Tigeot 	else
738926deccbSFrançois Tigeot 		sq_thread_resource_mgmt |= NUM_GS_THREADS((rdev->config.rv770.max_gs_threads * 1)/8);
739926deccbSFrançois Tigeot 	WREG32(SQ_THREAD_RESOURCE_MGMT, sq_thread_resource_mgmt);
740926deccbSFrançois Tigeot 
741926deccbSFrançois Tigeot 	WREG32(SQ_STACK_RESOURCE_MGMT_1, (NUM_PS_STACK_ENTRIES((rdev->config.rv770.max_stack_entries * 1)/4) |
742926deccbSFrançois Tigeot 						     NUM_VS_STACK_ENTRIES((rdev->config.rv770.max_stack_entries * 1)/4)));
743926deccbSFrançois Tigeot 
744926deccbSFrançois Tigeot 	WREG32(SQ_STACK_RESOURCE_MGMT_2, (NUM_GS_STACK_ENTRIES((rdev->config.rv770.max_stack_entries * 1)/4) |
745926deccbSFrançois Tigeot 						     NUM_ES_STACK_ENTRIES((rdev->config.rv770.max_stack_entries * 1)/4)));
746926deccbSFrançois Tigeot 
747926deccbSFrançois Tigeot 	sq_dyn_gpr_size_simd_ab_0 = (SIMDA_RING0((rdev->config.rv770.max_gprs * 38)/64) |
748926deccbSFrançois Tigeot 				     SIMDA_RING1((rdev->config.rv770.max_gprs * 38)/64) |
749926deccbSFrançois Tigeot 				     SIMDB_RING0((rdev->config.rv770.max_gprs * 38)/64) |
750926deccbSFrançois Tigeot 				     SIMDB_RING1((rdev->config.rv770.max_gprs * 38)/64));
751926deccbSFrançois Tigeot 
752926deccbSFrançois Tigeot 	WREG32(SQ_DYN_GPR_SIZE_SIMD_AB_0, sq_dyn_gpr_size_simd_ab_0);
753926deccbSFrançois Tigeot 	WREG32(SQ_DYN_GPR_SIZE_SIMD_AB_1, sq_dyn_gpr_size_simd_ab_0);
754926deccbSFrançois Tigeot 	WREG32(SQ_DYN_GPR_SIZE_SIMD_AB_2, sq_dyn_gpr_size_simd_ab_0);
755926deccbSFrançois Tigeot 	WREG32(SQ_DYN_GPR_SIZE_SIMD_AB_3, sq_dyn_gpr_size_simd_ab_0);
756926deccbSFrançois Tigeot 	WREG32(SQ_DYN_GPR_SIZE_SIMD_AB_4, sq_dyn_gpr_size_simd_ab_0);
757926deccbSFrançois Tigeot 	WREG32(SQ_DYN_GPR_SIZE_SIMD_AB_5, sq_dyn_gpr_size_simd_ab_0);
758926deccbSFrançois Tigeot 	WREG32(SQ_DYN_GPR_SIZE_SIMD_AB_6, sq_dyn_gpr_size_simd_ab_0);
759926deccbSFrançois Tigeot 	WREG32(SQ_DYN_GPR_SIZE_SIMD_AB_7, sq_dyn_gpr_size_simd_ab_0);
760926deccbSFrançois Tigeot 
761926deccbSFrançois Tigeot 	WREG32(PA_SC_FORCE_EOV_MAX_CNTS, (FORCE_EOV_MAX_CLK_CNT(4095) |
762926deccbSFrançois Tigeot 					  FORCE_EOV_MAX_REZ_CNT(255)));
763926deccbSFrançois Tigeot 
764926deccbSFrançois Tigeot 	if (rdev->family == CHIP_RV710)
765926deccbSFrançois Tigeot 		WREG32(VGT_CACHE_INVALIDATION, (CACHE_INVALIDATION(TC_ONLY) |
766926deccbSFrançois Tigeot 						AUTO_INVLD_EN(ES_AND_GS_AUTO)));
767926deccbSFrançois Tigeot 	else
768926deccbSFrançois Tigeot 		WREG32(VGT_CACHE_INVALIDATION, (CACHE_INVALIDATION(VC_AND_TC) |
769926deccbSFrançois Tigeot 						AUTO_INVLD_EN(ES_AND_GS_AUTO)));
770926deccbSFrançois Tigeot 
771926deccbSFrançois Tigeot 	switch (rdev->family) {
772926deccbSFrançois Tigeot 	case CHIP_RV770:
773926deccbSFrançois Tigeot 	case CHIP_RV730:
774926deccbSFrançois Tigeot 	case CHIP_RV740:
775926deccbSFrançois Tigeot 		gs_prim_buffer_depth = 384;
776926deccbSFrançois Tigeot 		break;
777926deccbSFrançois Tigeot 	case CHIP_RV710:
778926deccbSFrançois Tigeot 		gs_prim_buffer_depth = 128;
779926deccbSFrançois Tigeot 		break;
780926deccbSFrançois Tigeot 	default:
781926deccbSFrançois Tigeot 		break;
782926deccbSFrançois Tigeot 	}
783926deccbSFrançois Tigeot 
784926deccbSFrançois Tigeot 	num_gs_verts_per_thread = rdev->config.rv770.max_pipes * 16;
785926deccbSFrançois Tigeot 	vgt_gs_per_es = gs_prim_buffer_depth + num_gs_verts_per_thread;
786926deccbSFrançois Tigeot 	/* Max value for this is 256 */
787926deccbSFrançois Tigeot 	if (vgt_gs_per_es > 256)
788926deccbSFrançois Tigeot 		vgt_gs_per_es = 256;
789926deccbSFrançois Tigeot 
790926deccbSFrançois Tigeot 	WREG32(VGT_ES_PER_GS, 128);
791926deccbSFrançois Tigeot 	WREG32(VGT_GS_PER_ES, vgt_gs_per_es);
792926deccbSFrançois Tigeot 	WREG32(VGT_GS_PER_VS, 2);
793926deccbSFrançois Tigeot 
794926deccbSFrançois Tigeot 	/* more default values. 2D/3D driver should adjust as needed */
795926deccbSFrançois Tigeot 	WREG32(VGT_GS_VERTEX_REUSE, 16);
796926deccbSFrançois Tigeot 	WREG32(PA_SC_LINE_STIPPLE_STATE, 0);
797926deccbSFrançois Tigeot 	WREG32(VGT_STRMOUT_EN, 0);
798926deccbSFrançois Tigeot 	WREG32(SX_MISC, 0);
799926deccbSFrançois Tigeot 	WREG32(PA_SC_MODE_CNTL, 0);
800926deccbSFrançois Tigeot 	WREG32(PA_SC_EDGERULE, 0xaaaaaaaa);
801926deccbSFrançois Tigeot 	WREG32(PA_SC_AA_CONFIG, 0);
802926deccbSFrançois Tigeot 	WREG32(PA_SC_CLIPRECT_RULE, 0xffff);
803926deccbSFrançois Tigeot 	WREG32(PA_SC_LINE_STIPPLE, 0);
804926deccbSFrançois Tigeot 	WREG32(SPI_INPUT_Z, 0);
805926deccbSFrançois Tigeot 	WREG32(SPI_PS_IN_CONTROL_0, NUM_INTERP(2));
806926deccbSFrançois Tigeot 	WREG32(CB_COLOR7_FRAG, 0);
807926deccbSFrançois Tigeot 
808926deccbSFrançois Tigeot 	/* clear render buffer base addresses */
809926deccbSFrançois Tigeot 	WREG32(CB_COLOR0_BASE, 0);
810926deccbSFrançois Tigeot 	WREG32(CB_COLOR1_BASE, 0);
811926deccbSFrançois Tigeot 	WREG32(CB_COLOR2_BASE, 0);
812926deccbSFrançois Tigeot 	WREG32(CB_COLOR3_BASE, 0);
813926deccbSFrançois Tigeot 	WREG32(CB_COLOR4_BASE, 0);
814926deccbSFrançois Tigeot 	WREG32(CB_COLOR5_BASE, 0);
815926deccbSFrançois Tigeot 	WREG32(CB_COLOR6_BASE, 0);
816926deccbSFrançois Tigeot 	WREG32(CB_COLOR7_BASE, 0);
817926deccbSFrançois Tigeot 
818926deccbSFrançois Tigeot 	WREG32(TCP_CNTL, 0);
819926deccbSFrançois Tigeot 
820926deccbSFrançois Tigeot 	hdp_host_path_cntl = RREG32(HDP_HOST_PATH_CNTL);
821926deccbSFrançois Tigeot 	WREG32(HDP_HOST_PATH_CNTL, hdp_host_path_cntl);
822926deccbSFrançois Tigeot 
823926deccbSFrançois Tigeot 	WREG32(PA_SC_MULTI_CHIP_CNTL, 0);
824926deccbSFrançois Tigeot 
825926deccbSFrançois Tigeot 	WREG32(PA_CL_ENHANCE, (CLIP_VTX_REORDER_ENA |
826926deccbSFrançois Tigeot 					  NUM_CLIP_SEQ(3)));
827926deccbSFrançois Tigeot 	WREG32(VC_ENHANCE, 0);
828926deccbSFrançois Tigeot }
829926deccbSFrançois Tigeot 
830926deccbSFrançois Tigeot void r700_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc)
831926deccbSFrançois Tigeot {
832926deccbSFrançois Tigeot 	u64 size_bf, size_af;
833926deccbSFrançois Tigeot 
834926deccbSFrançois Tigeot 	if (mc->mc_vram_size > 0xE0000000) {
835926deccbSFrançois Tigeot 		/* leave room for at least 512M GTT */
836926deccbSFrançois Tigeot 		dev_warn(rdev->dev, "limiting VRAM\n");
837926deccbSFrançois Tigeot 		mc->real_vram_size = 0xE0000000;
838926deccbSFrançois Tigeot 		mc->mc_vram_size = 0xE0000000;
839926deccbSFrançois Tigeot 	}
840926deccbSFrançois Tigeot 	if (rdev->flags & RADEON_IS_AGP) {
841926deccbSFrançois Tigeot 		size_bf = mc->gtt_start;
842926deccbSFrançois Tigeot 		size_af = 0xFFFFFFFF - mc->gtt_end;
843926deccbSFrançois Tigeot 		if (size_bf > size_af) {
844926deccbSFrançois Tigeot 			if (mc->mc_vram_size > size_bf) {
845926deccbSFrançois Tigeot 				dev_warn(rdev->dev, "limiting VRAM\n");
846926deccbSFrançois Tigeot 				mc->real_vram_size = size_bf;
847926deccbSFrançois Tigeot 				mc->mc_vram_size = size_bf;
848926deccbSFrançois Tigeot 			}
849926deccbSFrançois Tigeot 			mc->vram_start = mc->gtt_start - mc->mc_vram_size;
850926deccbSFrançois Tigeot 		} else {
851926deccbSFrançois Tigeot 			if (mc->mc_vram_size > size_af) {
852926deccbSFrançois Tigeot 				dev_warn(rdev->dev, "limiting VRAM\n");
853926deccbSFrançois Tigeot 				mc->real_vram_size = size_af;
854926deccbSFrançois Tigeot 				mc->mc_vram_size = size_af;
855926deccbSFrançois Tigeot 			}
856926deccbSFrançois Tigeot 			mc->vram_start = mc->gtt_end + 1;
857926deccbSFrançois Tigeot 		}
858926deccbSFrançois Tigeot 		mc->vram_end = mc->vram_start + mc->mc_vram_size - 1;
859926deccbSFrançois Tigeot 		dev_info(rdev->dev, "VRAM: %juM 0x%08jX - 0x%08jX (%juM used)\n",
860926deccbSFrançois Tigeot 				(uintmax_t)mc->mc_vram_size >> 20, (uintmax_t)mc->vram_start,
861926deccbSFrançois Tigeot 				(uintmax_t)mc->vram_end, (uintmax_t)mc->real_vram_size >> 20);
862926deccbSFrançois Tigeot 	} else {
863926deccbSFrançois Tigeot 		radeon_vram_location(rdev, &rdev->mc, 0);
864926deccbSFrançois Tigeot 		rdev->mc.gtt_base_align = 0;
865926deccbSFrançois Tigeot 		radeon_gtt_location(rdev, mc);
866926deccbSFrançois Tigeot 	}
867926deccbSFrançois Tigeot }
868926deccbSFrançois Tigeot 
869926deccbSFrançois Tigeot static int rv770_mc_init(struct radeon_device *rdev)
870926deccbSFrançois Tigeot {
871926deccbSFrançois Tigeot 	u32 tmp;
872926deccbSFrançois Tigeot 	int chansize, numchan;
873926deccbSFrançois Tigeot 
874926deccbSFrançois Tigeot 	/* Get VRAM informations */
875926deccbSFrançois Tigeot 	rdev->mc.vram_is_ddr = true;
876926deccbSFrançois Tigeot 	tmp = RREG32(MC_ARB_RAMCFG);
877926deccbSFrançois Tigeot 	if (tmp & CHANSIZE_OVERRIDE) {
878926deccbSFrançois Tigeot 		chansize = 16;
879926deccbSFrançois Tigeot 	} else if (tmp & CHANSIZE_MASK) {
880926deccbSFrançois Tigeot 		chansize = 64;
881926deccbSFrançois Tigeot 	} else {
882926deccbSFrançois Tigeot 		chansize = 32;
883926deccbSFrançois Tigeot 	}
884926deccbSFrançois Tigeot 	tmp = RREG32(MC_SHARED_CHMAP);
885926deccbSFrançois Tigeot 	switch ((tmp & NOOFCHAN_MASK) >> NOOFCHAN_SHIFT) {
886926deccbSFrançois Tigeot 	case 0:
887926deccbSFrançois Tigeot 	default:
888926deccbSFrançois Tigeot 		numchan = 1;
889926deccbSFrançois Tigeot 		break;
890926deccbSFrançois Tigeot 	case 1:
891926deccbSFrançois Tigeot 		numchan = 2;
892926deccbSFrançois Tigeot 		break;
893926deccbSFrançois Tigeot 	case 2:
894926deccbSFrançois Tigeot 		numchan = 4;
895926deccbSFrançois Tigeot 		break;
896926deccbSFrançois Tigeot 	case 3:
897926deccbSFrançois Tigeot 		numchan = 8;
898926deccbSFrançois Tigeot 		break;
899926deccbSFrançois Tigeot 	}
900926deccbSFrançois Tigeot 	rdev->mc.vram_width = numchan * chansize;
901926deccbSFrançois Tigeot 	/* Could aper size report 0 ? */
902926deccbSFrançois Tigeot 	rdev->mc.aper_base = drm_get_resource_start(rdev->ddev, 0);
903926deccbSFrançois Tigeot 	rdev->mc.aper_size = drm_get_resource_len(rdev->ddev, 0);
904926deccbSFrançois Tigeot 	/* Setup GPU memory space */
905926deccbSFrançois Tigeot 	rdev->mc.mc_vram_size = RREG32(CONFIG_MEMSIZE);
906926deccbSFrançois Tigeot 	rdev->mc.real_vram_size = RREG32(CONFIG_MEMSIZE);
907926deccbSFrançois Tigeot 	rdev->mc.visible_vram_size = rdev->mc.aper_size;
908926deccbSFrançois Tigeot 	r700_vram_gtt_location(rdev, &rdev->mc);
909926deccbSFrançois Tigeot 	radeon_update_bandwidth_info(rdev);
910926deccbSFrançois Tigeot 
911926deccbSFrançois Tigeot 	return 0;
912926deccbSFrançois Tigeot }
913926deccbSFrançois Tigeot 
914926deccbSFrançois Tigeot /**
915926deccbSFrançois Tigeot  * rv770_copy_dma - copy pages using the DMA engine
916926deccbSFrançois Tigeot  *
917926deccbSFrançois Tigeot  * @rdev: radeon_device pointer
918926deccbSFrançois Tigeot  * @src_offset: src GPU address
919926deccbSFrançois Tigeot  * @dst_offset: dst GPU address
920926deccbSFrançois Tigeot  * @num_gpu_pages: number of GPU pages to xfer
921926deccbSFrançois Tigeot  * @fence: radeon fence object
922926deccbSFrançois Tigeot  *
923926deccbSFrançois Tigeot  * Copy GPU paging using the DMA engine (r7xx).
924926deccbSFrançois Tigeot  * Used by the radeon ttm implementation to move pages if
925926deccbSFrançois Tigeot  * registered as the asic copy callback.
926926deccbSFrançois Tigeot  */
927926deccbSFrançois Tigeot int rv770_copy_dma(struct radeon_device *rdev,
928926deccbSFrançois Tigeot 		  uint64_t src_offset, uint64_t dst_offset,
929926deccbSFrançois Tigeot 		  unsigned num_gpu_pages,
930926deccbSFrançois Tigeot 		  struct radeon_fence **fence)
931926deccbSFrançois Tigeot {
932926deccbSFrançois Tigeot 	struct radeon_semaphore *sem = NULL;
933926deccbSFrançois Tigeot 	int ring_index = rdev->asic->copy.dma_ring_index;
934926deccbSFrançois Tigeot 	struct radeon_ring *ring = &rdev->ring[ring_index];
935926deccbSFrançois Tigeot 	u32 size_in_dw, cur_size_in_dw;
936926deccbSFrançois Tigeot 	int i, num_loops;
937926deccbSFrançois Tigeot 	int r = 0;
938926deccbSFrançois Tigeot 
939926deccbSFrançois Tigeot 	r = radeon_semaphore_create(rdev, &sem);
940926deccbSFrançois Tigeot 	if (r) {
941926deccbSFrançois Tigeot 		DRM_ERROR("radeon: moving bo (%d).\n", r);
942926deccbSFrançois Tigeot 		return r;
943926deccbSFrançois Tigeot 	}
944926deccbSFrançois Tigeot 
945926deccbSFrançois Tigeot 	size_in_dw = (num_gpu_pages << RADEON_GPU_PAGE_SHIFT) / 4;
946926deccbSFrançois Tigeot 	num_loops = DIV_ROUND_UP(size_in_dw, 0xFFFF);
947926deccbSFrançois Tigeot 	r = radeon_ring_lock(rdev, ring, num_loops * 5 + 8);
948926deccbSFrançois Tigeot 	if (r) {
949926deccbSFrançois Tigeot 		DRM_ERROR("radeon: moving bo (%d).\n", r);
950926deccbSFrançois Tigeot 		radeon_semaphore_free(rdev, &sem, NULL);
951926deccbSFrançois Tigeot 		return r;
952926deccbSFrançois Tigeot 	}
953926deccbSFrançois Tigeot 
954926deccbSFrançois Tigeot 	if (radeon_fence_need_sync(*fence, ring->idx)) {
955926deccbSFrançois Tigeot 		radeon_semaphore_sync_rings(rdev, sem, (*fence)->ring,
956926deccbSFrançois Tigeot 					    ring->idx);
957926deccbSFrançois Tigeot 		radeon_fence_note_sync(*fence, ring->idx);
958926deccbSFrançois Tigeot 	} else {
959926deccbSFrançois Tigeot 		radeon_semaphore_free(rdev, &sem, NULL);
960926deccbSFrançois Tigeot 	}
961926deccbSFrançois Tigeot 
962926deccbSFrançois Tigeot 	for (i = 0; i < num_loops; i++) {
963926deccbSFrançois Tigeot 		cur_size_in_dw = size_in_dw;
964926deccbSFrançois Tigeot 		if (cur_size_in_dw > 0xFFFF)
965926deccbSFrançois Tigeot 			cur_size_in_dw = 0xFFFF;
966926deccbSFrançois Tigeot 		size_in_dw -= cur_size_in_dw;
967926deccbSFrançois Tigeot 		radeon_ring_write(ring, DMA_PACKET(DMA_PACKET_COPY, 0, 0, cur_size_in_dw));
968926deccbSFrançois Tigeot 		radeon_ring_write(ring, dst_offset & 0xfffffffc);
969926deccbSFrançois Tigeot 		radeon_ring_write(ring, src_offset & 0xfffffffc);
970926deccbSFrançois Tigeot 		radeon_ring_write(ring, upper_32_bits(dst_offset) & 0xff);
971926deccbSFrançois Tigeot 		radeon_ring_write(ring, upper_32_bits(src_offset) & 0xff);
972926deccbSFrançois Tigeot 		src_offset += cur_size_in_dw * 4;
973926deccbSFrançois Tigeot 		dst_offset += cur_size_in_dw * 4;
974926deccbSFrançois Tigeot 	}
975926deccbSFrançois Tigeot 
976926deccbSFrançois Tigeot 	r = radeon_fence_emit(rdev, fence, ring->idx);
977926deccbSFrançois Tigeot 	if (r) {
978926deccbSFrançois Tigeot 		radeon_ring_unlock_undo(rdev, ring);
979926deccbSFrançois Tigeot 		return r;
980926deccbSFrançois Tigeot 	}
981926deccbSFrançois Tigeot 
982926deccbSFrançois Tigeot 	radeon_ring_unlock_commit(rdev, ring);
983926deccbSFrançois Tigeot 	radeon_semaphore_free(rdev, &sem, *fence);
984926deccbSFrançois Tigeot 
985926deccbSFrançois Tigeot 	return r;
986926deccbSFrançois Tigeot }
987926deccbSFrançois Tigeot 
988926deccbSFrançois Tigeot static int rv770_startup(struct radeon_device *rdev)
989926deccbSFrançois Tigeot {
990926deccbSFrançois Tigeot 	struct radeon_ring *ring;
991926deccbSFrançois Tigeot 	int r;
992926deccbSFrançois Tigeot 
993926deccbSFrançois Tigeot 	/* enable pcie gen2 link */
994926deccbSFrançois Tigeot 	rv770_pcie_gen2_enable(rdev);
995926deccbSFrançois Tigeot 
996926deccbSFrançois Tigeot 	if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw) {
997926deccbSFrançois Tigeot 		r = r600_init_microcode(rdev);
998926deccbSFrançois Tigeot 		if (r) {
999926deccbSFrançois Tigeot 			DRM_ERROR("Failed to load firmware!\n");
1000926deccbSFrançois Tigeot 			return r;
1001926deccbSFrançois Tigeot 		}
1002926deccbSFrançois Tigeot 	}
1003926deccbSFrançois Tigeot 
1004926deccbSFrançois Tigeot 	r = r600_vram_scratch_init(rdev);
1005926deccbSFrançois Tigeot 	if (r)
1006926deccbSFrançois Tigeot 		return r;
1007926deccbSFrançois Tigeot 
1008926deccbSFrançois Tigeot 	rv770_mc_program(rdev);
1009926deccbSFrançois Tigeot 	if (rdev->flags & RADEON_IS_AGP) {
1010926deccbSFrançois Tigeot 		rv770_agp_enable(rdev);
1011926deccbSFrançois Tigeot 	} else {
1012926deccbSFrançois Tigeot 		r = rv770_pcie_gart_enable(rdev);
1013926deccbSFrançois Tigeot 		if (r)
1014926deccbSFrançois Tigeot 			return r;
1015926deccbSFrançois Tigeot 	}
1016926deccbSFrançois Tigeot 
1017926deccbSFrançois Tigeot 	rv770_gpu_init(rdev);
1018926deccbSFrançois Tigeot 	r = r600_blit_init(rdev);
1019926deccbSFrançois Tigeot 	if (r) {
1020926deccbSFrançois Tigeot 		r600_blit_fini(rdev);
1021926deccbSFrançois Tigeot 		rdev->asic->copy.copy = NULL;
1022926deccbSFrançois Tigeot 		dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r);
1023926deccbSFrançois Tigeot 	}
1024926deccbSFrançois Tigeot 
1025926deccbSFrançois Tigeot 	/* allocate wb buffer */
1026926deccbSFrançois Tigeot 	r = radeon_wb_init(rdev);
1027926deccbSFrançois Tigeot 	if (r)
1028926deccbSFrançois Tigeot 		return r;
1029926deccbSFrançois Tigeot 
1030926deccbSFrançois Tigeot 	r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX);
1031926deccbSFrançois Tigeot 	if (r) {
1032926deccbSFrançois Tigeot 		dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r);
1033926deccbSFrançois Tigeot 		return r;
1034926deccbSFrançois Tigeot 	}
1035926deccbSFrançois Tigeot 
1036926deccbSFrançois Tigeot 	r = radeon_fence_driver_start_ring(rdev, R600_RING_TYPE_DMA_INDEX);
1037926deccbSFrançois Tigeot 	if (r) {
1038926deccbSFrançois Tigeot 		dev_err(rdev->dev, "failed initializing DMA fences (%d).\n", r);
1039926deccbSFrançois Tigeot 		return r;
1040926deccbSFrançois Tigeot 	}
1041926deccbSFrançois Tigeot 
1042926deccbSFrançois Tigeot 	/* Enable IRQ */
1043926deccbSFrançois Tigeot 	r = r600_irq_init(rdev);
1044926deccbSFrançois Tigeot 	if (r) {
1045926deccbSFrançois Tigeot 		DRM_ERROR("radeon: IH init failed (%d).\n", r);
1046926deccbSFrançois Tigeot 		radeon_irq_kms_fini(rdev);
1047926deccbSFrançois Tigeot 		return r;
1048926deccbSFrançois Tigeot 	}
1049926deccbSFrançois Tigeot 	r600_irq_set(rdev);
1050926deccbSFrançois Tigeot 
1051926deccbSFrançois Tigeot 	ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
1052926deccbSFrançois Tigeot 	r = radeon_ring_init(rdev, ring, ring->ring_size, RADEON_WB_CP_RPTR_OFFSET,
1053926deccbSFrançois Tigeot 			     R600_CP_RB_RPTR, R600_CP_RB_WPTR,
1054926deccbSFrançois Tigeot 			     0, 0xfffff, RADEON_CP_PACKET2);
1055926deccbSFrançois Tigeot 	if (r)
1056926deccbSFrançois Tigeot 		return r;
1057926deccbSFrançois Tigeot 
1058926deccbSFrançois Tigeot 	ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX];
1059926deccbSFrançois Tigeot 	r = radeon_ring_init(rdev, ring, ring->ring_size, R600_WB_DMA_RPTR_OFFSET,
1060926deccbSFrançois Tigeot 			     DMA_RB_RPTR, DMA_RB_WPTR,
1061926deccbSFrançois Tigeot 			     2, 0x3fffc, DMA_PACKET(DMA_PACKET_NOP, 0, 0, 0));
1062926deccbSFrançois Tigeot 	if (r)
1063926deccbSFrançois Tigeot 		return r;
1064926deccbSFrançois Tigeot 
1065926deccbSFrançois Tigeot 	r = rv770_cp_load_microcode(rdev);
1066926deccbSFrançois Tigeot 	if (r)
1067926deccbSFrançois Tigeot 		return r;
1068926deccbSFrançois Tigeot 	r = r600_cp_resume(rdev);
1069926deccbSFrançois Tigeot 	if (r)
1070926deccbSFrançois Tigeot 		return r;
1071926deccbSFrançois Tigeot 
1072926deccbSFrançois Tigeot 	r = r600_dma_resume(rdev);
1073926deccbSFrançois Tigeot 	if (r)
1074926deccbSFrançois Tigeot 		return r;
1075926deccbSFrançois Tigeot 
1076926deccbSFrançois Tigeot 	r = radeon_ib_pool_init(rdev);
1077926deccbSFrançois Tigeot 	if (r) {
1078926deccbSFrançois Tigeot 		dev_err(rdev->dev, "IB initialization failed (%d).\n", r);
1079926deccbSFrançois Tigeot 		return r;
1080926deccbSFrançois Tigeot 	}
1081926deccbSFrançois Tigeot 
1082926deccbSFrançois Tigeot 	r = r600_audio_init(rdev);
1083926deccbSFrançois Tigeot 	if (r) {
1084926deccbSFrançois Tigeot 		DRM_ERROR("radeon: audio init failed\n");
1085926deccbSFrançois Tigeot 		return r;
1086926deccbSFrançois Tigeot 	}
1087926deccbSFrançois Tigeot 
1088926deccbSFrançois Tigeot 	return 0;
1089926deccbSFrançois Tigeot }
1090926deccbSFrançois Tigeot 
1091926deccbSFrançois Tigeot int rv770_resume(struct radeon_device *rdev)
1092926deccbSFrançois Tigeot {
1093926deccbSFrançois Tigeot 	int r;
1094926deccbSFrançois Tigeot 
1095926deccbSFrançois Tigeot 	/* Do not reset GPU before posting, on rv770 hw unlike on r500 hw,
1096926deccbSFrançois Tigeot 	 * posting will perform necessary task to bring back GPU into good
1097926deccbSFrançois Tigeot 	 * shape.
1098926deccbSFrançois Tigeot 	 */
1099926deccbSFrançois Tigeot 	/* post card */
1100926deccbSFrançois Tigeot 	atom_asic_init(rdev->mode_info.atom_context);
1101926deccbSFrançois Tigeot 
1102926deccbSFrançois Tigeot 	rdev->accel_working = true;
1103926deccbSFrançois Tigeot 	r = rv770_startup(rdev);
1104926deccbSFrançois Tigeot 	if (r) {
1105926deccbSFrançois Tigeot 		DRM_ERROR("r600 startup failed on resume\n");
1106926deccbSFrançois Tigeot 		rdev->accel_working = false;
1107926deccbSFrançois Tigeot 		return r;
1108926deccbSFrançois Tigeot 	}
1109926deccbSFrançois Tigeot 
1110926deccbSFrançois Tigeot 	return r;
1111926deccbSFrançois Tigeot 
1112926deccbSFrançois Tigeot }
1113926deccbSFrançois Tigeot 
1114926deccbSFrançois Tigeot int rv770_suspend(struct radeon_device *rdev)
1115926deccbSFrançois Tigeot {
1116926deccbSFrançois Tigeot 	r600_audio_fini(rdev);
1117926deccbSFrançois Tigeot 	r700_cp_stop(rdev);
1118926deccbSFrançois Tigeot 	r600_dma_stop(rdev);
1119926deccbSFrançois Tigeot 	r600_irq_suspend(rdev);
1120926deccbSFrançois Tigeot 	radeon_wb_disable(rdev);
1121926deccbSFrançois Tigeot 	rv770_pcie_gart_disable(rdev);
1122926deccbSFrançois Tigeot 
1123926deccbSFrançois Tigeot 	return 0;
1124926deccbSFrançois Tigeot }
1125926deccbSFrançois Tigeot 
1126926deccbSFrançois Tigeot /* Plan is to move initialization in that function and use
1127926deccbSFrançois Tigeot  * helper function so that radeon_device_init pretty much
1128926deccbSFrançois Tigeot  * do nothing more than calling asic specific function. This
1129926deccbSFrançois Tigeot  * should also allow to remove a bunch of callback function
1130926deccbSFrançois Tigeot  * like vram_info.
1131926deccbSFrançois Tigeot  */
1132926deccbSFrançois Tigeot int rv770_init(struct radeon_device *rdev)
1133926deccbSFrançois Tigeot {
1134926deccbSFrançois Tigeot 	int r;
1135926deccbSFrançois Tigeot 
1136926deccbSFrançois Tigeot 	/* Read BIOS */
1137926deccbSFrançois Tigeot 	if (!radeon_get_bios(rdev)) {
1138926deccbSFrançois Tigeot 		if (ASIC_IS_AVIVO(rdev))
1139926deccbSFrançois Tigeot 			return -EINVAL;
1140926deccbSFrançois Tigeot 	}
1141926deccbSFrançois Tigeot 	/* Must be an ATOMBIOS */
1142926deccbSFrançois Tigeot 	if (!rdev->is_atom_bios) {
1143926deccbSFrançois Tigeot 		dev_err(rdev->dev, "Expecting atombios for R600 GPU\n");
1144926deccbSFrançois Tigeot 		return -EINVAL;
1145926deccbSFrançois Tigeot 	}
1146926deccbSFrançois Tigeot 	r = radeon_atombios_init(rdev);
1147926deccbSFrançois Tigeot 	if (r)
1148926deccbSFrançois Tigeot 		return r;
1149926deccbSFrançois Tigeot 	/* Post card if necessary */
1150926deccbSFrançois Tigeot 	if (!radeon_card_posted(rdev)) {
1151926deccbSFrançois Tigeot 		if (!rdev->bios) {
1152926deccbSFrançois Tigeot 			dev_err(rdev->dev, "Card not posted and no BIOS - ignoring\n");
1153926deccbSFrançois Tigeot 			return -EINVAL;
1154926deccbSFrançois Tigeot 		}
1155926deccbSFrançois Tigeot 		DRM_INFO("GPU not posted. posting now...\n");
1156926deccbSFrançois Tigeot 		atom_asic_init(rdev->mode_info.atom_context);
1157926deccbSFrançois Tigeot 	}
1158926deccbSFrançois Tigeot 	/* Initialize scratch registers */
1159926deccbSFrançois Tigeot 	r600_scratch_init(rdev);
1160926deccbSFrançois Tigeot 	/* Initialize surface registers */
1161926deccbSFrançois Tigeot 	radeon_surface_init(rdev);
1162926deccbSFrançois Tigeot 	/* Initialize clocks */
1163926deccbSFrançois Tigeot 	radeon_get_clock_info(rdev->ddev);
1164926deccbSFrançois Tigeot 	/* Fence driver */
1165926deccbSFrançois Tigeot 	r = radeon_fence_driver_init(rdev);
1166926deccbSFrançois Tigeot 	if (r)
1167926deccbSFrançois Tigeot 		return r;
1168926deccbSFrançois Tigeot 	/* initialize AGP */
1169926deccbSFrançois Tigeot 	if (rdev->flags & RADEON_IS_AGP) {
1170926deccbSFrançois Tigeot 		r = radeon_agp_init(rdev);
1171926deccbSFrançois Tigeot 		if (r)
1172926deccbSFrançois Tigeot 			radeon_agp_disable(rdev);
1173926deccbSFrançois Tigeot 	}
1174926deccbSFrançois Tigeot 	r = rv770_mc_init(rdev);
1175926deccbSFrançois Tigeot 	if (r)
1176926deccbSFrançois Tigeot 		return r;
1177926deccbSFrançois Tigeot 	/* Memory manager */
1178926deccbSFrançois Tigeot 	r = radeon_bo_init(rdev);
1179926deccbSFrançois Tigeot 	if (r)
1180926deccbSFrançois Tigeot 		return r;
1181926deccbSFrançois Tigeot 
1182926deccbSFrançois Tigeot 	r = radeon_irq_kms_init(rdev);
1183926deccbSFrançois Tigeot 	if (r)
1184926deccbSFrançois Tigeot 		return r;
1185926deccbSFrançois Tigeot 
1186926deccbSFrançois Tigeot 	rdev->ring[RADEON_RING_TYPE_GFX_INDEX].ring_obj = NULL;
1187926deccbSFrançois Tigeot 	r600_ring_init(rdev, &rdev->ring[RADEON_RING_TYPE_GFX_INDEX], 1024 * 1024);
1188926deccbSFrançois Tigeot 
1189926deccbSFrançois Tigeot 	rdev->ring[R600_RING_TYPE_DMA_INDEX].ring_obj = NULL;
1190926deccbSFrançois Tigeot 	r600_ring_init(rdev, &rdev->ring[R600_RING_TYPE_DMA_INDEX], 64 * 1024);
1191926deccbSFrançois Tigeot 
1192926deccbSFrançois Tigeot 	rdev->ih.ring_obj = NULL;
1193926deccbSFrançois Tigeot 	r600_ih_ring_init(rdev, 64 * 1024);
1194926deccbSFrançois Tigeot 
1195926deccbSFrançois Tigeot 	r = r600_pcie_gart_init(rdev);
1196926deccbSFrançois Tigeot 	if (r)
1197926deccbSFrançois Tigeot 		return r;
1198926deccbSFrançois Tigeot 
1199926deccbSFrançois Tigeot 	rdev->accel_working = true;
1200926deccbSFrançois Tigeot 	r = rv770_startup(rdev);
1201926deccbSFrançois Tigeot 	if (r) {
1202926deccbSFrançois Tigeot 		dev_err(rdev->dev, "disabling GPU acceleration\n");
1203926deccbSFrançois Tigeot 		r700_cp_fini(rdev);
1204926deccbSFrançois Tigeot 		r600_dma_fini(rdev);
1205926deccbSFrançois Tigeot 		r600_irq_fini(rdev);
1206926deccbSFrançois Tigeot 		radeon_wb_fini(rdev);
1207926deccbSFrançois Tigeot 		radeon_ib_pool_fini(rdev);
1208926deccbSFrançois Tigeot 		radeon_irq_kms_fini(rdev);
1209926deccbSFrançois Tigeot 		rv770_pcie_gart_fini(rdev);
1210926deccbSFrançois Tigeot 		rdev->accel_working = false;
1211926deccbSFrançois Tigeot 	}
1212926deccbSFrançois Tigeot 
1213926deccbSFrançois Tigeot 	return 0;
1214926deccbSFrançois Tigeot }
1215926deccbSFrançois Tigeot 
1216926deccbSFrançois Tigeot void rv770_fini(struct radeon_device *rdev)
1217926deccbSFrançois Tigeot {
1218926deccbSFrançois Tigeot 	r600_blit_fini(rdev);
1219926deccbSFrançois Tigeot 	r700_cp_fini(rdev);
1220926deccbSFrançois Tigeot 	r600_dma_fini(rdev);
1221926deccbSFrançois Tigeot 	r600_irq_fini(rdev);
1222926deccbSFrançois Tigeot 	radeon_wb_fini(rdev);
1223926deccbSFrançois Tigeot 	radeon_ib_pool_fini(rdev);
1224926deccbSFrançois Tigeot 	radeon_irq_kms_fini(rdev);
1225926deccbSFrançois Tigeot 	rv770_pcie_gart_fini(rdev);
1226926deccbSFrançois Tigeot 	r600_vram_scratch_fini(rdev);
1227926deccbSFrançois Tigeot 	radeon_gem_fini(rdev);
1228926deccbSFrançois Tigeot 	radeon_fence_driver_fini(rdev);
1229926deccbSFrançois Tigeot 	radeon_agp_fini(rdev);
1230926deccbSFrançois Tigeot 	radeon_bo_fini(rdev);
1231926deccbSFrançois Tigeot 	radeon_atombios_fini(rdev);
1232926deccbSFrançois Tigeot 	r600_fini_microcode(rdev);
12335a3b77d5SFrançois Tigeot 	drm_free(rdev->bios, M_DRM);
1234926deccbSFrançois Tigeot 	rdev->bios = NULL;
1235926deccbSFrançois Tigeot }
1236926deccbSFrançois Tigeot 
1237926deccbSFrançois Tigeot static void rv770_pcie_gen2_enable(struct radeon_device *rdev)
1238926deccbSFrançois Tigeot {
1239926deccbSFrançois Tigeot 	u32 link_width_cntl, lanes, speed_cntl, tmp;
1240926deccbSFrançois Tigeot 	u16 link_cntl2;
1241926deccbSFrançois Tigeot 	u32 mask;
1242926deccbSFrançois Tigeot 	int ret;
1243926deccbSFrançois Tigeot 
1244926deccbSFrançois Tigeot 	if (radeon_pcie_gen2 == 0)
1245926deccbSFrançois Tigeot 		return;
1246926deccbSFrançois Tigeot 
1247926deccbSFrançois Tigeot 	if (rdev->flags & RADEON_IS_IGP)
1248926deccbSFrançois Tigeot 		return;
1249926deccbSFrançois Tigeot 
1250926deccbSFrançois Tigeot 	if (!(rdev->flags & RADEON_IS_PCIE))
1251926deccbSFrançois Tigeot 		return;
1252926deccbSFrançois Tigeot 
1253926deccbSFrançois Tigeot 	/* x2 cards have a special sequence */
1254926deccbSFrançois Tigeot 	if (ASIC_IS_X2(rdev))
1255926deccbSFrançois Tigeot 		return;
1256926deccbSFrançois Tigeot 
1257926deccbSFrançois Tigeot 	ret = drm_pcie_get_speed_cap_mask(rdev->ddev, &mask);
1258926deccbSFrançois Tigeot 	if (ret != 0)
1259926deccbSFrançois Tigeot 		return;
1260926deccbSFrançois Tigeot 
1261926deccbSFrançois Tigeot 	if (!(mask & DRM_PCIE_SPEED_50))
1262926deccbSFrançois Tigeot 		return;
1263926deccbSFrançois Tigeot 
1264926deccbSFrançois Tigeot 	DRM_INFO("enabling PCIE gen 2 link speeds, disable with radeon.pcie_gen2=0\n");
1265926deccbSFrançois Tigeot 
1266926deccbSFrançois Tigeot 	/* advertise upconfig capability */
1267926deccbSFrançois Tigeot 	link_width_cntl = RREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL);
1268926deccbSFrançois Tigeot 	link_width_cntl &= ~LC_UPCONFIGURE_DIS;
1269926deccbSFrançois Tigeot 	WREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl);
1270926deccbSFrançois Tigeot 	link_width_cntl = RREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL);
1271926deccbSFrançois Tigeot 	if (link_width_cntl & LC_RENEGOTIATION_SUPPORT) {
1272926deccbSFrançois Tigeot 		lanes = (link_width_cntl & LC_LINK_WIDTH_RD_MASK) >> LC_LINK_WIDTH_RD_SHIFT;
1273926deccbSFrançois Tigeot 		link_width_cntl &= ~(LC_LINK_WIDTH_MASK |
1274926deccbSFrançois Tigeot 				     LC_RECONFIG_ARC_MISSING_ESCAPE);
1275926deccbSFrançois Tigeot 		link_width_cntl |= lanes | LC_RECONFIG_NOW |
1276926deccbSFrançois Tigeot 			LC_RENEGOTIATE_EN | LC_UPCONFIGURE_SUPPORT;
1277926deccbSFrançois Tigeot 		WREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl);
1278926deccbSFrançois Tigeot 	} else {
1279926deccbSFrançois Tigeot 		link_width_cntl |= LC_UPCONFIGURE_DIS;
1280926deccbSFrançois Tigeot 		WREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl);
1281926deccbSFrançois Tigeot 	}
1282926deccbSFrançois Tigeot 
1283926deccbSFrançois Tigeot 	speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL);
1284926deccbSFrançois Tigeot 	if ((speed_cntl & LC_OTHER_SIDE_EVER_SENT_GEN2) &&
1285926deccbSFrançois Tigeot 	    (speed_cntl & LC_OTHER_SIDE_SUPPORTS_GEN2)) {
1286926deccbSFrançois Tigeot 
1287926deccbSFrançois Tigeot 		tmp = RREG32(0x541c);
1288926deccbSFrançois Tigeot 		WREG32(0x541c, tmp | 0x8);
1289926deccbSFrançois Tigeot 		WREG32(MM_CFGREGS_CNTL, MM_WR_TO_CFG_EN);
1290926deccbSFrançois Tigeot 		link_cntl2 = RREG16(0x4088);
1291926deccbSFrançois Tigeot 		link_cntl2 &= ~TARGET_LINK_SPEED_MASK;
1292926deccbSFrançois Tigeot 		link_cntl2 |= 0x2;
1293926deccbSFrançois Tigeot 		WREG16(0x4088, link_cntl2);
1294926deccbSFrançois Tigeot 		WREG32(MM_CFGREGS_CNTL, 0);
1295926deccbSFrançois Tigeot 
1296926deccbSFrançois Tigeot 		speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL);
1297926deccbSFrançois Tigeot 		speed_cntl &= ~LC_TARGET_LINK_SPEED_OVERRIDE_EN;
1298926deccbSFrançois Tigeot 		WREG32_PCIE_P(PCIE_LC_SPEED_CNTL, speed_cntl);
1299926deccbSFrançois Tigeot 
1300926deccbSFrançois Tigeot 		speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL);
1301926deccbSFrançois Tigeot 		speed_cntl |= LC_CLR_FAILED_SPD_CHANGE_CNT;
1302926deccbSFrançois Tigeot 		WREG32_PCIE_P(PCIE_LC_SPEED_CNTL, speed_cntl);
1303926deccbSFrançois Tigeot 
1304926deccbSFrançois Tigeot 		speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL);
1305926deccbSFrançois Tigeot 		speed_cntl &= ~LC_CLR_FAILED_SPD_CHANGE_CNT;
1306926deccbSFrançois Tigeot 		WREG32_PCIE_P(PCIE_LC_SPEED_CNTL, speed_cntl);
1307926deccbSFrançois Tigeot 
1308926deccbSFrançois Tigeot 		speed_cntl = RREG32_PCIE_P(PCIE_LC_SPEED_CNTL);
1309926deccbSFrançois Tigeot 		speed_cntl |= LC_GEN2_EN_STRAP;
1310926deccbSFrançois Tigeot 		WREG32_PCIE_P(PCIE_LC_SPEED_CNTL, speed_cntl);
1311926deccbSFrançois Tigeot 
1312926deccbSFrançois Tigeot 	} else {
1313926deccbSFrançois Tigeot 		link_width_cntl = RREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL);
1314926deccbSFrançois Tigeot 		/* XXX: only disable it if gen1 bridge vendor == 0x111d or 0x1106 */
1315926deccbSFrançois Tigeot 		if (1)
1316926deccbSFrançois Tigeot 			link_width_cntl |= LC_UPCONFIGURE_DIS;
1317926deccbSFrançois Tigeot 		else
1318926deccbSFrançois Tigeot 			link_width_cntl &= ~LC_UPCONFIGURE_DIS;
1319926deccbSFrançois Tigeot 		WREG32_PCIE_P(PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl);
1320926deccbSFrançois Tigeot 	}
1321926deccbSFrançois Tigeot }
1322