xref: /dflybsd-src/sys/dev/drm/radeon/r300.c (revision a85cb24f18e3804e75ab8bcda7692564d0563317)
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  */
287dcf36dcSFrançois Tigeot #include <linux/seq_file.h>
29926deccbSFrançois Tigeot #include <drm/drmP.h>
3083b4b9b9SFrançois Tigeot #include <drm/drm.h>
31926deccbSFrançois Tigeot #include <drm/drm_crtc_helper.h>
32926deccbSFrançois Tigeot #include "radeon_reg.h"
33926deccbSFrançois Tigeot #include "radeon.h"
34926deccbSFrançois Tigeot #include "radeon_asic.h"
3583b4b9b9SFrançois Tigeot #include <drm/radeon_drm.h>
36926deccbSFrançois Tigeot #include "r100_track.h"
37926deccbSFrançois Tigeot #include "r300d.h"
38926deccbSFrançois Tigeot #include "rv350d.h"
39926deccbSFrançois Tigeot #include "r300_reg_safe.h"
40926deccbSFrançois Tigeot 
41926deccbSFrançois Tigeot /* This files gather functions specifics to: r300,r350,rv350,rv370,rv380
42926deccbSFrançois Tigeot  *
43926deccbSFrançois Tigeot  * GPU Errata:
44926deccbSFrançois Tigeot  * - HOST_PATH_CNTL: r300 family seems to dislike write to HOST_PATH_CNTL
45926deccbSFrançois Tigeot  *   using MMIO to flush host path read cache, this lead to HARDLOCKUP.
46926deccbSFrançois Tigeot  *   However, scheduling such write to the ring seems harmless, i suspect
47926deccbSFrançois Tigeot  *   the CP read collide with the flush somehow, or maybe the MC, hard to
48926deccbSFrançois Tigeot  *   tell. (Jerome Glisse)
49926deccbSFrançois Tigeot  */
50926deccbSFrançois Tigeot 
51926deccbSFrançois Tigeot /*
52c59a5c48SFrançois Tigeot  * Indirect registers accessor
53c59a5c48SFrançois Tigeot  */
rv370_pcie_rreg(struct radeon_device * rdev,uint32_t reg)54c59a5c48SFrançois Tigeot uint32_t rv370_pcie_rreg(struct radeon_device *rdev, uint32_t reg)
55c59a5c48SFrançois Tigeot {
56c59a5c48SFrançois Tigeot 	uint32_t r;
57c59a5c48SFrançois Tigeot 
58ec5b6af4SFrançois Tigeot 	lockmgr(&rdev->pcie_idx_lock, LK_EXCLUSIVE);
59c59a5c48SFrançois Tigeot 	WREG32(RADEON_PCIE_INDEX, ((reg) & rdev->pcie_reg_mask));
60c59a5c48SFrançois Tigeot 	r = RREG32(RADEON_PCIE_DATA);
61ec5b6af4SFrançois Tigeot 	lockmgr(&rdev->pcie_idx_lock, LK_RELEASE);
62c59a5c48SFrançois Tigeot 	return r;
63c59a5c48SFrançois Tigeot }
64c59a5c48SFrançois Tigeot 
rv370_pcie_wreg(struct radeon_device * rdev,uint32_t reg,uint32_t v)65c59a5c48SFrançois Tigeot void rv370_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v)
66c59a5c48SFrançois Tigeot {
67ec5b6af4SFrançois Tigeot 	lockmgr(&rdev->pcie_idx_lock, LK_EXCLUSIVE);
68c59a5c48SFrançois Tigeot 	WREG32(RADEON_PCIE_INDEX, ((reg) & rdev->pcie_reg_mask));
69c59a5c48SFrançois Tigeot 	WREG32(RADEON_PCIE_DATA, (v));
70ec5b6af4SFrançois Tigeot 	lockmgr(&rdev->pcie_idx_lock, LK_RELEASE);
71c59a5c48SFrançois Tigeot }
72c59a5c48SFrançois Tigeot 
73c59a5c48SFrançois Tigeot /*
74926deccbSFrançois Tigeot  * rv370,rv380 PCIE GART
75926deccbSFrançois Tigeot  */
76926deccbSFrançois Tigeot static int rv370_debugfs_pcie_gart_info_init(struct radeon_device *rdev);
77926deccbSFrançois Tigeot 
rv370_pcie_gart_tlb_flush(struct radeon_device * rdev)78926deccbSFrançois Tigeot void rv370_pcie_gart_tlb_flush(struct radeon_device *rdev)
79926deccbSFrançois Tigeot {
80926deccbSFrançois Tigeot 	uint32_t tmp;
81926deccbSFrançois Tigeot 	int i;
82926deccbSFrançois Tigeot 
83926deccbSFrançois Tigeot 	/* Workaround HW bug do flush 2 times */
84926deccbSFrançois Tigeot 	for (i = 0; i < 2; i++) {
85926deccbSFrançois Tigeot 		tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL);
86926deccbSFrançois Tigeot 		WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp | RADEON_PCIE_TX_GART_INVALIDATE_TLB);
87926deccbSFrançois Tigeot 		(void)RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL);
88926deccbSFrançois Tigeot 		WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp);
89926deccbSFrançois Tigeot 	}
90c4ef309bSzrj 	mb();
91926deccbSFrançois Tigeot }
92926deccbSFrançois Tigeot 
93c6f73aabSFrançois Tigeot #define R300_PTE_UNSNOOPED (1 << 0)
94926deccbSFrançois Tigeot #define R300_PTE_WRITEABLE (1 << 2)
95926deccbSFrançois Tigeot #define R300_PTE_READABLE  (1 << 3)
96926deccbSFrançois Tigeot 
rv370_pcie_gart_get_page_entry(uint64_t addr,uint32_t flags)977dcf36dcSFrançois Tigeot uint64_t rv370_pcie_gart_get_page_entry(uint64_t addr, uint32_t flags)
98926deccbSFrançois Tigeot {
99926deccbSFrançois Tigeot 	addr = (lower_32_bits(addr) >> 8) |
100c6f73aabSFrançois Tigeot 		((upper_32_bits(addr) & 0xff) << 24);
101c6f73aabSFrançois Tigeot 	if (flags & RADEON_GART_PAGE_READ)
102c6f73aabSFrançois Tigeot 		addr |= R300_PTE_READABLE;
103c6f73aabSFrançois Tigeot 	if (flags & RADEON_GART_PAGE_WRITE)
104c6f73aabSFrançois Tigeot 		addr |= R300_PTE_WRITEABLE;
105c6f73aabSFrançois Tigeot 	if (!(flags & RADEON_GART_PAGE_SNOOP))
106c6f73aabSFrançois Tigeot 		addr |= R300_PTE_UNSNOOPED;
1077dcf36dcSFrançois Tigeot 	return addr;
1087dcf36dcSFrançois Tigeot }
1097dcf36dcSFrançois Tigeot 
rv370_pcie_gart_set_page(struct radeon_device * rdev,unsigned i,uint64_t entry)1107dcf36dcSFrançois Tigeot void rv370_pcie_gart_set_page(struct radeon_device *rdev, unsigned i,
1117dcf36dcSFrançois Tigeot 			      uint64_t entry)
1127dcf36dcSFrançois Tigeot {
1137dcf36dcSFrançois Tigeot 	void __iomem *ptr = rdev->gart.ptr;
1147dcf36dcSFrançois Tigeot 
115926deccbSFrançois Tigeot 	/* on x86 we want this to be CPU endian, on powerpc
116926deccbSFrançois Tigeot 	 * on powerpc without HW swappers, it'll get swapped on way
117926deccbSFrançois Tigeot 	 * into VRAM - so no need for cpu_to_le32 on VRAM tables */
1187dcf36dcSFrançois Tigeot 	writel(entry, ((uint8_t __iomem *)ptr) + (i * 4));
119926deccbSFrançois Tigeot }
120926deccbSFrançois Tigeot 
rv370_pcie_gart_init(struct radeon_device * rdev)121926deccbSFrançois Tigeot int rv370_pcie_gart_init(struct radeon_device *rdev)
122926deccbSFrançois Tigeot {
123926deccbSFrançois Tigeot 	int r;
124926deccbSFrançois Tigeot 
125926deccbSFrançois Tigeot 	if (rdev->gart.robj) {
126c4ef309bSzrj 		WARN(1, "RV370 PCIE GART already initialized\n");
127926deccbSFrançois Tigeot 		return 0;
128926deccbSFrançois Tigeot 	}
129926deccbSFrançois Tigeot 	/* Initialize common gart structure */
130926deccbSFrançois Tigeot 	r = radeon_gart_init(rdev);
131926deccbSFrançois Tigeot 	if (r)
132926deccbSFrançois Tigeot 		return r;
133926deccbSFrançois Tigeot 	r = rv370_debugfs_pcie_gart_info_init(rdev);
134926deccbSFrançois Tigeot 	if (r)
135926deccbSFrançois Tigeot 		DRM_ERROR("Failed to register debugfs file for PCIE gart !\n");
136926deccbSFrançois Tigeot 	rdev->gart.table_size = rdev->gart.num_gpu_pages * 4;
137926deccbSFrançois Tigeot 	rdev->asic->gart.tlb_flush = &rv370_pcie_gart_tlb_flush;
1387dcf36dcSFrançois Tigeot 	rdev->asic->gart.get_page_entry = &rv370_pcie_gart_get_page_entry;
139926deccbSFrançois Tigeot 	rdev->asic->gart.set_page = &rv370_pcie_gart_set_page;
140926deccbSFrançois Tigeot 	return radeon_gart_table_vram_alloc(rdev);
141926deccbSFrançois Tigeot }
142926deccbSFrançois Tigeot 
rv370_pcie_gart_enable(struct radeon_device * rdev)143926deccbSFrançois Tigeot int rv370_pcie_gart_enable(struct radeon_device *rdev)
144926deccbSFrançois Tigeot {
145926deccbSFrançois Tigeot 	uint32_t table_addr;
146926deccbSFrançois Tigeot 	uint32_t tmp;
147926deccbSFrançois Tigeot 	int r;
148926deccbSFrançois Tigeot 
149926deccbSFrançois Tigeot 	if (rdev->gart.robj == NULL) {
150926deccbSFrançois Tigeot 		dev_err(rdev->dev, "No VRAM object for PCIE GART.\n");
151926deccbSFrançois Tigeot 		return -EINVAL;
152926deccbSFrançois Tigeot 	}
153926deccbSFrançois Tigeot 	r = radeon_gart_table_vram_pin(rdev);
154926deccbSFrançois Tigeot 	if (r)
155926deccbSFrançois Tigeot 		return r;
156926deccbSFrançois Tigeot 	/* discard memory request outside of configured range */
157926deccbSFrançois Tigeot 	tmp = RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD;
158926deccbSFrançois Tigeot 	WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp);
159926deccbSFrançois Tigeot 	WREG32_PCIE(RADEON_PCIE_TX_GART_START_LO, rdev->mc.gtt_start);
160926deccbSFrançois Tigeot 	tmp = rdev->mc.gtt_end & ~RADEON_GPU_PAGE_MASK;
161926deccbSFrançois Tigeot 	WREG32_PCIE(RADEON_PCIE_TX_GART_END_LO, tmp);
162926deccbSFrançois Tigeot 	WREG32_PCIE(RADEON_PCIE_TX_GART_START_HI, 0);
163926deccbSFrançois Tigeot 	WREG32_PCIE(RADEON_PCIE_TX_GART_END_HI, 0);
164926deccbSFrançois Tigeot 	table_addr = rdev->gart.table_addr;
165926deccbSFrançois Tigeot 	WREG32_PCIE(RADEON_PCIE_TX_GART_BASE, table_addr);
166926deccbSFrançois Tigeot 	/* FIXME: setup default page */
167926deccbSFrançois Tigeot 	WREG32_PCIE(RADEON_PCIE_TX_DISCARD_RD_ADDR_LO, rdev->mc.vram_start);
168926deccbSFrançois Tigeot 	WREG32_PCIE(RADEON_PCIE_TX_DISCARD_RD_ADDR_HI, 0);
169926deccbSFrançois Tigeot 	/* Clear error */
170926deccbSFrançois Tigeot 	WREG32_PCIE(RADEON_PCIE_TX_GART_ERROR, 0);
171926deccbSFrançois Tigeot 	tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL);
172926deccbSFrançois Tigeot 	tmp |= RADEON_PCIE_TX_GART_EN;
173926deccbSFrançois Tigeot 	tmp |= RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD;
174926deccbSFrançois Tigeot 	WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp);
175926deccbSFrançois Tigeot 	rv370_pcie_gart_tlb_flush(rdev);
176926deccbSFrançois Tigeot 	DRM_INFO("PCIE GART of %uM enabled (table at 0x%016llX).\n",
177926deccbSFrançois Tigeot 		 (unsigned)(rdev->mc.gtt_size >> 20),
178926deccbSFrançois Tigeot 		 (unsigned long long)table_addr);
179926deccbSFrançois Tigeot 	rdev->gart.ready = true;
180926deccbSFrançois Tigeot 	return 0;
181926deccbSFrançois Tigeot }
182926deccbSFrançois Tigeot 
rv370_pcie_gart_disable(struct radeon_device * rdev)183926deccbSFrançois Tigeot void rv370_pcie_gart_disable(struct radeon_device *rdev)
184926deccbSFrançois Tigeot {
185926deccbSFrançois Tigeot 	u32 tmp;
186926deccbSFrançois Tigeot 
187926deccbSFrançois Tigeot 	WREG32_PCIE(RADEON_PCIE_TX_GART_START_LO, 0);
188926deccbSFrançois Tigeot 	WREG32_PCIE(RADEON_PCIE_TX_GART_END_LO, 0);
189926deccbSFrançois Tigeot 	WREG32_PCIE(RADEON_PCIE_TX_GART_START_HI, 0);
190926deccbSFrançois Tigeot 	WREG32_PCIE(RADEON_PCIE_TX_GART_END_HI, 0);
191926deccbSFrançois Tigeot 	tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL);
192926deccbSFrançois Tigeot 	tmp |= RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD;
193926deccbSFrançois Tigeot 	WREG32_PCIE(RADEON_PCIE_TX_GART_CNTL, tmp & ~RADEON_PCIE_TX_GART_EN);
194926deccbSFrançois Tigeot 	radeon_gart_table_vram_unpin(rdev);
195926deccbSFrançois Tigeot }
196926deccbSFrançois Tigeot 
rv370_pcie_gart_fini(struct radeon_device * rdev)197926deccbSFrançois Tigeot void rv370_pcie_gart_fini(struct radeon_device *rdev)
198926deccbSFrançois Tigeot {
199926deccbSFrançois Tigeot 	radeon_gart_fini(rdev);
200926deccbSFrançois Tigeot 	rv370_pcie_gart_disable(rdev);
201926deccbSFrançois Tigeot 	radeon_gart_table_vram_free(rdev);
202926deccbSFrançois Tigeot }
203926deccbSFrançois Tigeot 
r300_fence_ring_emit(struct radeon_device * rdev,struct radeon_fence * fence)204926deccbSFrançois Tigeot void r300_fence_ring_emit(struct radeon_device *rdev,
205926deccbSFrançois Tigeot 			  struct radeon_fence *fence)
206926deccbSFrançois Tigeot {
207926deccbSFrançois Tigeot 	struct radeon_ring *ring = &rdev->ring[fence->ring];
208926deccbSFrançois Tigeot 
209926deccbSFrançois Tigeot 	/* Who ever call radeon_fence_emit should call ring_lock and ask
210926deccbSFrançois Tigeot 	 * for enough space (today caller are ib schedule and buffer move) */
211926deccbSFrançois Tigeot 	/* Write SC register so SC & US assert idle */
212926deccbSFrançois Tigeot 	radeon_ring_write(ring, PACKET0(R300_RE_SCISSORS_TL, 0));
213926deccbSFrançois Tigeot 	radeon_ring_write(ring, 0);
214926deccbSFrançois Tigeot 	radeon_ring_write(ring, PACKET0(R300_RE_SCISSORS_BR, 0));
215926deccbSFrançois Tigeot 	radeon_ring_write(ring, 0);
216926deccbSFrançois Tigeot 	/* Flush 3D cache */
217926deccbSFrançois Tigeot 	radeon_ring_write(ring, PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
218926deccbSFrançois Tigeot 	radeon_ring_write(ring, R300_RB3D_DC_FLUSH);
219926deccbSFrançois Tigeot 	radeon_ring_write(ring, PACKET0(R300_RB3D_ZCACHE_CTLSTAT, 0));
220926deccbSFrançois Tigeot 	radeon_ring_write(ring, R300_ZC_FLUSH);
221926deccbSFrançois Tigeot 	/* Wait until IDLE & CLEAN */
222926deccbSFrançois Tigeot 	radeon_ring_write(ring, PACKET0(RADEON_WAIT_UNTIL, 0));
223926deccbSFrançois Tigeot 	radeon_ring_write(ring, (RADEON_WAIT_3D_IDLECLEAN |
224926deccbSFrançois Tigeot 				 RADEON_WAIT_2D_IDLECLEAN |
225926deccbSFrançois Tigeot 				 RADEON_WAIT_DMA_GUI_IDLE));
226926deccbSFrançois Tigeot 	radeon_ring_write(ring, PACKET0(RADEON_HOST_PATH_CNTL, 0));
227926deccbSFrançois Tigeot 	radeon_ring_write(ring, rdev->config.r300.hdp_cntl |
228926deccbSFrançois Tigeot 				RADEON_HDP_READ_BUFFER_INVALIDATE);
229926deccbSFrançois Tigeot 	radeon_ring_write(ring, PACKET0(RADEON_HOST_PATH_CNTL, 0));
230926deccbSFrançois Tigeot 	radeon_ring_write(ring, rdev->config.r300.hdp_cntl);
231926deccbSFrançois Tigeot 	/* Emit fence sequence & fire IRQ */
232926deccbSFrançois Tigeot 	radeon_ring_write(ring, PACKET0(rdev->fence_drv[fence->ring].scratch_reg, 0));
233926deccbSFrançois Tigeot 	radeon_ring_write(ring, fence->seq);
234926deccbSFrançois Tigeot 	radeon_ring_write(ring, PACKET0(RADEON_GEN_INT_STATUS, 0));
235926deccbSFrançois Tigeot 	radeon_ring_write(ring, RADEON_SW_INT_FIRE);
236926deccbSFrançois Tigeot }
237926deccbSFrançois Tigeot 
r300_ring_start(struct radeon_device * rdev,struct radeon_ring * ring)238926deccbSFrançois Tigeot void r300_ring_start(struct radeon_device *rdev, struct radeon_ring *ring)
239926deccbSFrançois Tigeot {
240926deccbSFrançois Tigeot 	unsigned gb_tile_config;
241926deccbSFrançois Tigeot 	int r;
242926deccbSFrançois Tigeot 
243926deccbSFrançois Tigeot 	/* Sub pixel 1/12 so we can have 4K rendering according to doc */
244926deccbSFrançois Tigeot 	gb_tile_config = (R300_ENABLE_TILING | R300_TILE_SIZE_16);
245926deccbSFrançois Tigeot 	switch(rdev->num_gb_pipes) {
246926deccbSFrançois Tigeot 	case 2:
247926deccbSFrançois Tigeot 		gb_tile_config |= R300_PIPE_COUNT_R300;
248926deccbSFrançois Tigeot 		break;
249926deccbSFrançois Tigeot 	case 3:
250926deccbSFrançois Tigeot 		gb_tile_config |= R300_PIPE_COUNT_R420_3P;
251926deccbSFrançois Tigeot 		break;
252926deccbSFrançois Tigeot 	case 4:
253926deccbSFrançois Tigeot 		gb_tile_config |= R300_PIPE_COUNT_R420;
254926deccbSFrançois Tigeot 		break;
255926deccbSFrançois Tigeot 	case 1:
256926deccbSFrançois Tigeot 	default:
257926deccbSFrançois Tigeot 		gb_tile_config |= R300_PIPE_COUNT_RV350;
258926deccbSFrançois Tigeot 		break;
259926deccbSFrançois Tigeot 	}
260926deccbSFrançois Tigeot 
261926deccbSFrançois Tigeot 	r = radeon_ring_lock(rdev, ring, 64);
262926deccbSFrançois Tigeot 	if (r) {
263926deccbSFrançois Tigeot 		return;
264926deccbSFrançois Tigeot 	}
265926deccbSFrançois Tigeot 	radeon_ring_write(ring, PACKET0(RADEON_ISYNC_CNTL, 0));
266926deccbSFrançois Tigeot 	radeon_ring_write(ring,
267926deccbSFrançois Tigeot 			  RADEON_ISYNC_ANY2D_IDLE3D |
268926deccbSFrançois Tigeot 			  RADEON_ISYNC_ANY3D_IDLE2D |
269926deccbSFrançois Tigeot 			  RADEON_ISYNC_WAIT_IDLEGUI |
270926deccbSFrançois Tigeot 			  RADEON_ISYNC_CPSCRATCH_IDLEGUI);
271926deccbSFrançois Tigeot 	radeon_ring_write(ring, PACKET0(R300_GB_TILE_CONFIG, 0));
272926deccbSFrançois Tigeot 	radeon_ring_write(ring, gb_tile_config);
273926deccbSFrançois Tigeot 	radeon_ring_write(ring, PACKET0(RADEON_WAIT_UNTIL, 0));
274926deccbSFrançois Tigeot 	radeon_ring_write(ring,
275926deccbSFrançois Tigeot 			  RADEON_WAIT_2D_IDLECLEAN |
276926deccbSFrançois Tigeot 			  RADEON_WAIT_3D_IDLECLEAN);
277926deccbSFrançois Tigeot 	radeon_ring_write(ring, PACKET0(R300_DST_PIPE_CONFIG, 0));
278926deccbSFrançois Tigeot 	radeon_ring_write(ring, R300_PIPE_AUTO_CONFIG);
279926deccbSFrançois Tigeot 	radeon_ring_write(ring, PACKET0(R300_GB_SELECT, 0));
280926deccbSFrançois Tigeot 	radeon_ring_write(ring, 0);
281926deccbSFrançois Tigeot 	radeon_ring_write(ring, PACKET0(R300_GB_ENABLE, 0));
282926deccbSFrançois Tigeot 	radeon_ring_write(ring, 0);
283926deccbSFrançois Tigeot 	radeon_ring_write(ring, PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
284926deccbSFrançois Tigeot 	radeon_ring_write(ring, R300_RB3D_DC_FLUSH | R300_RB3D_DC_FREE);
285926deccbSFrançois Tigeot 	radeon_ring_write(ring, PACKET0(R300_RB3D_ZCACHE_CTLSTAT, 0));
286926deccbSFrançois Tigeot 	radeon_ring_write(ring, R300_ZC_FLUSH | R300_ZC_FREE);
287926deccbSFrançois Tigeot 	radeon_ring_write(ring, PACKET0(RADEON_WAIT_UNTIL, 0));
288926deccbSFrançois Tigeot 	radeon_ring_write(ring,
289926deccbSFrançois Tigeot 			  RADEON_WAIT_2D_IDLECLEAN |
290926deccbSFrançois Tigeot 			  RADEON_WAIT_3D_IDLECLEAN);
291926deccbSFrançois Tigeot 	radeon_ring_write(ring, PACKET0(R300_GB_AA_CONFIG, 0));
292926deccbSFrançois Tigeot 	radeon_ring_write(ring, 0);
293926deccbSFrançois Tigeot 	radeon_ring_write(ring, PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0));
294926deccbSFrançois Tigeot 	radeon_ring_write(ring, R300_RB3D_DC_FLUSH | R300_RB3D_DC_FREE);
295926deccbSFrançois Tigeot 	radeon_ring_write(ring, PACKET0(R300_RB3D_ZCACHE_CTLSTAT, 0));
296926deccbSFrançois Tigeot 	radeon_ring_write(ring, R300_ZC_FLUSH | R300_ZC_FREE);
297926deccbSFrançois Tigeot 	radeon_ring_write(ring, PACKET0(R300_GB_MSPOS0, 0));
298926deccbSFrançois Tigeot 	radeon_ring_write(ring,
299926deccbSFrançois Tigeot 			  ((6 << R300_MS_X0_SHIFT) |
300926deccbSFrançois Tigeot 			   (6 << R300_MS_Y0_SHIFT) |
301926deccbSFrançois Tigeot 			   (6 << R300_MS_X1_SHIFT) |
302926deccbSFrançois Tigeot 			   (6 << R300_MS_Y1_SHIFT) |
303926deccbSFrançois Tigeot 			   (6 << R300_MS_X2_SHIFT) |
304926deccbSFrançois Tigeot 			   (6 << R300_MS_Y2_SHIFT) |
305926deccbSFrançois Tigeot 			   (6 << R300_MSBD0_Y_SHIFT) |
306926deccbSFrançois Tigeot 			   (6 << R300_MSBD0_X_SHIFT)));
307926deccbSFrançois Tigeot 	radeon_ring_write(ring, PACKET0(R300_GB_MSPOS1, 0));
308926deccbSFrançois Tigeot 	radeon_ring_write(ring,
309926deccbSFrançois Tigeot 			  ((6 << R300_MS_X3_SHIFT) |
310926deccbSFrançois Tigeot 			   (6 << R300_MS_Y3_SHIFT) |
311926deccbSFrançois Tigeot 			   (6 << R300_MS_X4_SHIFT) |
312926deccbSFrançois Tigeot 			   (6 << R300_MS_Y4_SHIFT) |
313926deccbSFrançois Tigeot 			   (6 << R300_MS_X5_SHIFT) |
314926deccbSFrançois Tigeot 			   (6 << R300_MS_Y5_SHIFT) |
315926deccbSFrançois Tigeot 			   (6 << R300_MSBD1_SHIFT)));
316926deccbSFrançois Tigeot 	radeon_ring_write(ring, PACKET0(R300_GA_ENHANCE, 0));
317926deccbSFrançois Tigeot 	radeon_ring_write(ring, R300_GA_DEADLOCK_CNTL | R300_GA_FASTSYNC_CNTL);
318926deccbSFrançois Tigeot 	radeon_ring_write(ring, PACKET0(R300_GA_POLY_MODE, 0));
319926deccbSFrançois Tigeot 	radeon_ring_write(ring,
320926deccbSFrançois Tigeot 			  R300_FRONT_PTYPE_TRIANGE | R300_BACK_PTYPE_TRIANGE);
321926deccbSFrançois Tigeot 	radeon_ring_write(ring, PACKET0(R300_GA_ROUND_MODE, 0));
322926deccbSFrançois Tigeot 	radeon_ring_write(ring,
323926deccbSFrançois Tigeot 			  R300_GEOMETRY_ROUND_NEAREST |
324926deccbSFrançois Tigeot 			  R300_COLOR_ROUND_NEAREST);
325c6f73aabSFrançois Tigeot 	radeon_ring_unlock_commit(rdev, ring, false);
326926deccbSFrançois Tigeot }
327926deccbSFrançois Tigeot 
r300_errata(struct radeon_device * rdev)328926deccbSFrançois Tigeot static void r300_errata(struct radeon_device *rdev)
329926deccbSFrançois Tigeot {
330926deccbSFrançois Tigeot 	rdev->pll_errata = 0;
331926deccbSFrançois Tigeot 
332926deccbSFrançois Tigeot 	if (rdev->family == CHIP_R300 &&
333926deccbSFrançois Tigeot 	    (RREG32(RADEON_CONFIG_CNTL) & RADEON_CFG_ATI_REV_ID_MASK) == RADEON_CFG_ATI_REV_A11) {
334926deccbSFrançois Tigeot 		rdev->pll_errata |= CHIP_ERRATA_R300_CG;
335926deccbSFrançois Tigeot 	}
336926deccbSFrançois Tigeot }
337926deccbSFrançois Tigeot 
r300_mc_wait_for_idle(struct radeon_device * rdev)338926deccbSFrançois Tigeot int r300_mc_wait_for_idle(struct radeon_device *rdev)
339926deccbSFrançois Tigeot {
340926deccbSFrançois Tigeot 	unsigned i;
341926deccbSFrançois Tigeot 	uint32_t tmp;
342926deccbSFrançois Tigeot 
343926deccbSFrançois Tigeot 	for (i = 0; i < rdev->usec_timeout; i++) {
344926deccbSFrançois Tigeot 		/* read MC_STATUS */
345926deccbSFrançois Tigeot 		tmp = RREG32(RADEON_MC_STATUS);
346926deccbSFrançois Tigeot 		if (tmp & R300_MC_IDLE) {
347926deccbSFrançois Tigeot 			return 0;
348926deccbSFrançois Tigeot 		}
349926deccbSFrançois Tigeot 		DRM_UDELAY(1);
350926deccbSFrançois Tigeot 	}
351926deccbSFrançois Tigeot 	return -1;
352926deccbSFrançois Tigeot }
353926deccbSFrançois Tigeot 
r300_gpu_init(struct radeon_device * rdev)354926deccbSFrançois Tigeot static void r300_gpu_init(struct radeon_device *rdev)
355926deccbSFrançois Tigeot {
356926deccbSFrançois Tigeot 	uint32_t gb_tile_config, tmp;
357926deccbSFrançois Tigeot 
358c6f73aabSFrançois Tigeot 	if ((rdev->family == CHIP_R300 && rdev->pdev->device != 0x4144) ||
359c6f73aabSFrançois Tigeot 	    (rdev->family == CHIP_R350 && rdev->pdev->device != 0x4148)) {
360926deccbSFrançois Tigeot 		/* r300,r350 */
361926deccbSFrançois Tigeot 		rdev->num_gb_pipes = 2;
362926deccbSFrançois Tigeot 	} else {
363926deccbSFrançois Tigeot 		/* rv350,rv370,rv380,r300 AD, r350 AH */
364926deccbSFrançois Tigeot 		rdev->num_gb_pipes = 1;
365926deccbSFrançois Tigeot 	}
366926deccbSFrançois Tigeot 	rdev->num_z_pipes = 1;
367926deccbSFrançois Tigeot 	gb_tile_config = (R300_ENABLE_TILING | R300_TILE_SIZE_16);
368926deccbSFrançois Tigeot 	switch (rdev->num_gb_pipes) {
369926deccbSFrançois Tigeot 	case 2:
370926deccbSFrançois Tigeot 		gb_tile_config |= R300_PIPE_COUNT_R300;
371926deccbSFrançois Tigeot 		break;
372926deccbSFrançois Tigeot 	case 3:
373926deccbSFrançois Tigeot 		gb_tile_config |= R300_PIPE_COUNT_R420_3P;
374926deccbSFrançois Tigeot 		break;
375926deccbSFrançois Tigeot 	case 4:
376926deccbSFrançois Tigeot 		gb_tile_config |= R300_PIPE_COUNT_R420;
377926deccbSFrançois Tigeot 		break;
378926deccbSFrançois Tigeot 	default:
379926deccbSFrançois Tigeot 	case 1:
380926deccbSFrançois Tigeot 		gb_tile_config |= R300_PIPE_COUNT_RV350;
381926deccbSFrançois Tigeot 		break;
382926deccbSFrançois Tigeot 	}
383926deccbSFrançois Tigeot 	WREG32(R300_GB_TILE_CONFIG, gb_tile_config);
384926deccbSFrançois Tigeot 
385926deccbSFrançois Tigeot 	if (r100_gui_wait_for_idle(rdev)) {
386*a85cb24fSFrançois Tigeot 		pr_warn("Failed to wait GUI idle while programming pipes. Bad things might happen.\n");
387926deccbSFrançois Tigeot 	}
388926deccbSFrançois Tigeot 
389926deccbSFrançois Tigeot 	tmp = RREG32(R300_DST_PIPE_CONFIG);
390926deccbSFrançois Tigeot 	WREG32(R300_DST_PIPE_CONFIG, tmp | R300_PIPE_AUTO_CONFIG);
391926deccbSFrançois Tigeot 
392926deccbSFrançois Tigeot 	WREG32(R300_RB2D_DSTCACHE_MODE,
393926deccbSFrançois Tigeot 	       R300_DC_AUTOFLUSH_ENABLE |
394926deccbSFrançois Tigeot 	       R300_DC_DC_DISABLE_IGNORE_PE);
395926deccbSFrançois Tigeot 
396926deccbSFrançois Tigeot 	if (r100_gui_wait_for_idle(rdev)) {
397*a85cb24fSFrançois Tigeot 		pr_warn("Failed to wait GUI idle while programming pipes. Bad things might happen.\n");
398926deccbSFrançois Tigeot 	}
399926deccbSFrançois Tigeot 	if (r300_mc_wait_for_idle(rdev)) {
400*a85cb24fSFrançois Tigeot 		pr_warn("Failed to wait MC idle while programming pipes. Bad things might happen.\n");
401926deccbSFrançois Tigeot 	}
402*a85cb24fSFrançois Tigeot 	DRM_INFO("radeon: %d quad pipes, %d Z pipes initialized\n",
403926deccbSFrançois Tigeot 		 rdev->num_gb_pipes, rdev->num_z_pipes);
404926deccbSFrançois Tigeot }
405926deccbSFrançois Tigeot 
r300_asic_reset(struct radeon_device * rdev,bool hard)406d78d3a22SFrançois Tigeot int r300_asic_reset(struct radeon_device *rdev, bool hard)
407926deccbSFrançois Tigeot {
408926deccbSFrançois Tigeot 	struct r100_mc_save save;
409926deccbSFrançois Tigeot 	u32 status, tmp;
410926deccbSFrançois Tigeot 	int ret = 0;
411926deccbSFrançois Tigeot 
412926deccbSFrançois Tigeot 	status = RREG32(R_000E40_RBBM_STATUS);
413926deccbSFrançois Tigeot 	if (!G_000E40_GUI_ACTIVE(status)) {
414926deccbSFrançois Tigeot 		return 0;
415926deccbSFrançois Tigeot 	}
416926deccbSFrançois Tigeot 	r100_mc_stop(rdev, &save);
417926deccbSFrançois Tigeot 	status = RREG32(R_000E40_RBBM_STATUS);
418926deccbSFrançois Tigeot 	dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status);
419926deccbSFrançois Tigeot 	/* stop CP */
420926deccbSFrançois Tigeot 	WREG32(RADEON_CP_CSQ_CNTL, 0);
421926deccbSFrançois Tigeot 	tmp = RREG32(RADEON_CP_RB_CNTL);
422926deccbSFrançois Tigeot 	WREG32(RADEON_CP_RB_CNTL, tmp | RADEON_RB_RPTR_WR_ENA);
423926deccbSFrançois Tigeot 	WREG32(RADEON_CP_RB_RPTR_WR, 0);
424926deccbSFrançois Tigeot 	WREG32(RADEON_CP_RB_WPTR, 0);
425926deccbSFrançois Tigeot 	WREG32(RADEON_CP_RB_CNTL, tmp);
426926deccbSFrançois Tigeot 	/* save PCI state */
427fb572d17SFrançois Tigeot 	pci_save_state(device_get_parent(rdev->dev->bsddev));
428926deccbSFrançois Tigeot 	/* disable bus mastering */
429926deccbSFrançois Tigeot 	r100_bm_disable(rdev);
430926deccbSFrançois Tigeot 	WREG32(R_0000F0_RBBM_SOFT_RESET, S_0000F0_SOFT_RESET_VAP(1) |
431926deccbSFrançois Tigeot 					S_0000F0_SOFT_RESET_GA(1));
432926deccbSFrançois Tigeot 	RREG32(R_0000F0_RBBM_SOFT_RESET);
433c4ef309bSzrj 	mdelay(500);
434926deccbSFrançois Tigeot 	WREG32(R_0000F0_RBBM_SOFT_RESET, 0);
435c4ef309bSzrj 	mdelay(1);
436926deccbSFrançois Tigeot 	status = RREG32(R_000E40_RBBM_STATUS);
437926deccbSFrançois Tigeot 	dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status);
438926deccbSFrançois Tigeot 	/* resetting the CP seems to be problematic sometimes it end up
439926deccbSFrançois Tigeot 	 * hard locking the computer, but it's necessary for successful
440926deccbSFrançois Tigeot 	 * reset more test & playing is needed on R3XX/R4XX to find a
441926deccbSFrançois Tigeot 	 * reliable (if any solution)
442926deccbSFrançois Tigeot 	 */
443926deccbSFrançois Tigeot 	WREG32(R_0000F0_RBBM_SOFT_RESET, S_0000F0_SOFT_RESET_CP(1));
444926deccbSFrançois Tigeot 	RREG32(R_0000F0_RBBM_SOFT_RESET);
445c4ef309bSzrj 	mdelay(500);
446926deccbSFrançois Tigeot 	WREG32(R_0000F0_RBBM_SOFT_RESET, 0);
447c4ef309bSzrj 	mdelay(1);
448926deccbSFrançois Tigeot 	status = RREG32(R_000E40_RBBM_STATUS);
449926deccbSFrançois Tigeot 	dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status);
450926deccbSFrançois Tigeot 	/* restore PCI & busmastering */
451fb572d17SFrançois Tigeot 	pci_restore_state(device_get_parent(rdev->dev->bsddev));
452926deccbSFrançois Tigeot 	r100_enable_bm(rdev);
453926deccbSFrançois Tigeot 	/* Check if GPU is idle */
454926deccbSFrançois Tigeot 	if (G_000E40_GA_BUSY(status) || G_000E40_VAP_BUSY(status)) {
455926deccbSFrançois Tigeot 		dev_err(rdev->dev, "failed to reset GPU\n");
456926deccbSFrançois Tigeot 		ret = -1;
457926deccbSFrançois Tigeot 	} else
458926deccbSFrançois Tigeot 		dev_info(rdev->dev, "GPU reset succeed\n");
459926deccbSFrançois Tigeot 	r100_mc_resume(rdev, &save);
460926deccbSFrançois Tigeot 	return ret;
461926deccbSFrançois Tigeot }
462926deccbSFrançois Tigeot 
463926deccbSFrançois Tigeot /*
464926deccbSFrançois Tigeot  * r300,r350,rv350,rv380 VRAM info
465926deccbSFrançois Tigeot  */
r300_mc_init(struct radeon_device * rdev)466926deccbSFrançois Tigeot void r300_mc_init(struct radeon_device *rdev)
467926deccbSFrançois Tigeot {
468926deccbSFrançois Tigeot 	u64 base;
469926deccbSFrançois Tigeot 	u32 tmp;
470926deccbSFrançois Tigeot 
471926deccbSFrançois Tigeot 	/* DDR for all card after R300 & IGP */
472926deccbSFrançois Tigeot 	rdev->mc.vram_is_ddr = true;
473926deccbSFrançois Tigeot 	tmp = RREG32(RADEON_MEM_CNTL);
474926deccbSFrançois Tigeot 	tmp &= R300_MEM_NUM_CHANNELS_MASK;
475926deccbSFrançois Tigeot 	switch (tmp) {
476926deccbSFrançois Tigeot 	case 0: rdev->mc.vram_width = 64; break;
477926deccbSFrançois Tigeot 	case 1: rdev->mc.vram_width = 128; break;
478926deccbSFrançois Tigeot 	case 2: rdev->mc.vram_width = 256; break;
479926deccbSFrançois Tigeot 	default:  rdev->mc.vram_width = 128; break;
480926deccbSFrançois Tigeot 	}
481926deccbSFrançois Tigeot 	r100_vram_init_sizes(rdev);
482926deccbSFrançois Tigeot 	base = rdev->mc.aper_base;
483926deccbSFrançois Tigeot 	if (rdev->flags & RADEON_IS_IGP)
484926deccbSFrançois Tigeot 		base = (RREG32(RADEON_NB_TOM) & 0xffff) << 16;
485926deccbSFrançois Tigeot 	radeon_vram_location(rdev, &rdev->mc, base);
486926deccbSFrançois Tigeot 	rdev->mc.gtt_base_align = 0;
487926deccbSFrançois Tigeot 	if (!(rdev->flags & RADEON_IS_AGP))
488926deccbSFrançois Tigeot 		radeon_gtt_location(rdev, &rdev->mc);
489926deccbSFrançois Tigeot 	radeon_update_bandwidth_info(rdev);
490926deccbSFrançois Tigeot }
491926deccbSFrançois Tigeot 
rv370_set_pcie_lanes(struct radeon_device * rdev,int lanes)492926deccbSFrançois Tigeot void rv370_set_pcie_lanes(struct radeon_device *rdev, int lanes)
493926deccbSFrançois Tigeot {
494926deccbSFrançois Tigeot 	uint32_t link_width_cntl, mask;
495926deccbSFrançois Tigeot 
496926deccbSFrançois Tigeot 	if (rdev->flags & RADEON_IS_IGP)
497926deccbSFrançois Tigeot 		return;
498926deccbSFrançois Tigeot 
499926deccbSFrançois Tigeot 	if (!(rdev->flags & RADEON_IS_PCIE))
500926deccbSFrançois Tigeot 		return;
501926deccbSFrançois Tigeot 
502926deccbSFrançois Tigeot 	/* FIXME wait for idle */
503926deccbSFrançois Tigeot 
504926deccbSFrançois Tigeot 	switch (lanes) {
505926deccbSFrançois Tigeot 	case 0:
506926deccbSFrançois Tigeot 		mask = RADEON_PCIE_LC_LINK_WIDTH_X0;
507926deccbSFrançois Tigeot 		break;
508926deccbSFrançois Tigeot 	case 1:
509926deccbSFrançois Tigeot 		mask = RADEON_PCIE_LC_LINK_WIDTH_X1;
510926deccbSFrançois Tigeot 		break;
511926deccbSFrançois Tigeot 	case 2:
512926deccbSFrançois Tigeot 		mask = RADEON_PCIE_LC_LINK_WIDTH_X2;
513926deccbSFrançois Tigeot 		break;
514926deccbSFrançois Tigeot 	case 4:
515926deccbSFrançois Tigeot 		mask = RADEON_PCIE_LC_LINK_WIDTH_X4;
516926deccbSFrançois Tigeot 		break;
517926deccbSFrançois Tigeot 	case 8:
518926deccbSFrançois Tigeot 		mask = RADEON_PCIE_LC_LINK_WIDTH_X8;
519926deccbSFrançois Tigeot 		break;
520926deccbSFrançois Tigeot 	case 12:
521926deccbSFrançois Tigeot 		mask = RADEON_PCIE_LC_LINK_WIDTH_X12;
522926deccbSFrançois Tigeot 		break;
523926deccbSFrançois Tigeot 	case 16:
524926deccbSFrançois Tigeot 	default:
525926deccbSFrançois Tigeot 		mask = RADEON_PCIE_LC_LINK_WIDTH_X16;
526926deccbSFrançois Tigeot 		break;
527926deccbSFrançois Tigeot 	}
528926deccbSFrançois Tigeot 
529926deccbSFrançois Tigeot 	link_width_cntl = RREG32_PCIE(RADEON_PCIE_LC_LINK_WIDTH_CNTL);
530926deccbSFrançois Tigeot 
531926deccbSFrançois Tigeot 	if ((link_width_cntl & RADEON_PCIE_LC_LINK_WIDTH_RD_MASK) ==
532926deccbSFrançois Tigeot 	    (mask << RADEON_PCIE_LC_LINK_WIDTH_RD_SHIFT))
533926deccbSFrançois Tigeot 		return;
534926deccbSFrançois Tigeot 
535926deccbSFrançois Tigeot 	link_width_cntl &= ~(RADEON_PCIE_LC_LINK_WIDTH_MASK |
536926deccbSFrançois Tigeot 			     RADEON_PCIE_LC_RECONFIG_NOW |
537926deccbSFrançois Tigeot 			     RADEON_PCIE_LC_RECONFIG_LATER |
538926deccbSFrançois Tigeot 			     RADEON_PCIE_LC_SHORT_RECONFIG_EN);
539926deccbSFrançois Tigeot 	link_width_cntl |= mask;
540926deccbSFrançois Tigeot 	WREG32_PCIE(RADEON_PCIE_LC_LINK_WIDTH_CNTL, link_width_cntl);
541926deccbSFrançois Tigeot 	WREG32_PCIE(RADEON_PCIE_LC_LINK_WIDTH_CNTL, (link_width_cntl |
542926deccbSFrançois Tigeot 						     RADEON_PCIE_LC_RECONFIG_NOW));
543926deccbSFrançois Tigeot 
544926deccbSFrançois Tigeot 	/* wait for lane set to complete */
545926deccbSFrançois Tigeot 	link_width_cntl = RREG32_PCIE(RADEON_PCIE_LC_LINK_WIDTH_CNTL);
546926deccbSFrançois Tigeot 	while (link_width_cntl == 0xffffffff)
547926deccbSFrançois Tigeot 		link_width_cntl = RREG32_PCIE(RADEON_PCIE_LC_LINK_WIDTH_CNTL);
548926deccbSFrançois Tigeot 
549926deccbSFrançois Tigeot }
550926deccbSFrançois Tigeot 
rv370_get_pcie_lanes(struct radeon_device * rdev)551926deccbSFrançois Tigeot int rv370_get_pcie_lanes(struct radeon_device *rdev)
552926deccbSFrançois Tigeot {
553926deccbSFrançois Tigeot 	u32 link_width_cntl;
554926deccbSFrançois Tigeot 
555926deccbSFrançois Tigeot 	if (rdev->flags & RADEON_IS_IGP)
556926deccbSFrançois Tigeot 		return 0;
557926deccbSFrançois Tigeot 
558926deccbSFrançois Tigeot 	if (!(rdev->flags & RADEON_IS_PCIE))
559926deccbSFrançois Tigeot 		return 0;
560926deccbSFrançois Tigeot 
561926deccbSFrançois Tigeot 	/* FIXME wait for idle */
562926deccbSFrançois Tigeot 
563926deccbSFrançois Tigeot 	link_width_cntl = RREG32_PCIE(RADEON_PCIE_LC_LINK_WIDTH_CNTL);
564926deccbSFrançois Tigeot 
565926deccbSFrançois Tigeot 	switch ((link_width_cntl & RADEON_PCIE_LC_LINK_WIDTH_RD_MASK) >> RADEON_PCIE_LC_LINK_WIDTH_RD_SHIFT) {
566926deccbSFrançois Tigeot 	case RADEON_PCIE_LC_LINK_WIDTH_X0:
567926deccbSFrançois Tigeot 		return 0;
568926deccbSFrançois Tigeot 	case RADEON_PCIE_LC_LINK_WIDTH_X1:
569926deccbSFrançois Tigeot 		return 1;
570926deccbSFrançois Tigeot 	case RADEON_PCIE_LC_LINK_WIDTH_X2:
571926deccbSFrançois Tigeot 		return 2;
572926deccbSFrançois Tigeot 	case RADEON_PCIE_LC_LINK_WIDTH_X4:
573926deccbSFrançois Tigeot 		return 4;
574926deccbSFrançois Tigeot 	case RADEON_PCIE_LC_LINK_WIDTH_X8:
575926deccbSFrançois Tigeot 		return 8;
576926deccbSFrançois Tigeot 	case RADEON_PCIE_LC_LINK_WIDTH_X16:
577926deccbSFrançois Tigeot 	default:
578926deccbSFrançois Tigeot 		return 16;
579926deccbSFrançois Tigeot 	}
580926deccbSFrançois Tigeot }
581926deccbSFrançois Tigeot 
582926deccbSFrançois Tigeot #if defined(CONFIG_DEBUG_FS)
rv370_debugfs_pcie_gart_info(struct seq_file * m,void * data)583926deccbSFrançois Tigeot static int rv370_debugfs_pcie_gart_info(struct seq_file *m, void *data)
584926deccbSFrançois Tigeot {
585926deccbSFrançois Tigeot 	struct drm_info_node *node = (struct drm_info_node *) m->private;
586926deccbSFrançois Tigeot 	struct drm_device *dev = node->minor->dev;
587926deccbSFrançois Tigeot 	struct radeon_device *rdev = dev->dev_private;
588926deccbSFrançois Tigeot 	uint32_t tmp;
589926deccbSFrançois Tigeot 
590926deccbSFrançois Tigeot 	tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_CNTL);
591926deccbSFrançois Tigeot 	seq_printf(m, "PCIE_TX_GART_CNTL 0x%08x\n", tmp);
592926deccbSFrançois Tigeot 	tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_BASE);
593926deccbSFrançois Tigeot 	seq_printf(m, "PCIE_TX_GART_BASE 0x%08x\n", tmp);
594926deccbSFrançois Tigeot 	tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_START_LO);
595926deccbSFrançois Tigeot 	seq_printf(m, "PCIE_TX_GART_START_LO 0x%08x\n", tmp);
596926deccbSFrançois Tigeot 	tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_START_HI);
597926deccbSFrançois Tigeot 	seq_printf(m, "PCIE_TX_GART_START_HI 0x%08x\n", tmp);
598926deccbSFrançois Tigeot 	tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_END_LO);
599926deccbSFrançois Tigeot 	seq_printf(m, "PCIE_TX_GART_END_LO 0x%08x\n", tmp);
600926deccbSFrançois Tigeot 	tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_END_HI);
601926deccbSFrançois Tigeot 	seq_printf(m, "PCIE_TX_GART_END_HI 0x%08x\n", tmp);
602926deccbSFrançois Tigeot 	tmp = RREG32_PCIE(RADEON_PCIE_TX_GART_ERROR);
603926deccbSFrançois Tigeot 	seq_printf(m, "PCIE_TX_GART_ERROR 0x%08x\n", tmp);
604926deccbSFrançois Tigeot 	return 0;
605926deccbSFrançois Tigeot }
606926deccbSFrançois Tigeot 
607926deccbSFrançois Tigeot static struct drm_info_list rv370_pcie_gart_info_list[] = {
608926deccbSFrançois Tigeot 	{"rv370_pcie_gart_info", rv370_debugfs_pcie_gart_info, 0, NULL},
609926deccbSFrançois Tigeot };
610926deccbSFrançois Tigeot #endif
611926deccbSFrançois Tigeot 
rv370_debugfs_pcie_gart_info_init(struct radeon_device * rdev)612926deccbSFrançois Tigeot static int rv370_debugfs_pcie_gart_info_init(struct radeon_device *rdev)
613926deccbSFrançois Tigeot {
614926deccbSFrançois Tigeot #if defined(CONFIG_DEBUG_FS)
615926deccbSFrançois Tigeot 	return radeon_debugfs_add_files(rdev, rv370_pcie_gart_info_list, 1);
616926deccbSFrançois Tigeot #else
617926deccbSFrançois Tigeot 	return 0;
618926deccbSFrançois Tigeot #endif
619926deccbSFrançois Tigeot }
620926deccbSFrançois Tigeot 
r300_packet0_check(struct radeon_cs_parser * p,struct radeon_cs_packet * pkt,unsigned idx,unsigned reg)621926deccbSFrançois Tigeot static int r300_packet0_check(struct radeon_cs_parser *p,
622926deccbSFrançois Tigeot 		struct radeon_cs_packet *pkt,
623926deccbSFrançois Tigeot 		unsigned idx, unsigned reg)
624926deccbSFrançois Tigeot {
6257dcf36dcSFrançois Tigeot 	struct radeon_bo_list *reloc;
626926deccbSFrançois Tigeot 	struct r100_cs_track *track;
627926deccbSFrançois Tigeot 	volatile uint32_t *ib;
628926deccbSFrançois Tigeot 	uint32_t tmp, tile_flags = 0;
629926deccbSFrançois Tigeot 	unsigned i;
630926deccbSFrançois Tigeot 	int r;
631926deccbSFrançois Tigeot 	u32 idx_value;
632926deccbSFrançois Tigeot 
633926deccbSFrançois Tigeot 	ib = p->ib.ptr;
634926deccbSFrançois Tigeot 	track = (struct r100_cs_track *)p->track;
635926deccbSFrançois Tigeot 	idx_value = radeon_get_ib_value(p, idx);
636926deccbSFrançois Tigeot 
637926deccbSFrançois Tigeot 	switch(reg) {
638926deccbSFrançois Tigeot 	case AVIVO_D1MODE_VLINE_START_END:
639926deccbSFrançois Tigeot 	case RADEON_CRTC_GUI_TRIG_VLINE:
640926deccbSFrançois Tigeot 		r = r100_cs_packet_parse_vline(p);
641926deccbSFrançois Tigeot 		if (r) {
642926deccbSFrançois Tigeot 			DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
643926deccbSFrançois Tigeot 					idx, reg);
644b403bed8SMichael Neumann 			radeon_cs_dump_packet(p, pkt);
645926deccbSFrançois Tigeot 			return r;
646926deccbSFrançois Tigeot 		}
647926deccbSFrançois Tigeot 		break;
648926deccbSFrançois Tigeot 	case RADEON_DST_PITCH_OFFSET:
649926deccbSFrançois Tigeot 	case RADEON_SRC_PITCH_OFFSET:
650926deccbSFrançois Tigeot 		r = r100_reloc_pitch_offset(p, pkt, idx, reg);
651926deccbSFrançois Tigeot 		if (r)
652926deccbSFrançois Tigeot 			return r;
653926deccbSFrançois Tigeot 		break;
654926deccbSFrançois Tigeot 	case R300_RB3D_COLOROFFSET0:
655926deccbSFrançois Tigeot 	case R300_RB3D_COLOROFFSET1:
656926deccbSFrançois Tigeot 	case R300_RB3D_COLOROFFSET2:
657926deccbSFrançois Tigeot 	case R300_RB3D_COLOROFFSET3:
658926deccbSFrançois Tigeot 		i = (reg - R300_RB3D_COLOROFFSET0) >> 2;
659b403bed8SMichael Neumann 		r = radeon_cs_packet_next_reloc(p, &reloc, 0);
660926deccbSFrançois Tigeot 		if (r) {
661926deccbSFrançois Tigeot 			DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
662926deccbSFrançois Tigeot 					idx, reg);
663b403bed8SMichael Neumann 			radeon_cs_dump_packet(p, pkt);
664926deccbSFrançois Tigeot 			return r;
665926deccbSFrançois Tigeot 		}
666926deccbSFrançois Tigeot 		track->cb[i].robj = reloc->robj;
667926deccbSFrançois Tigeot 		track->cb[i].offset = idx_value;
668926deccbSFrançois Tigeot 		track->cb_dirty = true;
669c6f73aabSFrançois Tigeot 		ib[idx] = idx_value + ((u32)reloc->gpu_offset);
670926deccbSFrançois Tigeot 		break;
671926deccbSFrançois Tigeot 	case R300_ZB_DEPTHOFFSET:
672b403bed8SMichael Neumann 		r = radeon_cs_packet_next_reloc(p, &reloc, 0);
673926deccbSFrançois Tigeot 		if (r) {
674926deccbSFrançois Tigeot 			DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
675926deccbSFrançois Tigeot 					idx, reg);
676b403bed8SMichael Neumann 			radeon_cs_dump_packet(p, pkt);
677926deccbSFrançois Tigeot 			return r;
678926deccbSFrançois Tigeot 		}
679926deccbSFrançois Tigeot 		track->zb.robj = reloc->robj;
680926deccbSFrançois Tigeot 		track->zb.offset = idx_value;
681926deccbSFrançois Tigeot 		track->zb_dirty = true;
682c6f73aabSFrançois Tigeot 		ib[idx] = idx_value + ((u32)reloc->gpu_offset);
683926deccbSFrançois Tigeot 		break;
684926deccbSFrançois Tigeot 	case R300_TX_OFFSET_0:
685926deccbSFrançois Tigeot 	case R300_TX_OFFSET_0+4:
686926deccbSFrançois Tigeot 	case R300_TX_OFFSET_0+8:
687926deccbSFrançois Tigeot 	case R300_TX_OFFSET_0+12:
688926deccbSFrançois Tigeot 	case R300_TX_OFFSET_0+16:
689926deccbSFrançois Tigeot 	case R300_TX_OFFSET_0+20:
690926deccbSFrançois Tigeot 	case R300_TX_OFFSET_0+24:
691926deccbSFrançois Tigeot 	case R300_TX_OFFSET_0+28:
692926deccbSFrançois Tigeot 	case R300_TX_OFFSET_0+32:
693926deccbSFrançois Tigeot 	case R300_TX_OFFSET_0+36:
694926deccbSFrançois Tigeot 	case R300_TX_OFFSET_0+40:
695926deccbSFrançois Tigeot 	case R300_TX_OFFSET_0+44:
696926deccbSFrançois Tigeot 	case R300_TX_OFFSET_0+48:
697926deccbSFrançois Tigeot 	case R300_TX_OFFSET_0+52:
698926deccbSFrançois Tigeot 	case R300_TX_OFFSET_0+56:
699926deccbSFrançois Tigeot 	case R300_TX_OFFSET_0+60:
700926deccbSFrançois Tigeot 		i = (reg - R300_TX_OFFSET_0) >> 2;
701b403bed8SMichael Neumann 		r = radeon_cs_packet_next_reloc(p, &reloc, 0);
702926deccbSFrançois Tigeot 		if (r) {
703926deccbSFrançois Tigeot 			DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
704926deccbSFrançois Tigeot 					idx, reg);
705b403bed8SMichael Neumann 			radeon_cs_dump_packet(p, pkt);
706926deccbSFrançois Tigeot 			return r;
707926deccbSFrançois Tigeot 		}
708926deccbSFrançois Tigeot 
709926deccbSFrançois Tigeot 		if (p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS) {
710926deccbSFrançois Tigeot 			ib[idx] = (idx_value & 31) | /* keep the 1st 5 bits */
711c6f73aabSFrançois Tigeot 				  ((idx_value & ~31) + (u32)reloc->gpu_offset);
712926deccbSFrançois Tigeot 		} else {
713c6f73aabSFrançois Tigeot 			if (reloc->tiling_flags & RADEON_TILING_MACRO)
714926deccbSFrançois Tigeot 				tile_flags |= R300_TXO_MACRO_TILE;
715c6f73aabSFrançois Tigeot 			if (reloc->tiling_flags & RADEON_TILING_MICRO)
716926deccbSFrançois Tigeot 				tile_flags |= R300_TXO_MICRO_TILE;
717c6f73aabSFrançois Tigeot 			else if (reloc->tiling_flags & RADEON_TILING_MICRO_SQUARE)
718926deccbSFrançois Tigeot 				tile_flags |= R300_TXO_MICRO_TILE_SQUARE;
719926deccbSFrançois Tigeot 
720c6f73aabSFrançois Tigeot 			tmp = idx_value + ((u32)reloc->gpu_offset);
721926deccbSFrançois Tigeot 			tmp |= tile_flags;
722926deccbSFrançois Tigeot 			ib[idx] = tmp;
723926deccbSFrançois Tigeot 		}
724926deccbSFrançois Tigeot 		track->textures[i].robj = reloc->robj;
725926deccbSFrançois Tigeot 		track->tex_dirty = true;
726926deccbSFrançois Tigeot 		break;
727926deccbSFrançois Tigeot 	/* Tracked registers */
728926deccbSFrançois Tigeot 	case 0x2084:
729926deccbSFrançois Tigeot 		/* VAP_VF_CNTL */
730926deccbSFrançois Tigeot 		track->vap_vf_cntl = idx_value;
731926deccbSFrançois Tigeot 		break;
732926deccbSFrançois Tigeot 	case 0x20B4:
733926deccbSFrançois Tigeot 		/* VAP_VTX_SIZE */
734926deccbSFrançois Tigeot 		track->vtx_size = idx_value & 0x7F;
735926deccbSFrançois Tigeot 		break;
736926deccbSFrançois Tigeot 	case 0x2134:
737926deccbSFrançois Tigeot 		/* VAP_VF_MAX_VTX_INDX */
738926deccbSFrançois Tigeot 		track->max_indx = idx_value & 0x00FFFFFFUL;
739926deccbSFrançois Tigeot 		break;
740926deccbSFrançois Tigeot 	case 0x2088:
741926deccbSFrançois Tigeot 		/* VAP_ALT_NUM_VERTICES - only valid on r500 */
742926deccbSFrançois Tigeot 		if (p->rdev->family < CHIP_RV515)
743926deccbSFrançois Tigeot 			goto fail;
744926deccbSFrançois Tigeot 		track->vap_alt_nverts = idx_value & 0xFFFFFF;
745926deccbSFrançois Tigeot 		break;
746926deccbSFrançois Tigeot 	case 0x43E4:
747926deccbSFrançois Tigeot 		/* SC_SCISSOR1 */
748926deccbSFrançois Tigeot 		track->maxy = ((idx_value >> 13) & 0x1FFF) + 1;
749926deccbSFrançois Tigeot 		if (p->rdev->family < CHIP_RV515) {
750926deccbSFrançois Tigeot 			track->maxy -= 1440;
751926deccbSFrançois Tigeot 		}
752926deccbSFrançois Tigeot 		track->cb_dirty = true;
753926deccbSFrançois Tigeot 		track->zb_dirty = true;
754926deccbSFrançois Tigeot 		break;
755926deccbSFrançois Tigeot 	case 0x4E00:
756926deccbSFrançois Tigeot 		/* RB3D_CCTL */
757926deccbSFrançois Tigeot 		if ((idx_value & (1 << 10)) && /* CMASK_ENABLE */
758926deccbSFrançois Tigeot 		    p->rdev->cmask_filp != p->filp) {
759926deccbSFrançois Tigeot 			DRM_ERROR("Invalid RB3D_CCTL: Cannot enable CMASK.\n");
760926deccbSFrançois Tigeot 			return -EINVAL;
761926deccbSFrançois Tigeot 		}
762926deccbSFrançois Tigeot 		track->num_cb = ((idx_value >> 5) & 0x3) + 1;
763926deccbSFrançois Tigeot 		track->cb_dirty = true;
764926deccbSFrançois Tigeot 		break;
765926deccbSFrançois Tigeot 	case 0x4E38:
766926deccbSFrançois Tigeot 	case 0x4E3C:
767926deccbSFrançois Tigeot 	case 0x4E40:
768926deccbSFrançois Tigeot 	case 0x4E44:
769926deccbSFrançois Tigeot 		/* RB3D_COLORPITCH0 */
770926deccbSFrançois Tigeot 		/* RB3D_COLORPITCH1 */
771926deccbSFrançois Tigeot 		/* RB3D_COLORPITCH2 */
772926deccbSFrançois Tigeot 		/* RB3D_COLORPITCH3 */
773926deccbSFrançois Tigeot 		if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
774b403bed8SMichael Neumann 			r = radeon_cs_packet_next_reloc(p, &reloc, 0);
775926deccbSFrançois Tigeot 			if (r) {
776926deccbSFrançois Tigeot 				DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
777926deccbSFrançois Tigeot 					  idx, reg);
778b403bed8SMichael Neumann 				radeon_cs_dump_packet(p, pkt);
779926deccbSFrançois Tigeot 				return r;
780926deccbSFrançois Tigeot 			}
781926deccbSFrançois Tigeot 
782c6f73aabSFrançois Tigeot 			if (reloc->tiling_flags & RADEON_TILING_MACRO)
783926deccbSFrançois Tigeot 				tile_flags |= R300_COLOR_TILE_ENABLE;
784c6f73aabSFrançois Tigeot 			if (reloc->tiling_flags & RADEON_TILING_MICRO)
785926deccbSFrançois Tigeot 				tile_flags |= R300_COLOR_MICROTILE_ENABLE;
786c6f73aabSFrançois Tigeot 			else if (reloc->tiling_flags & RADEON_TILING_MICRO_SQUARE)
787926deccbSFrançois Tigeot 				tile_flags |= R300_COLOR_MICROTILE_SQUARE_ENABLE;
788926deccbSFrançois Tigeot 
789926deccbSFrançois Tigeot 			tmp = idx_value & ~(0x7 << 16);
790926deccbSFrançois Tigeot 			tmp |= tile_flags;
791926deccbSFrançois Tigeot 			ib[idx] = tmp;
792926deccbSFrançois Tigeot 		}
793926deccbSFrançois Tigeot 		i = (reg - 0x4E38) >> 2;
794926deccbSFrançois Tigeot 		track->cb[i].pitch = idx_value & 0x3FFE;
795926deccbSFrançois Tigeot 		switch (((idx_value >> 21) & 0xF)) {
796926deccbSFrançois Tigeot 		case 9:
797926deccbSFrançois Tigeot 		case 11:
798926deccbSFrançois Tigeot 		case 12:
799926deccbSFrançois Tigeot 			track->cb[i].cpp = 1;
800926deccbSFrançois Tigeot 			break;
801926deccbSFrançois Tigeot 		case 3:
802926deccbSFrançois Tigeot 		case 4:
803926deccbSFrançois Tigeot 		case 13:
804926deccbSFrançois Tigeot 		case 15:
805926deccbSFrançois Tigeot 			track->cb[i].cpp = 2;
806926deccbSFrançois Tigeot 			break;
807926deccbSFrançois Tigeot 		case 5:
808926deccbSFrançois Tigeot 			if (p->rdev->family < CHIP_RV515) {
809926deccbSFrançois Tigeot 				DRM_ERROR("Invalid color buffer format (%d)!\n",
810926deccbSFrançois Tigeot 					  ((idx_value >> 21) & 0xF));
811926deccbSFrançois Tigeot 				return -EINVAL;
812926deccbSFrançois Tigeot 			}
813926deccbSFrançois Tigeot 			/* Pass through. */
814926deccbSFrançois Tigeot 		case 6:
815926deccbSFrançois Tigeot 			track->cb[i].cpp = 4;
816926deccbSFrançois Tigeot 			break;
817926deccbSFrançois Tigeot 		case 10:
818926deccbSFrançois Tigeot 			track->cb[i].cpp = 8;
819926deccbSFrançois Tigeot 			break;
820926deccbSFrançois Tigeot 		case 7:
821926deccbSFrançois Tigeot 			track->cb[i].cpp = 16;
822926deccbSFrançois Tigeot 			break;
823926deccbSFrançois Tigeot 		default:
824926deccbSFrançois Tigeot 			DRM_ERROR("Invalid color buffer format (%d) !\n",
825926deccbSFrançois Tigeot 				  ((idx_value >> 21) & 0xF));
826926deccbSFrançois Tigeot 			return -EINVAL;
827926deccbSFrançois Tigeot 		}
828926deccbSFrançois Tigeot 		track->cb_dirty = true;
829926deccbSFrançois Tigeot 		break;
830926deccbSFrançois Tigeot 	case 0x4F00:
831926deccbSFrançois Tigeot 		/* ZB_CNTL */
832926deccbSFrançois Tigeot 		if (idx_value & 2) {
833926deccbSFrançois Tigeot 			track->z_enabled = true;
834926deccbSFrançois Tigeot 		} else {
835926deccbSFrançois Tigeot 			track->z_enabled = false;
836926deccbSFrançois Tigeot 		}
837926deccbSFrançois Tigeot 		track->zb_dirty = true;
838926deccbSFrançois Tigeot 		break;
839926deccbSFrançois Tigeot 	case 0x4F10:
840926deccbSFrançois Tigeot 		/* ZB_FORMAT */
841926deccbSFrançois Tigeot 		switch ((idx_value & 0xF)) {
842926deccbSFrançois Tigeot 		case 0:
843926deccbSFrançois Tigeot 		case 1:
844926deccbSFrançois Tigeot 			track->zb.cpp = 2;
845926deccbSFrançois Tigeot 			break;
846926deccbSFrançois Tigeot 		case 2:
847926deccbSFrançois Tigeot 			track->zb.cpp = 4;
848926deccbSFrançois Tigeot 			break;
849926deccbSFrançois Tigeot 		default:
850926deccbSFrançois Tigeot 			DRM_ERROR("Invalid z buffer format (%d) !\n",
851926deccbSFrançois Tigeot 				  (idx_value & 0xF));
852926deccbSFrançois Tigeot 			return -EINVAL;
853926deccbSFrançois Tigeot 		}
854926deccbSFrançois Tigeot 		track->zb_dirty = true;
855926deccbSFrançois Tigeot 		break;
856926deccbSFrançois Tigeot 	case 0x4F24:
857926deccbSFrançois Tigeot 		/* ZB_DEPTHPITCH */
858926deccbSFrançois Tigeot 		if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
859b403bed8SMichael Neumann 			r = radeon_cs_packet_next_reloc(p, &reloc, 0);
860926deccbSFrançois Tigeot 			if (r) {
861926deccbSFrançois Tigeot 				DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
862926deccbSFrançois Tigeot 					  idx, reg);
863b403bed8SMichael Neumann 				radeon_cs_dump_packet(p, pkt);
864926deccbSFrançois Tigeot 				return r;
865926deccbSFrançois Tigeot 			}
866926deccbSFrançois Tigeot 
867c6f73aabSFrançois Tigeot 			if (reloc->tiling_flags & RADEON_TILING_MACRO)
868926deccbSFrançois Tigeot 				tile_flags |= R300_DEPTHMACROTILE_ENABLE;
869c6f73aabSFrançois Tigeot 			if (reloc->tiling_flags & RADEON_TILING_MICRO)
870926deccbSFrançois Tigeot 				tile_flags |= R300_DEPTHMICROTILE_TILED;
871c6f73aabSFrançois Tigeot 			else if (reloc->tiling_flags & RADEON_TILING_MICRO_SQUARE)
872926deccbSFrançois Tigeot 				tile_flags |= R300_DEPTHMICROTILE_TILED_SQUARE;
873926deccbSFrançois Tigeot 
874926deccbSFrançois Tigeot 			tmp = idx_value & ~(0x7 << 16);
875926deccbSFrançois Tigeot 			tmp |= tile_flags;
876926deccbSFrançois Tigeot 			ib[idx] = tmp;
877926deccbSFrançois Tigeot 		}
878926deccbSFrançois Tigeot 		track->zb.pitch = idx_value & 0x3FFC;
879926deccbSFrançois Tigeot 		track->zb_dirty = true;
880926deccbSFrançois Tigeot 		break;
881926deccbSFrançois Tigeot 	case 0x4104:
882926deccbSFrançois Tigeot 		/* TX_ENABLE */
883926deccbSFrançois Tigeot 		for (i = 0; i < 16; i++) {
884926deccbSFrançois Tigeot 			bool enabled;
885926deccbSFrançois Tigeot 
886926deccbSFrançois Tigeot 			enabled = !!(idx_value & (1 << i));
887926deccbSFrançois Tigeot 			track->textures[i].enabled = enabled;
888926deccbSFrançois Tigeot 		}
889926deccbSFrançois Tigeot 		track->tex_dirty = true;
890926deccbSFrançois Tigeot 		break;
891926deccbSFrançois Tigeot 	case 0x44C0:
892926deccbSFrançois Tigeot 	case 0x44C4:
893926deccbSFrançois Tigeot 	case 0x44C8:
894926deccbSFrançois Tigeot 	case 0x44CC:
895926deccbSFrançois Tigeot 	case 0x44D0:
896926deccbSFrançois Tigeot 	case 0x44D4:
897926deccbSFrançois Tigeot 	case 0x44D8:
898926deccbSFrançois Tigeot 	case 0x44DC:
899926deccbSFrançois Tigeot 	case 0x44E0:
900926deccbSFrançois Tigeot 	case 0x44E4:
901926deccbSFrançois Tigeot 	case 0x44E8:
902926deccbSFrançois Tigeot 	case 0x44EC:
903926deccbSFrançois Tigeot 	case 0x44F0:
904926deccbSFrançois Tigeot 	case 0x44F4:
905926deccbSFrançois Tigeot 	case 0x44F8:
906926deccbSFrançois Tigeot 	case 0x44FC:
907926deccbSFrançois Tigeot 		/* TX_FORMAT1_[0-15] */
908926deccbSFrançois Tigeot 		i = (reg - 0x44C0) >> 2;
909926deccbSFrançois Tigeot 		tmp = (idx_value >> 25) & 0x3;
910926deccbSFrançois Tigeot 		track->textures[i].tex_coord_type = tmp;
911926deccbSFrançois Tigeot 		switch ((idx_value & 0x1F)) {
912926deccbSFrançois Tigeot 		case R300_TX_FORMAT_X8:
913926deccbSFrançois Tigeot 		case R300_TX_FORMAT_Y4X4:
914926deccbSFrançois Tigeot 		case R300_TX_FORMAT_Z3Y3X2:
915926deccbSFrançois Tigeot 			track->textures[i].cpp = 1;
916926deccbSFrançois Tigeot 			track->textures[i].compress_format = R100_TRACK_COMP_NONE;
917926deccbSFrançois Tigeot 			break;
918926deccbSFrançois Tigeot 		case R300_TX_FORMAT_X16:
919926deccbSFrançois Tigeot 		case R300_TX_FORMAT_FL_I16:
920926deccbSFrançois Tigeot 		case R300_TX_FORMAT_Y8X8:
921926deccbSFrançois Tigeot 		case R300_TX_FORMAT_Z5Y6X5:
922926deccbSFrançois Tigeot 		case R300_TX_FORMAT_Z6Y5X5:
923926deccbSFrançois Tigeot 		case R300_TX_FORMAT_W4Z4Y4X4:
924926deccbSFrançois Tigeot 		case R300_TX_FORMAT_W1Z5Y5X5:
925926deccbSFrançois Tigeot 		case R300_TX_FORMAT_D3DMFT_CxV8U8:
926926deccbSFrançois Tigeot 		case R300_TX_FORMAT_B8G8_B8G8:
927926deccbSFrançois Tigeot 		case R300_TX_FORMAT_G8R8_G8B8:
928926deccbSFrançois Tigeot 			track->textures[i].cpp = 2;
929926deccbSFrançois Tigeot 			track->textures[i].compress_format = R100_TRACK_COMP_NONE;
930926deccbSFrançois Tigeot 			break;
931926deccbSFrançois Tigeot 		case R300_TX_FORMAT_Y16X16:
932926deccbSFrançois Tigeot 		case R300_TX_FORMAT_FL_I16A16:
933926deccbSFrançois Tigeot 		case R300_TX_FORMAT_Z11Y11X10:
934926deccbSFrançois Tigeot 		case R300_TX_FORMAT_Z10Y11X11:
935926deccbSFrançois Tigeot 		case R300_TX_FORMAT_W8Z8Y8X8:
936926deccbSFrançois Tigeot 		case R300_TX_FORMAT_W2Z10Y10X10:
937926deccbSFrançois Tigeot 		case 0x17:
938926deccbSFrançois Tigeot 		case R300_TX_FORMAT_FL_I32:
939926deccbSFrançois Tigeot 		case 0x1e:
940926deccbSFrançois Tigeot 			track->textures[i].cpp = 4;
941926deccbSFrançois Tigeot 			track->textures[i].compress_format = R100_TRACK_COMP_NONE;
942926deccbSFrançois Tigeot 			break;
943926deccbSFrançois Tigeot 		case R300_TX_FORMAT_W16Z16Y16X16:
944926deccbSFrançois Tigeot 		case R300_TX_FORMAT_FL_R16G16B16A16:
945926deccbSFrançois Tigeot 		case R300_TX_FORMAT_FL_I32A32:
946926deccbSFrançois Tigeot 			track->textures[i].cpp = 8;
947926deccbSFrançois Tigeot 			track->textures[i].compress_format = R100_TRACK_COMP_NONE;
948926deccbSFrançois Tigeot 			break;
949926deccbSFrançois Tigeot 		case R300_TX_FORMAT_FL_R32G32B32A32:
950926deccbSFrançois Tigeot 			track->textures[i].cpp = 16;
951926deccbSFrançois Tigeot 			track->textures[i].compress_format = R100_TRACK_COMP_NONE;
952926deccbSFrançois Tigeot 			break;
953926deccbSFrançois Tigeot 		case R300_TX_FORMAT_DXT1:
954926deccbSFrançois Tigeot 			track->textures[i].cpp = 1;
955926deccbSFrançois Tigeot 			track->textures[i].compress_format = R100_TRACK_COMP_DXT1;
956926deccbSFrançois Tigeot 			break;
957926deccbSFrançois Tigeot 		case R300_TX_FORMAT_ATI2N:
958926deccbSFrançois Tigeot 			if (p->rdev->family < CHIP_R420) {
959926deccbSFrançois Tigeot 				DRM_ERROR("Invalid texture format %u\n",
960926deccbSFrançois Tigeot 					  (idx_value & 0x1F));
961926deccbSFrançois Tigeot 				return -EINVAL;
962926deccbSFrançois Tigeot 			}
963926deccbSFrançois Tigeot 			/* The same rules apply as for DXT3/5. */
964926deccbSFrançois Tigeot 			/* Pass through. */
965926deccbSFrançois Tigeot 		case R300_TX_FORMAT_DXT3:
966926deccbSFrançois Tigeot 		case R300_TX_FORMAT_DXT5:
967926deccbSFrançois Tigeot 			track->textures[i].cpp = 1;
968926deccbSFrançois Tigeot 			track->textures[i].compress_format = R100_TRACK_COMP_DXT35;
969926deccbSFrançois Tigeot 			break;
970926deccbSFrançois Tigeot 		default:
971926deccbSFrançois Tigeot 			DRM_ERROR("Invalid texture format %u\n",
972926deccbSFrançois Tigeot 				  (idx_value & 0x1F));
973926deccbSFrançois Tigeot 			return -EINVAL;
974926deccbSFrançois Tigeot 		}
975926deccbSFrançois Tigeot 		track->tex_dirty = true;
976926deccbSFrançois Tigeot 		break;
977926deccbSFrançois Tigeot 	case 0x4400:
978926deccbSFrançois Tigeot 	case 0x4404:
979926deccbSFrançois Tigeot 	case 0x4408:
980926deccbSFrançois Tigeot 	case 0x440C:
981926deccbSFrançois Tigeot 	case 0x4410:
982926deccbSFrançois Tigeot 	case 0x4414:
983926deccbSFrançois Tigeot 	case 0x4418:
984926deccbSFrançois Tigeot 	case 0x441C:
985926deccbSFrançois Tigeot 	case 0x4420:
986926deccbSFrançois Tigeot 	case 0x4424:
987926deccbSFrançois Tigeot 	case 0x4428:
988926deccbSFrançois Tigeot 	case 0x442C:
989926deccbSFrançois Tigeot 	case 0x4430:
990926deccbSFrançois Tigeot 	case 0x4434:
991926deccbSFrançois Tigeot 	case 0x4438:
992926deccbSFrançois Tigeot 	case 0x443C:
993926deccbSFrançois Tigeot 		/* TX_FILTER0_[0-15] */
994926deccbSFrançois Tigeot 		i = (reg - 0x4400) >> 2;
995926deccbSFrançois Tigeot 		tmp = idx_value & 0x7;
996926deccbSFrançois Tigeot 		if (tmp == 2 || tmp == 4 || tmp == 6) {
997926deccbSFrançois Tigeot 			track->textures[i].roundup_w = false;
998926deccbSFrançois Tigeot 		}
999926deccbSFrançois Tigeot 		tmp = (idx_value >> 3) & 0x7;
1000926deccbSFrançois Tigeot 		if (tmp == 2 || tmp == 4 || tmp == 6) {
1001926deccbSFrançois Tigeot 			track->textures[i].roundup_h = false;
1002926deccbSFrançois Tigeot 		}
1003926deccbSFrançois Tigeot 		track->tex_dirty = true;
1004926deccbSFrançois Tigeot 		break;
1005926deccbSFrançois Tigeot 	case 0x4500:
1006926deccbSFrançois Tigeot 	case 0x4504:
1007926deccbSFrançois Tigeot 	case 0x4508:
1008926deccbSFrançois Tigeot 	case 0x450C:
1009926deccbSFrançois Tigeot 	case 0x4510:
1010926deccbSFrançois Tigeot 	case 0x4514:
1011926deccbSFrançois Tigeot 	case 0x4518:
1012926deccbSFrançois Tigeot 	case 0x451C:
1013926deccbSFrançois Tigeot 	case 0x4520:
1014926deccbSFrançois Tigeot 	case 0x4524:
1015926deccbSFrançois Tigeot 	case 0x4528:
1016926deccbSFrançois Tigeot 	case 0x452C:
1017926deccbSFrançois Tigeot 	case 0x4530:
1018926deccbSFrançois Tigeot 	case 0x4534:
1019926deccbSFrançois Tigeot 	case 0x4538:
1020926deccbSFrançois Tigeot 	case 0x453C:
1021926deccbSFrançois Tigeot 		/* TX_FORMAT2_[0-15] */
1022926deccbSFrançois Tigeot 		i = (reg - 0x4500) >> 2;
1023926deccbSFrançois Tigeot 		tmp = idx_value & 0x3FFF;
1024926deccbSFrançois Tigeot 		track->textures[i].pitch = tmp + 1;
1025926deccbSFrançois Tigeot 		if (p->rdev->family >= CHIP_RV515) {
1026926deccbSFrançois Tigeot 			tmp = ((idx_value >> 15) & 1) << 11;
1027926deccbSFrançois Tigeot 			track->textures[i].width_11 = tmp;
1028926deccbSFrançois Tigeot 			tmp = ((idx_value >> 16) & 1) << 11;
1029926deccbSFrançois Tigeot 			track->textures[i].height_11 = tmp;
1030926deccbSFrançois Tigeot 
1031926deccbSFrançois Tigeot 			/* ATI1N */
1032926deccbSFrançois Tigeot 			if (idx_value & (1 << 14)) {
1033926deccbSFrançois Tigeot 				/* The same rules apply as for DXT1. */
1034926deccbSFrançois Tigeot 				track->textures[i].compress_format =
1035926deccbSFrançois Tigeot 					R100_TRACK_COMP_DXT1;
1036926deccbSFrançois Tigeot 			}
1037926deccbSFrançois Tigeot 		} else if (idx_value & (1 << 14)) {
1038926deccbSFrançois Tigeot 			DRM_ERROR("Forbidden bit TXFORMAT_MSB\n");
1039926deccbSFrançois Tigeot 			return -EINVAL;
1040926deccbSFrançois Tigeot 		}
1041926deccbSFrançois Tigeot 		track->tex_dirty = true;
1042926deccbSFrançois Tigeot 		break;
1043926deccbSFrançois Tigeot 	case 0x4480:
1044926deccbSFrançois Tigeot 	case 0x4484:
1045926deccbSFrançois Tigeot 	case 0x4488:
1046926deccbSFrançois Tigeot 	case 0x448C:
1047926deccbSFrançois Tigeot 	case 0x4490:
1048926deccbSFrançois Tigeot 	case 0x4494:
1049926deccbSFrançois Tigeot 	case 0x4498:
1050926deccbSFrançois Tigeot 	case 0x449C:
1051926deccbSFrançois Tigeot 	case 0x44A0:
1052926deccbSFrançois Tigeot 	case 0x44A4:
1053926deccbSFrançois Tigeot 	case 0x44A8:
1054926deccbSFrançois Tigeot 	case 0x44AC:
1055926deccbSFrançois Tigeot 	case 0x44B0:
1056926deccbSFrançois Tigeot 	case 0x44B4:
1057926deccbSFrançois Tigeot 	case 0x44B8:
1058926deccbSFrançois Tigeot 	case 0x44BC:
1059926deccbSFrançois Tigeot 		/* TX_FORMAT0_[0-15] */
1060926deccbSFrançois Tigeot 		i = (reg - 0x4480) >> 2;
1061926deccbSFrançois Tigeot 		tmp = idx_value & 0x7FF;
1062926deccbSFrançois Tigeot 		track->textures[i].width = tmp + 1;
1063926deccbSFrançois Tigeot 		tmp = (idx_value >> 11) & 0x7FF;
1064926deccbSFrançois Tigeot 		track->textures[i].height = tmp + 1;
1065926deccbSFrançois Tigeot 		tmp = (idx_value >> 26) & 0xF;
1066926deccbSFrançois Tigeot 		track->textures[i].num_levels = tmp;
1067926deccbSFrançois Tigeot 		tmp = idx_value & (1 << 31);
1068926deccbSFrançois Tigeot 		track->textures[i].use_pitch = !!tmp;
1069926deccbSFrançois Tigeot 		tmp = (idx_value >> 22) & 0xF;
1070926deccbSFrançois Tigeot 		track->textures[i].txdepth = tmp;
1071926deccbSFrançois Tigeot 		track->tex_dirty = true;
1072926deccbSFrançois Tigeot 		break;
1073926deccbSFrançois Tigeot 	case R300_ZB_ZPASS_ADDR:
1074b403bed8SMichael Neumann 		r = radeon_cs_packet_next_reloc(p, &reloc, 0);
1075926deccbSFrançois Tigeot 		if (r) {
1076926deccbSFrançois Tigeot 			DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
1077926deccbSFrançois Tigeot 					idx, reg);
1078b403bed8SMichael Neumann 			radeon_cs_dump_packet(p, pkt);
1079926deccbSFrançois Tigeot 			return r;
1080926deccbSFrançois Tigeot 		}
1081c6f73aabSFrançois Tigeot 		ib[idx] = idx_value + ((u32)reloc->gpu_offset);
1082926deccbSFrançois Tigeot 		break;
1083926deccbSFrançois Tigeot 	case 0x4e0c:
1084926deccbSFrançois Tigeot 		/* RB3D_COLOR_CHANNEL_MASK */
1085926deccbSFrançois Tigeot 		track->color_channel_mask = idx_value;
1086926deccbSFrançois Tigeot 		track->cb_dirty = true;
1087926deccbSFrançois Tigeot 		break;
1088926deccbSFrançois Tigeot 	case 0x43a4:
1089926deccbSFrançois Tigeot 		/* SC_HYPERZ_EN */
1090926deccbSFrançois Tigeot 		/* r300c emits this register - we need to disable hyperz for it
1091926deccbSFrançois Tigeot 		 * without complaining */
1092926deccbSFrançois Tigeot 		if (p->rdev->hyperz_filp != p->filp) {
1093926deccbSFrançois Tigeot 			if (idx_value & 0x1)
1094926deccbSFrançois Tigeot 				ib[idx] = idx_value & ~1;
1095926deccbSFrançois Tigeot 		}
1096926deccbSFrançois Tigeot 		break;
1097926deccbSFrançois Tigeot 	case 0x4f1c:
1098926deccbSFrançois Tigeot 		/* ZB_BW_CNTL */
1099926deccbSFrançois Tigeot 		track->zb_cb_clear = !!(idx_value & (1 << 5));
1100926deccbSFrançois Tigeot 		track->cb_dirty = true;
1101926deccbSFrançois Tigeot 		track->zb_dirty = true;
1102926deccbSFrançois Tigeot 		if (p->rdev->hyperz_filp != p->filp) {
1103926deccbSFrançois Tigeot 			if (idx_value & (R300_HIZ_ENABLE |
1104926deccbSFrançois Tigeot 					 R300_RD_COMP_ENABLE |
1105926deccbSFrançois Tigeot 					 R300_WR_COMP_ENABLE |
1106926deccbSFrançois Tigeot 					 R300_FAST_FILL_ENABLE))
1107926deccbSFrançois Tigeot 				goto fail;
1108926deccbSFrançois Tigeot 		}
1109926deccbSFrançois Tigeot 		break;
1110926deccbSFrançois Tigeot 	case 0x4e04:
1111926deccbSFrançois Tigeot 		/* RB3D_BLENDCNTL */
1112926deccbSFrançois Tigeot 		track->blend_read_enable = !!(idx_value & (1 << 2));
1113926deccbSFrançois Tigeot 		track->cb_dirty = true;
1114926deccbSFrançois Tigeot 		break;
1115926deccbSFrançois Tigeot 	case R300_RB3D_AARESOLVE_OFFSET:
1116b403bed8SMichael Neumann 		r = radeon_cs_packet_next_reloc(p, &reloc, 0);
1117926deccbSFrançois Tigeot 		if (r) {
1118926deccbSFrançois Tigeot 			DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
1119926deccbSFrançois Tigeot 				  idx, reg);
1120b403bed8SMichael Neumann 			radeon_cs_dump_packet(p, pkt);
1121926deccbSFrançois Tigeot 			return r;
1122926deccbSFrançois Tigeot 		}
1123926deccbSFrançois Tigeot 		track->aa.robj = reloc->robj;
1124926deccbSFrançois Tigeot 		track->aa.offset = idx_value;
1125926deccbSFrançois Tigeot 		track->aa_dirty = true;
1126c6f73aabSFrançois Tigeot 		ib[idx] = idx_value + ((u32)reloc->gpu_offset);
1127926deccbSFrançois Tigeot 		break;
1128926deccbSFrançois Tigeot 	case R300_RB3D_AARESOLVE_PITCH:
1129926deccbSFrançois Tigeot 		track->aa.pitch = idx_value & 0x3FFE;
1130926deccbSFrançois Tigeot 		track->aa_dirty = true;
1131926deccbSFrançois Tigeot 		break;
1132926deccbSFrançois Tigeot 	case R300_RB3D_AARESOLVE_CTL:
1133926deccbSFrançois Tigeot 		track->aaresolve = idx_value & 0x1;
1134926deccbSFrançois Tigeot 		track->aa_dirty = true;
1135926deccbSFrançois Tigeot 		break;
1136926deccbSFrançois Tigeot 	case 0x4f30: /* ZB_MASK_OFFSET */
1137926deccbSFrançois Tigeot 	case 0x4f34: /* ZB_ZMASK_PITCH */
1138926deccbSFrançois Tigeot 	case 0x4f44: /* ZB_HIZ_OFFSET */
1139926deccbSFrançois Tigeot 	case 0x4f54: /* ZB_HIZ_PITCH */
1140926deccbSFrançois Tigeot 		if (idx_value && (p->rdev->hyperz_filp != p->filp))
1141926deccbSFrançois Tigeot 			goto fail;
1142926deccbSFrançois Tigeot 		break;
1143926deccbSFrançois Tigeot 	case 0x4028:
1144926deccbSFrançois Tigeot 		if (idx_value && (p->rdev->hyperz_filp != p->filp))
1145926deccbSFrançois Tigeot 			goto fail;
1146926deccbSFrançois Tigeot 		/* GB_Z_PEQ_CONFIG */
1147926deccbSFrançois Tigeot 		if (p->rdev->family >= CHIP_RV350)
1148926deccbSFrançois Tigeot 			break;
1149926deccbSFrançois Tigeot 		goto fail;
1150926deccbSFrançois Tigeot 		break;
1151926deccbSFrançois Tigeot 	case 0x4be8:
1152926deccbSFrançois Tigeot 		/* valid register only on RV530 */
1153926deccbSFrançois Tigeot 		if (p->rdev->family == CHIP_RV530)
1154926deccbSFrançois Tigeot 			break;
1155926deccbSFrançois Tigeot 		/* fallthrough do not move */
1156926deccbSFrançois Tigeot 	default:
1157926deccbSFrançois Tigeot 		goto fail;
1158926deccbSFrançois Tigeot 	}
1159926deccbSFrançois Tigeot 	return 0;
1160926deccbSFrançois Tigeot fail:
1161*a85cb24fSFrançois Tigeot 	pr_err("Forbidden register 0x%04X in cs at %d (val=%08x)\n",
1162926deccbSFrançois Tigeot 	       reg, idx, idx_value);
1163926deccbSFrançois Tigeot 	return -EINVAL;
1164926deccbSFrançois Tigeot }
1165926deccbSFrançois Tigeot 
r300_packet3_check(struct radeon_cs_parser * p,struct radeon_cs_packet * pkt)1166926deccbSFrançois Tigeot static int r300_packet3_check(struct radeon_cs_parser *p,
1167926deccbSFrançois Tigeot 			      struct radeon_cs_packet *pkt)
1168926deccbSFrançois Tigeot {
11697dcf36dcSFrançois Tigeot 	struct radeon_bo_list *reloc;
1170926deccbSFrançois Tigeot 	struct r100_cs_track *track;
1171926deccbSFrançois Tigeot 	volatile uint32_t *ib;
1172926deccbSFrançois Tigeot 	unsigned idx;
1173926deccbSFrançois Tigeot 	int r;
1174926deccbSFrançois Tigeot 
1175926deccbSFrançois Tigeot 	ib = p->ib.ptr;
1176926deccbSFrançois Tigeot 	idx = pkt->idx + 1;
1177926deccbSFrançois Tigeot 	track = (struct r100_cs_track *)p->track;
1178926deccbSFrançois Tigeot 	switch(pkt->opcode) {
1179926deccbSFrançois Tigeot 	case PACKET3_3D_LOAD_VBPNTR:
1180926deccbSFrançois Tigeot 		r = r100_packet3_load_vbpntr(p, pkt, idx);
1181926deccbSFrançois Tigeot 		if (r)
1182926deccbSFrançois Tigeot 			return r;
1183926deccbSFrançois Tigeot 		break;
1184926deccbSFrançois Tigeot 	case PACKET3_INDX_BUFFER:
1185b403bed8SMichael Neumann 		r = radeon_cs_packet_next_reloc(p, &reloc, 0);
1186926deccbSFrançois Tigeot 		if (r) {
1187926deccbSFrançois Tigeot 			DRM_ERROR("No reloc for packet3 %d\n", pkt->opcode);
1188b403bed8SMichael Neumann 			radeon_cs_dump_packet(p, pkt);
1189926deccbSFrançois Tigeot 			return r;
1190926deccbSFrançois Tigeot 		}
1191c6f73aabSFrançois Tigeot 		ib[idx+1] = radeon_get_ib_value(p, idx + 1) + ((u32)reloc->gpu_offset);
1192926deccbSFrançois Tigeot 		r = r100_cs_track_check_pkt3_indx_buffer(p, pkt, reloc->robj);
1193926deccbSFrançois Tigeot 		if (r) {
1194926deccbSFrançois Tigeot 			return r;
1195926deccbSFrançois Tigeot 		}
1196926deccbSFrançois Tigeot 		break;
1197926deccbSFrançois Tigeot 	/* Draw packet */
1198926deccbSFrançois Tigeot 	case PACKET3_3D_DRAW_IMMD:
1199926deccbSFrançois Tigeot 		/* Number of dwords is vtx_size * (num_vertices - 1)
1200926deccbSFrançois Tigeot 		 * PRIM_WALK must be equal to 3 vertex data in embedded
1201926deccbSFrançois Tigeot 		 * in cmd stream */
1202926deccbSFrançois Tigeot 		if (((radeon_get_ib_value(p, idx + 1) >> 4) & 0x3) != 3) {
1203926deccbSFrançois Tigeot 			DRM_ERROR("PRIM_WALK must be 3 for IMMD draw\n");
1204926deccbSFrançois Tigeot 			return -EINVAL;
1205926deccbSFrançois Tigeot 		}
1206926deccbSFrançois Tigeot 		track->vap_vf_cntl = radeon_get_ib_value(p, idx + 1);
1207926deccbSFrançois Tigeot 		track->immd_dwords = pkt->count - 1;
1208926deccbSFrançois Tigeot 		r = r100_cs_track_check(p->rdev, track);
1209926deccbSFrançois Tigeot 		if (r) {
1210926deccbSFrançois Tigeot 			return r;
1211926deccbSFrançois Tigeot 		}
1212926deccbSFrançois Tigeot 		break;
1213926deccbSFrançois Tigeot 	case PACKET3_3D_DRAW_IMMD_2:
1214926deccbSFrançois Tigeot 		/* Number of dwords is vtx_size * (num_vertices - 1)
1215926deccbSFrançois Tigeot 		 * PRIM_WALK must be equal to 3 vertex data in embedded
1216926deccbSFrançois Tigeot 		 * in cmd stream */
1217926deccbSFrançois Tigeot 		if (((radeon_get_ib_value(p, idx) >> 4) & 0x3) != 3) {
1218926deccbSFrançois Tigeot 			DRM_ERROR("PRIM_WALK must be 3 for IMMD draw\n");
1219926deccbSFrançois Tigeot 			return -EINVAL;
1220926deccbSFrançois Tigeot 		}
1221926deccbSFrançois Tigeot 		track->vap_vf_cntl = radeon_get_ib_value(p, idx);
1222926deccbSFrançois Tigeot 		track->immd_dwords = pkt->count;
1223926deccbSFrançois Tigeot 		r = r100_cs_track_check(p->rdev, track);
1224926deccbSFrançois Tigeot 		if (r) {
1225926deccbSFrançois Tigeot 			return r;
1226926deccbSFrançois Tigeot 		}
1227926deccbSFrançois Tigeot 		break;
1228926deccbSFrançois Tigeot 	case PACKET3_3D_DRAW_VBUF:
1229926deccbSFrançois Tigeot 		track->vap_vf_cntl = radeon_get_ib_value(p, idx + 1);
1230926deccbSFrançois Tigeot 		r = r100_cs_track_check(p->rdev, track);
1231926deccbSFrançois Tigeot 		if (r) {
1232926deccbSFrançois Tigeot 			return r;
1233926deccbSFrançois Tigeot 		}
1234926deccbSFrançois Tigeot 		break;
1235926deccbSFrançois Tigeot 	case PACKET3_3D_DRAW_VBUF_2:
1236926deccbSFrançois Tigeot 		track->vap_vf_cntl = radeon_get_ib_value(p, idx);
1237926deccbSFrançois Tigeot 		r = r100_cs_track_check(p->rdev, track);
1238926deccbSFrançois Tigeot 		if (r) {
1239926deccbSFrançois Tigeot 			return r;
1240926deccbSFrançois Tigeot 		}
1241926deccbSFrançois Tigeot 		break;
1242926deccbSFrançois Tigeot 	case PACKET3_3D_DRAW_INDX:
1243926deccbSFrançois Tigeot 		track->vap_vf_cntl = radeon_get_ib_value(p, idx + 1);
1244926deccbSFrançois Tigeot 		r = r100_cs_track_check(p->rdev, track);
1245926deccbSFrançois Tigeot 		if (r) {
1246926deccbSFrançois Tigeot 			return r;
1247926deccbSFrançois Tigeot 		}
1248926deccbSFrançois Tigeot 		break;
1249926deccbSFrançois Tigeot 	case PACKET3_3D_DRAW_INDX_2:
1250926deccbSFrançois Tigeot 		track->vap_vf_cntl = radeon_get_ib_value(p, idx);
1251926deccbSFrançois Tigeot 		r = r100_cs_track_check(p->rdev, track);
1252926deccbSFrançois Tigeot 		if (r) {
1253926deccbSFrançois Tigeot 			return r;
1254926deccbSFrançois Tigeot 		}
1255926deccbSFrançois Tigeot 		break;
1256926deccbSFrançois Tigeot 	case PACKET3_3D_CLEAR_HIZ:
1257926deccbSFrançois Tigeot 	case PACKET3_3D_CLEAR_ZMASK:
1258926deccbSFrançois Tigeot 		if (p->rdev->hyperz_filp != p->filp)
1259926deccbSFrançois Tigeot 			return -EINVAL;
1260926deccbSFrançois Tigeot 		break;
1261926deccbSFrançois Tigeot 	case PACKET3_3D_CLEAR_CMASK:
1262926deccbSFrançois Tigeot 		if (p->rdev->cmask_filp != p->filp)
1263926deccbSFrançois Tigeot 			return -EINVAL;
1264926deccbSFrançois Tigeot 		break;
1265926deccbSFrançois Tigeot 	case PACKET3_NOP:
1266926deccbSFrançois Tigeot 		break;
1267926deccbSFrançois Tigeot 	default:
1268926deccbSFrançois Tigeot 		DRM_ERROR("Packet3 opcode %x not supported\n", pkt->opcode);
1269926deccbSFrançois Tigeot 		return -EINVAL;
1270926deccbSFrançois Tigeot 	}
1271926deccbSFrançois Tigeot 	return 0;
1272926deccbSFrançois Tigeot }
1273926deccbSFrançois Tigeot 
r300_cs_parse(struct radeon_cs_parser * p)1274926deccbSFrançois Tigeot int r300_cs_parse(struct radeon_cs_parser *p)
1275926deccbSFrançois Tigeot {
1276926deccbSFrançois Tigeot 	struct radeon_cs_packet pkt;
1277926deccbSFrançois Tigeot 	struct r100_cs_track *track;
1278926deccbSFrançois Tigeot 	int r;
1279926deccbSFrançois Tigeot 
1280c4ef309bSzrj 	track = kzalloc(sizeof(*track), GFP_KERNEL);
1281926deccbSFrançois Tigeot 	if (track == NULL)
1282926deccbSFrançois Tigeot 		return -ENOMEM;
1283926deccbSFrançois Tigeot 	r100_cs_track_clear(p->rdev, track);
1284926deccbSFrançois Tigeot 	p->track = track;
1285926deccbSFrançois Tigeot 	do {
1286b403bed8SMichael Neumann 		r = radeon_cs_packet_parse(p, &pkt, p->idx);
1287926deccbSFrançois Tigeot 		if (r) {
1288926deccbSFrançois Tigeot 			return r;
1289926deccbSFrançois Tigeot 		}
1290926deccbSFrançois Tigeot 		p->idx += pkt.count + 2;
1291926deccbSFrançois Tigeot 		switch (pkt.type) {
1292b403bed8SMichael Neumann 		case RADEON_PACKET_TYPE0:
1293926deccbSFrançois Tigeot 			r = r100_cs_parse_packet0(p, &pkt,
1294926deccbSFrançois Tigeot 						  p->rdev->config.r300.reg_safe_bm,
1295926deccbSFrançois Tigeot 						  p->rdev->config.r300.reg_safe_bm_size,
1296926deccbSFrançois Tigeot 						  &r300_packet0_check);
1297926deccbSFrançois Tigeot 			break;
1298b403bed8SMichael Neumann 		case RADEON_PACKET_TYPE2:
1299926deccbSFrançois Tigeot 			break;
1300b403bed8SMichael Neumann 		case RADEON_PACKET_TYPE3:
1301926deccbSFrançois Tigeot 			r = r300_packet3_check(p, &pkt);
1302926deccbSFrançois Tigeot 			break;
1303926deccbSFrançois Tigeot 		default:
1304926deccbSFrançois Tigeot 			DRM_ERROR("Unknown packet type %d !\n", pkt.type);
1305926deccbSFrançois Tigeot 			return -EINVAL;
1306926deccbSFrançois Tigeot 		}
1307926deccbSFrançois Tigeot 		if (r) {
1308926deccbSFrançois Tigeot 			return r;
1309926deccbSFrançois Tigeot 		}
13107dcf36dcSFrançois Tigeot 	} while (p->idx < p->chunk_ib->length_dw);
1311926deccbSFrançois Tigeot 	return 0;
1312926deccbSFrançois Tigeot }
1313926deccbSFrançois Tigeot 
r300_set_reg_safe(struct radeon_device * rdev)1314926deccbSFrançois Tigeot void r300_set_reg_safe(struct radeon_device *rdev)
1315926deccbSFrançois Tigeot {
1316926deccbSFrançois Tigeot 	rdev->config.r300.reg_safe_bm = r300_reg_safe_bm;
1317c4ef309bSzrj 	rdev->config.r300.reg_safe_bm_size = ARRAY_SIZE(r300_reg_safe_bm);
1318926deccbSFrançois Tigeot }
1319926deccbSFrançois Tigeot 
r300_mc_program(struct radeon_device * rdev)1320926deccbSFrançois Tigeot void r300_mc_program(struct radeon_device *rdev)
1321926deccbSFrançois Tigeot {
1322926deccbSFrançois Tigeot 	struct r100_mc_save save;
1323926deccbSFrançois Tigeot 	int r;
1324926deccbSFrançois Tigeot 
1325926deccbSFrançois Tigeot 	r = r100_debugfs_mc_info_init(rdev);
1326926deccbSFrançois Tigeot 	if (r) {
1327926deccbSFrançois Tigeot 		dev_err(rdev->dev, "Failed to create r100_mc debugfs file.\n");
1328926deccbSFrançois Tigeot 	}
1329926deccbSFrançois Tigeot 
1330926deccbSFrançois Tigeot 	/* Stops all mc clients */
1331926deccbSFrançois Tigeot 	r100_mc_stop(rdev, &save);
1332926deccbSFrançois Tigeot 	if (rdev->flags & RADEON_IS_AGP) {
1333926deccbSFrançois Tigeot 		WREG32(R_00014C_MC_AGP_LOCATION,
1334926deccbSFrançois Tigeot 			S_00014C_MC_AGP_START(rdev->mc.gtt_start >> 16) |
1335926deccbSFrançois Tigeot 			S_00014C_MC_AGP_TOP(rdev->mc.gtt_end >> 16));
1336926deccbSFrançois Tigeot 		WREG32(R_000170_AGP_BASE, lower_32_bits(rdev->mc.agp_base));
1337926deccbSFrançois Tigeot 		WREG32(R_00015C_AGP_BASE_2,
1338926deccbSFrançois Tigeot 			upper_32_bits(rdev->mc.agp_base) & 0xff);
1339926deccbSFrançois Tigeot 	} else {
1340926deccbSFrançois Tigeot 		WREG32(R_00014C_MC_AGP_LOCATION, 0x0FFFFFFF);
1341926deccbSFrançois Tigeot 		WREG32(R_000170_AGP_BASE, 0);
1342926deccbSFrançois Tigeot 		WREG32(R_00015C_AGP_BASE_2, 0);
1343926deccbSFrançois Tigeot 	}
1344926deccbSFrançois Tigeot 	/* Wait for mc idle */
1345926deccbSFrançois Tigeot 	if (r300_mc_wait_for_idle(rdev))
1346926deccbSFrançois Tigeot 		DRM_INFO("Failed to wait MC idle before programming MC.\n");
1347926deccbSFrançois Tigeot 	/* Program MC, should be a 32bits limited address space */
1348926deccbSFrançois Tigeot 	WREG32(R_000148_MC_FB_LOCATION,
1349926deccbSFrançois Tigeot 		S_000148_MC_FB_START(rdev->mc.vram_start >> 16) |
1350926deccbSFrançois Tigeot 		S_000148_MC_FB_TOP(rdev->mc.vram_end >> 16));
1351926deccbSFrançois Tigeot 	r100_mc_resume(rdev, &save);
1352926deccbSFrançois Tigeot }
1353926deccbSFrançois Tigeot 
r300_clock_startup(struct radeon_device * rdev)1354926deccbSFrançois Tigeot void r300_clock_startup(struct radeon_device *rdev)
1355926deccbSFrançois Tigeot {
1356926deccbSFrançois Tigeot 	u32 tmp;
1357926deccbSFrançois Tigeot 
1358926deccbSFrançois Tigeot 	if (radeon_dynclks != -1 && radeon_dynclks)
1359926deccbSFrançois Tigeot 		radeon_legacy_set_clock_gating(rdev, 1);
1360926deccbSFrançois Tigeot 	/* We need to force on some of the block */
1361926deccbSFrançois Tigeot 	tmp = RREG32_PLL(R_00000D_SCLK_CNTL);
1362926deccbSFrançois Tigeot 	tmp |= S_00000D_FORCE_CP(1) | S_00000D_FORCE_VIP(1);
1363926deccbSFrançois Tigeot 	if ((rdev->family == CHIP_RV350) || (rdev->family == CHIP_RV380))
1364926deccbSFrançois Tigeot 		tmp |= S_00000D_FORCE_VAP(1);
1365926deccbSFrançois Tigeot 	WREG32_PLL(R_00000D_SCLK_CNTL, tmp);
1366926deccbSFrançois Tigeot }
1367926deccbSFrançois Tigeot 
r300_startup(struct radeon_device * rdev)1368926deccbSFrançois Tigeot static int r300_startup(struct radeon_device *rdev)
1369926deccbSFrançois Tigeot {
1370926deccbSFrançois Tigeot 	int r;
1371926deccbSFrançois Tigeot 
1372926deccbSFrançois Tigeot 	/* set common regs */
1373926deccbSFrançois Tigeot 	r100_set_common_regs(rdev);
1374926deccbSFrançois Tigeot 	/* program mc */
1375926deccbSFrançois Tigeot 	r300_mc_program(rdev);
1376926deccbSFrançois Tigeot 	/* Resume clock */
1377926deccbSFrançois Tigeot 	r300_clock_startup(rdev);
1378926deccbSFrançois Tigeot 	/* Initialize GPU configuration (# pipes, ...) */
1379926deccbSFrançois Tigeot 	r300_gpu_init(rdev);
1380926deccbSFrançois Tigeot 	/* Initialize GART (initialize after TTM so we can allocate
1381926deccbSFrançois Tigeot 	 * memory through TTM but finalize after TTM) */
1382926deccbSFrançois Tigeot 	if (rdev->flags & RADEON_IS_PCIE) {
1383926deccbSFrançois Tigeot 		r = rv370_pcie_gart_enable(rdev);
1384926deccbSFrançois Tigeot 		if (r)
1385926deccbSFrançois Tigeot 			return r;
1386926deccbSFrançois Tigeot 	}
1387926deccbSFrançois Tigeot 
1388926deccbSFrançois Tigeot 	if (rdev->family == CHIP_R300 ||
1389926deccbSFrançois Tigeot 	    rdev->family == CHIP_R350 ||
1390926deccbSFrançois Tigeot 	    rdev->family == CHIP_RV350)
1391926deccbSFrançois Tigeot 		r100_enable_bm(rdev);
1392926deccbSFrançois Tigeot 
1393926deccbSFrançois Tigeot 	if (rdev->flags & RADEON_IS_PCI) {
1394926deccbSFrançois Tigeot 		r = r100_pci_gart_enable(rdev);
1395926deccbSFrançois Tigeot 		if (r)
1396926deccbSFrançois Tigeot 			return r;
1397926deccbSFrançois Tigeot 	}
1398926deccbSFrançois Tigeot 
1399926deccbSFrançois Tigeot 	/* allocate wb buffer */
1400926deccbSFrançois Tigeot 	r = radeon_wb_init(rdev);
1401926deccbSFrançois Tigeot 	if (r)
1402926deccbSFrançois Tigeot 		return r;
1403926deccbSFrançois Tigeot 
1404926deccbSFrançois Tigeot 	r = radeon_fence_driver_start_ring(rdev, RADEON_RING_TYPE_GFX_INDEX);
1405926deccbSFrançois Tigeot 	if (r) {
1406926deccbSFrançois Tigeot 		dev_err(rdev->dev, "failed initializing CP fences (%d).\n", r);
1407926deccbSFrançois Tigeot 		return r;
1408926deccbSFrançois Tigeot 	}
1409926deccbSFrançois Tigeot 
1410926deccbSFrançois Tigeot 	/* Enable IRQ */
1411f43cf1b1SMichael Neumann 	if (!rdev->irq.installed) {
1412f43cf1b1SMichael Neumann 		r = radeon_irq_kms_init(rdev);
1413f43cf1b1SMichael Neumann 		if (r)
1414f43cf1b1SMichael Neumann 			return r;
1415f43cf1b1SMichael Neumann 	}
1416f43cf1b1SMichael Neumann 
1417926deccbSFrançois Tigeot 	r100_irq_set(rdev);
1418926deccbSFrançois Tigeot 	rdev->config.r300.hdp_cntl = RREG32(RADEON_HOST_PATH_CNTL);
1419926deccbSFrançois Tigeot 	/* 1M ring buffer */
1420926deccbSFrançois Tigeot 	r = r100_cp_init(rdev, 1024 * 1024);
1421926deccbSFrançois Tigeot 	if (r) {
1422926deccbSFrançois Tigeot 		dev_err(rdev->dev, "failed initializing CP (%d).\n", r);
1423926deccbSFrançois Tigeot 		return r;
1424926deccbSFrançois Tigeot 	}
1425926deccbSFrançois Tigeot 
1426926deccbSFrançois Tigeot 	r = radeon_ib_pool_init(rdev);
1427926deccbSFrançois Tigeot 	if (r) {
1428926deccbSFrançois Tigeot 		dev_err(rdev->dev, "IB initialization failed (%d).\n", r);
1429926deccbSFrançois Tigeot 		return r;
1430926deccbSFrançois Tigeot 	}
1431926deccbSFrançois Tigeot 
1432926deccbSFrançois Tigeot 	return 0;
1433926deccbSFrançois Tigeot }
1434926deccbSFrançois Tigeot 
r300_resume(struct radeon_device * rdev)1435926deccbSFrançois Tigeot int r300_resume(struct radeon_device *rdev)
1436926deccbSFrançois Tigeot {
1437926deccbSFrançois Tigeot 	int r;
1438926deccbSFrançois Tigeot 
1439926deccbSFrançois Tigeot 	/* Make sur GART are not working */
1440926deccbSFrançois Tigeot 	if (rdev->flags & RADEON_IS_PCIE)
1441926deccbSFrançois Tigeot 		rv370_pcie_gart_disable(rdev);
1442926deccbSFrançois Tigeot 	if (rdev->flags & RADEON_IS_PCI)
1443926deccbSFrançois Tigeot 		r100_pci_gart_disable(rdev);
1444926deccbSFrançois Tigeot 	/* Resume clock before doing reset */
1445926deccbSFrançois Tigeot 	r300_clock_startup(rdev);
1446926deccbSFrançois Tigeot 	/* Reset gpu before posting otherwise ATOM will enter infinite loop */
1447926deccbSFrançois Tigeot 	if (radeon_asic_reset(rdev)) {
1448926deccbSFrançois Tigeot 		dev_warn(rdev->dev, "GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n",
1449926deccbSFrançois Tigeot 			RREG32(R_000E40_RBBM_STATUS),
1450926deccbSFrançois Tigeot 			RREG32(R_0007C0_CP_STAT));
1451926deccbSFrançois Tigeot 	}
1452926deccbSFrançois Tigeot 	/* post */
1453926deccbSFrançois Tigeot 	radeon_combios_asic_init(rdev->ddev);
1454926deccbSFrançois Tigeot 	/* Resume clock after posting */
1455926deccbSFrançois Tigeot 	r300_clock_startup(rdev);
1456926deccbSFrançois Tigeot 	/* Initialize surface registers */
1457926deccbSFrançois Tigeot 	radeon_surface_init(rdev);
1458926deccbSFrançois Tigeot 
1459926deccbSFrançois Tigeot 	rdev->accel_working = true;
1460926deccbSFrançois Tigeot 	r = r300_startup(rdev);
1461926deccbSFrançois Tigeot 	if (r) {
1462926deccbSFrançois Tigeot 		rdev->accel_working = false;
1463926deccbSFrançois Tigeot 	}
1464926deccbSFrançois Tigeot 	return r;
1465926deccbSFrançois Tigeot }
1466926deccbSFrançois Tigeot 
r300_suspend(struct radeon_device * rdev)1467926deccbSFrançois Tigeot int r300_suspend(struct radeon_device *rdev)
1468926deccbSFrançois Tigeot {
1469c6f73aabSFrançois Tigeot 	radeon_pm_suspend(rdev);
1470926deccbSFrançois Tigeot 	r100_cp_disable(rdev);
1471926deccbSFrançois Tigeot 	radeon_wb_disable(rdev);
1472926deccbSFrançois Tigeot 	r100_irq_disable(rdev);
1473926deccbSFrançois Tigeot 	if (rdev->flags & RADEON_IS_PCIE)
1474926deccbSFrançois Tigeot 		rv370_pcie_gart_disable(rdev);
1475926deccbSFrançois Tigeot 	if (rdev->flags & RADEON_IS_PCI)
1476926deccbSFrançois Tigeot 		r100_pci_gart_disable(rdev);
1477926deccbSFrançois Tigeot 	return 0;
1478926deccbSFrançois Tigeot }
1479926deccbSFrançois Tigeot 
r300_fini(struct radeon_device * rdev)1480926deccbSFrançois Tigeot void r300_fini(struct radeon_device *rdev)
1481926deccbSFrançois Tigeot {
1482c6f73aabSFrançois Tigeot 	radeon_pm_fini(rdev);
1483926deccbSFrançois Tigeot 	r100_cp_fini(rdev);
1484926deccbSFrançois Tigeot 	radeon_wb_fini(rdev);
1485926deccbSFrançois Tigeot 	radeon_ib_pool_fini(rdev);
1486926deccbSFrançois Tigeot 	radeon_gem_fini(rdev);
1487926deccbSFrançois Tigeot 	if (rdev->flags & RADEON_IS_PCIE)
1488926deccbSFrançois Tigeot 		rv370_pcie_gart_fini(rdev);
1489926deccbSFrançois Tigeot 	if (rdev->flags & RADEON_IS_PCI)
1490926deccbSFrançois Tigeot 		r100_pci_gart_fini(rdev);
1491926deccbSFrançois Tigeot 	radeon_agp_fini(rdev);
1492926deccbSFrançois Tigeot 	radeon_irq_kms_fini(rdev);
1493926deccbSFrançois Tigeot 	radeon_fence_driver_fini(rdev);
1494926deccbSFrançois Tigeot 	radeon_bo_fini(rdev);
1495926deccbSFrançois Tigeot 	radeon_atombios_fini(rdev);
1496c4ef309bSzrj 	kfree(rdev->bios);
1497926deccbSFrançois Tigeot 	rdev->bios = NULL;
1498926deccbSFrançois Tigeot }
1499926deccbSFrançois Tigeot 
r300_init(struct radeon_device * rdev)1500926deccbSFrançois Tigeot int r300_init(struct radeon_device *rdev)
1501926deccbSFrançois Tigeot {
1502926deccbSFrançois Tigeot 	int r;
1503926deccbSFrançois Tigeot 
1504926deccbSFrançois Tigeot 	/* Disable VGA */
1505926deccbSFrançois Tigeot 	r100_vga_render_disable(rdev);
1506926deccbSFrançois Tigeot 	/* Initialize scratch registers */
1507926deccbSFrançois Tigeot 	radeon_scratch_init(rdev);
1508926deccbSFrançois Tigeot 	/* Initialize surface registers */
1509926deccbSFrançois Tigeot 	radeon_surface_init(rdev);
1510926deccbSFrançois Tigeot 	/* TODO: disable VGA need to use VGA request */
1511926deccbSFrançois Tigeot 	/* restore some register to sane defaults */
1512926deccbSFrançois Tigeot 	r100_restore_sanity(rdev);
1513926deccbSFrançois Tigeot 	/* BIOS*/
1514926deccbSFrançois Tigeot 	if (!radeon_get_bios(rdev)) {
1515926deccbSFrançois Tigeot 		if (ASIC_IS_AVIVO(rdev))
1516926deccbSFrançois Tigeot 			return -EINVAL;
1517926deccbSFrançois Tigeot 	}
1518926deccbSFrançois Tigeot 	if (rdev->is_atom_bios) {
1519926deccbSFrançois Tigeot 		dev_err(rdev->dev, "Expecting combios for RS400/RS480 GPU\n");
1520926deccbSFrançois Tigeot 		return -EINVAL;
1521926deccbSFrançois Tigeot 	} else {
1522926deccbSFrançois Tigeot 		r = radeon_combios_init(rdev);
1523926deccbSFrançois Tigeot 		if (r)
1524926deccbSFrançois Tigeot 			return r;
1525926deccbSFrançois Tigeot 	}
1526926deccbSFrançois Tigeot 	/* Reset gpu before posting otherwise ATOM will enter infinite loop */
1527926deccbSFrançois Tigeot 	if (radeon_asic_reset(rdev)) {
1528926deccbSFrançois Tigeot 		dev_warn(rdev->dev,
1529926deccbSFrançois Tigeot 			"GPU reset failed ! (0xE40=0x%08X, 0x7C0=0x%08X)\n",
1530926deccbSFrançois Tigeot 			RREG32(R_000E40_RBBM_STATUS),
1531926deccbSFrançois Tigeot 			RREG32(R_0007C0_CP_STAT));
1532926deccbSFrançois Tigeot 	}
1533926deccbSFrançois Tigeot 	/* check if cards are posted or not */
1534926deccbSFrançois Tigeot 	if (radeon_boot_test_post_card(rdev) == false)
1535926deccbSFrançois Tigeot 		return -EINVAL;
1536926deccbSFrançois Tigeot 	/* Set asic errata */
1537926deccbSFrançois Tigeot 	r300_errata(rdev);
1538926deccbSFrançois Tigeot 	/* Initialize clocks */
1539926deccbSFrançois Tigeot 	radeon_get_clock_info(rdev->ddev);
1540926deccbSFrançois Tigeot 	/* initialize AGP */
1541926deccbSFrançois Tigeot 	if (rdev->flags & RADEON_IS_AGP) {
1542926deccbSFrançois Tigeot 		r = radeon_agp_init(rdev);
1543926deccbSFrançois Tigeot 		if (r) {
1544926deccbSFrançois Tigeot 			radeon_agp_disable(rdev);
1545926deccbSFrançois Tigeot 		}
1546926deccbSFrançois Tigeot 	}
1547926deccbSFrançois Tigeot 	/* initialize memory controller */
1548926deccbSFrançois Tigeot 	r300_mc_init(rdev);
1549926deccbSFrançois Tigeot 	/* Fence driver */
1550926deccbSFrançois Tigeot 	r = radeon_fence_driver_init(rdev);
1551926deccbSFrançois Tigeot 	if (r)
1552926deccbSFrançois Tigeot 		return r;
1553926deccbSFrançois Tigeot 	/* Memory manager */
1554926deccbSFrançois Tigeot 	r = radeon_bo_init(rdev);
1555926deccbSFrançois Tigeot 	if (r)
1556926deccbSFrançois Tigeot 		return r;
1557926deccbSFrançois Tigeot 	if (rdev->flags & RADEON_IS_PCIE) {
1558926deccbSFrançois Tigeot 		r = rv370_pcie_gart_init(rdev);
1559926deccbSFrançois Tigeot 		if (r)
1560926deccbSFrançois Tigeot 			return r;
1561926deccbSFrançois Tigeot 	}
1562926deccbSFrançois Tigeot 	if (rdev->flags & RADEON_IS_PCI) {
1563926deccbSFrançois Tigeot 		r = r100_pci_gart_init(rdev);
1564926deccbSFrançois Tigeot 		if (r)
1565926deccbSFrançois Tigeot 			return r;
1566926deccbSFrançois Tigeot 	}
1567926deccbSFrançois Tigeot 	r300_set_reg_safe(rdev);
1568926deccbSFrançois Tigeot 
1569c6f73aabSFrançois Tigeot 	/* Initialize power management */
1570c6f73aabSFrançois Tigeot 	radeon_pm_init(rdev);
1571c6f73aabSFrançois Tigeot 
1572926deccbSFrançois Tigeot 	rdev->accel_working = true;
1573926deccbSFrançois Tigeot 	r = r300_startup(rdev);
1574926deccbSFrançois Tigeot 	if (r) {
15754cd92098Szrj 		/* Something went wrong with the accel init, so stop accel */
1576926deccbSFrançois Tigeot 		dev_err(rdev->dev, "Disabling GPU acceleration\n");
1577926deccbSFrançois Tigeot 		r100_cp_fini(rdev);
1578926deccbSFrançois Tigeot 		radeon_wb_fini(rdev);
1579926deccbSFrançois Tigeot 		radeon_ib_pool_fini(rdev);
1580926deccbSFrançois Tigeot 		radeon_irq_kms_fini(rdev);
1581926deccbSFrançois Tigeot 		if (rdev->flags & RADEON_IS_PCIE)
1582926deccbSFrançois Tigeot 			rv370_pcie_gart_fini(rdev);
1583926deccbSFrançois Tigeot 		if (rdev->flags & RADEON_IS_PCI)
1584926deccbSFrançois Tigeot 			r100_pci_gart_fini(rdev);
1585926deccbSFrançois Tigeot 		radeon_agp_fini(rdev);
1586926deccbSFrançois Tigeot 		rdev->accel_working = false;
1587926deccbSFrançois Tigeot 	}
1588926deccbSFrançois Tigeot 	return 0;
1589926deccbSFrançois Tigeot }
1590