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