r600_cp.c revision 189499
1189499Srnoland/*-
2189499Srnoland * Copyright 2008-2009 Advanced Micro Devices, Inc.
3189499Srnoland * Copyright 2008 Red Hat Inc.
4189499Srnoland *
5189499Srnoland * Permission is hereby granted, free of charge, to any person obtaining a
6189499Srnoland * copy of this software and associated documentation files (the "Software"),
7189499Srnoland * to deal in the Software without restriction, including without limitation
8189499Srnoland * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9189499Srnoland * and/or sell copies of the Software, and to permit persons to whom the
10189499Srnoland * Software is furnished to do so, subject to the following conditions:
11189499Srnoland *
12189499Srnoland * The above copyright notice and this permission notice (including the next
13189499Srnoland * paragraph) shall be included in all copies or substantial portions of the
14189499Srnoland * Software.
15189499Srnoland *
16189499Srnoland * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17189499Srnoland * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18189499Srnoland * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19189499Srnoland * THE COPYRIGHT HOLDER(S) AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20189499Srnoland * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21189499Srnoland * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22189499Srnoland * DEALINGS IN THE SOFTWARE.
23189499Srnoland *
24189499Srnoland * Authors:
25189499Srnoland *     Dave Airlie <airlied@redhat.com>
26189499Srnoland *     Alex Deucher <alexander.deucher@amd.com>
27189499Srnoland */
28189499Srnoland
29189499Srnoland#include <sys/cdefs.h>
30189499Srnoland__FBSDID("$FreeBSD: head/sys/dev/drm/r600_cp.c 189499 2009-03-07 21:36:57Z rnoland $");
31189499Srnoland
32189499Srnoland#include "dev/drm/drmP.h"
33189499Srnoland#include "dev/drm/drm.h"
34189499Srnoland#include "dev/drm/radeon_drm.h"
35189499Srnoland#include "dev/drm/radeon_drv.h"
36189499Srnoland
37189499Srnoland#include "dev/drm/r600_microcode.h"
38189499Srnoland
39189499Srnoland# define ATI_PCIGART_PAGE_SIZE		4096	/**< PCI GART page size */
40189499Srnoland# define ATI_PCIGART_PAGE_MASK		(~(ATI_PCIGART_PAGE_SIZE-1))
41189499Srnoland
42189499Srnoland#define R600_PTE_VALID     (1 << 0)
43189499Srnoland#define R600_PTE_SYSTEM    (1 << 1)
44189499Srnoland#define R600_PTE_SNOOPED   (1 << 2)
45189499Srnoland#define R600_PTE_READABLE  (1 << 5)
46189499Srnoland#define R600_PTE_WRITEABLE (1 << 6)
47189499Srnoland
48189499Srnoland/* MAX values used for gfx init */
49189499Srnoland#define R6XX_MAX_SH_GPRS           256
50189499Srnoland#define R6XX_MAX_TEMP_GPRS         16
51189499Srnoland#define R6XX_MAX_SH_THREADS        256
52189499Srnoland#define R6XX_MAX_SH_STACK_ENTRIES  4096
53189499Srnoland#define R6XX_MAX_BACKENDS          8
54189499Srnoland#define R6XX_MAX_BACKENDS_MASK     0xff
55189499Srnoland#define R6XX_MAX_SIMDS             8
56189499Srnoland#define R6XX_MAX_SIMDS_MASK        0xff
57189499Srnoland#define R6XX_MAX_PIPES             8
58189499Srnoland#define R6XX_MAX_PIPES_MASK        0xff
59189499Srnoland
60189499Srnoland#define R7XX_MAX_SH_GPRS           256
61189499Srnoland#define R7XX_MAX_TEMP_GPRS         16
62189499Srnoland#define R7XX_MAX_SH_THREADS        256
63189499Srnoland#define R7XX_MAX_SH_STACK_ENTRIES  4096
64189499Srnoland#define R7XX_MAX_BACKENDS          8
65189499Srnoland#define R7XX_MAX_BACKENDS_MASK     0xff
66189499Srnoland#define R7XX_MAX_SIMDS             16
67189499Srnoland#define R7XX_MAX_SIMDS_MASK        0xffff
68189499Srnoland#define R7XX_MAX_PIPES             8
69189499Srnoland#define R7XX_MAX_PIPES_MASK        0xff
70189499Srnoland
71189499Srnolandstatic int r600_do_wait_for_fifo(drm_radeon_private_t *dev_priv, int entries)
72189499Srnoland{
73189499Srnoland	int i;
74189499Srnoland
75189499Srnoland	dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
76189499Srnoland
77189499Srnoland	for (i = 0; i < dev_priv->usec_timeout; i++) {
78189499Srnoland		int slots;
79189499Srnoland		if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770)
80189499Srnoland			slots = (RADEON_READ(R600_GRBM_STATUS)
81189499Srnoland				 & R700_CMDFIFO_AVAIL_MASK);
82189499Srnoland		else
83189499Srnoland			slots = (RADEON_READ(R600_GRBM_STATUS)
84189499Srnoland				 & R600_CMDFIFO_AVAIL_MASK);
85189499Srnoland		if (slots >= entries)
86189499Srnoland			return 0;
87189499Srnoland		DRM_UDELAY(1);
88189499Srnoland	}
89189499Srnoland	DRM_INFO("wait for fifo failed status : 0x%08X 0x%08X\n",
90189499Srnoland		 RADEON_READ(R600_GRBM_STATUS),
91189499Srnoland		 RADEON_READ(R600_GRBM_STATUS2));
92189499Srnoland
93189499Srnoland	return -EBUSY;
94189499Srnoland}
95189499Srnoland
96189499Srnolandstatic int r600_do_wait_for_idle(drm_radeon_private_t *dev_priv)
97189499Srnoland{
98189499Srnoland	int i, ret;
99189499Srnoland
100189499Srnoland	dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE;
101189499Srnoland
102189499Srnoland	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770)
103189499Srnoland		ret = r600_do_wait_for_fifo(dev_priv, 8);
104189499Srnoland	else
105189499Srnoland		ret = r600_do_wait_for_fifo(dev_priv, 16);
106189499Srnoland	if (ret)
107189499Srnoland		return ret;
108189499Srnoland	for (i = 0; i < dev_priv->usec_timeout; i++) {
109189499Srnoland		if (!(RADEON_READ(R600_GRBM_STATUS) & R600_GUI_ACTIVE))
110189499Srnoland			return 0;
111189499Srnoland		DRM_UDELAY(1);
112189499Srnoland	}
113189499Srnoland	DRM_INFO("wait idle failed status : 0x%08X 0x%08X\n",
114189499Srnoland		 RADEON_READ(R600_GRBM_STATUS),
115189499Srnoland		 RADEON_READ(R600_GRBM_STATUS2));
116189499Srnoland
117189499Srnoland	return -EBUSY;
118189499Srnoland}
119189499Srnoland
120189499Srnolandvoid r600_page_table_cleanup(struct drm_device *dev, struct drm_ati_pcigart_info *gart_info)
121189499Srnoland{
122189499Srnoland#ifdef __linux__
123189499Srnoland	struct drm_sg_mem *entry = dev->sg;
124189499Srnoland	int max_pages;
125189499Srnoland	int pages;
126189499Srnoland	int i;
127189499Srnoland#endif
128189499Srnoland	if (gart_info->bus_addr) {
129189499Srnoland#ifdef __linux__
130189499Srnoland		max_pages = (gart_info->table_size / sizeof(u32));
131189499Srnoland		pages = (entry->pages <= max_pages)
132189499Srnoland		  ? entry->pages : max_pages;
133189499Srnoland
134189499Srnoland		for (i = 0; i < pages; i++) {
135189499Srnoland			if (!entry->busaddr[i])
136189499Srnoland				break;
137189499Srnoland			pci_unmap_single(dev->pdev, entry->busaddr[i],
138189499Srnoland					 PAGE_SIZE, PCI_DMA_TODEVICE);
139189499Srnoland		}
140189499Srnoland#endif
141189499Srnoland		if (gart_info->gart_table_location == DRM_ATI_GART_MAIN)
142189499Srnoland			gart_info->bus_addr = 0;
143189499Srnoland	}
144189499Srnoland}
145189499Srnoland
146189499Srnoland/* R600 has page table setup */
147189499Srnolandint r600_page_table_init(struct drm_device *dev)
148189499Srnoland{
149189499Srnoland	drm_radeon_private_t *dev_priv = dev->dev_private;
150189499Srnoland	struct drm_ati_pcigart_info *gart_info = &dev_priv->gart_info;
151189499Srnoland	struct drm_sg_mem *entry = dev->sg;
152189499Srnoland	int ret = 0;
153189499Srnoland	int i, j;
154189499Srnoland	int max_pages, pages;
155189499Srnoland	u64 *pci_gart, page_base;
156189499Srnoland	dma_addr_t entry_addr;
157189499Srnoland
158189499Srnoland	/* okay page table is available - lets rock */
159189499Srnoland
160189499Srnoland	/* PTEs are 64-bits */
161189499Srnoland	pci_gart = (u64 *)gart_info->addr;
162189499Srnoland
163189499Srnoland	max_pages = (gart_info->table_size / sizeof(u64));
164189499Srnoland	pages = (entry->pages <= max_pages) ? entry->pages : max_pages;
165189499Srnoland
166189499Srnoland	memset(pci_gart, 0, max_pages * sizeof(u64));
167189499Srnoland
168189499Srnoland	for (i = 0; i < pages; i++) {
169189499Srnoland#ifdef __linux__
170189499Srnoland		entry->busaddr[i] = pci_map_single(dev->pdev,
171189499Srnoland						   page_address(entry->
172189499Srnoland								pagelist[i]),
173189499Srnoland						   PAGE_SIZE, PCI_DMA_TODEVICE);
174189499Srnoland		if (entry->busaddr[i] == 0) {
175189499Srnoland			DRM_ERROR("unable to map PCIGART pages!\n");
176189499Srnoland			r600_page_table_cleanup(dev, gart_info);
177189499Srnoland			ret = -EINVAL;
178189499Srnoland			goto done;
179189499Srnoland		}
180189499Srnoland#endif
181189499Srnoland		entry_addr = entry->busaddr[i];
182189499Srnoland		for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) {
183189499Srnoland			page_base = (u64) entry_addr & ATI_PCIGART_PAGE_MASK;
184189499Srnoland			page_base |= R600_PTE_VALID | R600_PTE_SYSTEM | R600_PTE_SNOOPED;
185189499Srnoland			page_base |= R600_PTE_READABLE | R600_PTE_WRITEABLE;
186189499Srnoland
187189499Srnoland			*pci_gart = page_base;
188189499Srnoland
189189499Srnoland			if ((i % 128) == 0)
190189499Srnoland				DRM_DEBUG("page entry %d: 0x%016llx\n",
191189499Srnoland				    i, (unsigned long long)page_base);
192189499Srnoland			pci_gart++;
193189499Srnoland			entry_addr += ATI_PCIGART_PAGE_SIZE;
194189499Srnoland		}
195189499Srnoland	}
196189499Srnoland#ifdef __linux__
197189499Srnolanddone:
198189499Srnoland#endif
199189499Srnoland	return ret;
200189499Srnoland}
201189499Srnoland
202189499Srnolandstatic void r600_vm_flush_gart_range(struct drm_device *dev)
203189499Srnoland{
204189499Srnoland	drm_radeon_private_t *dev_priv = dev->dev_private;
205189499Srnoland	u32 resp, countdown = 1000;
206189499Srnoland	RADEON_WRITE(R600_VM_CONTEXT0_INVALIDATION_LOW_ADDR, dev_priv->gart_vm_start >> 12);
207189499Srnoland	RADEON_WRITE(R600_VM_CONTEXT0_INVALIDATION_HIGH_ADDR, (dev_priv->gart_vm_start + dev_priv->gart_size - 1) >> 12);
208189499Srnoland	RADEON_WRITE(R600_VM_CONTEXT0_REQUEST_RESPONSE, 2);
209189499Srnoland
210189499Srnoland	do {
211189499Srnoland		resp = RADEON_READ(R600_VM_CONTEXT0_REQUEST_RESPONSE);
212189499Srnoland		countdown--;
213189499Srnoland		DRM_UDELAY(1);
214189499Srnoland	} while (((resp & 0xf0) == 0) && countdown);
215189499Srnoland}
216189499Srnoland
217189499Srnolandstatic void r600_vm_init(struct drm_device *dev)
218189499Srnoland{
219189499Srnoland	drm_radeon_private_t *dev_priv = dev->dev_private;
220189499Srnoland	/* initialise the VM to use the page table we constructed up there */
221189499Srnoland	u32 vm_c0, i;
222189499Srnoland	u32 mc_rd_a;
223189499Srnoland	u32 vm_l2_cntl, vm_l2_cntl3;
224189499Srnoland	/* okay set up the PCIE aperture type thingo */
225189499Srnoland	RADEON_WRITE(R600_MC_VM_SYSTEM_APERTURE_LOW_ADDR, dev_priv->gart_vm_start >> 12);
226189499Srnoland	RADEON_WRITE(R600_MC_VM_SYSTEM_APERTURE_HIGH_ADDR, (dev_priv->gart_vm_start + dev_priv->gart_size - 1) >> 12);
227189499Srnoland	RADEON_WRITE(R600_MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, 0);
228189499Srnoland
229189499Srnoland	/* setup MC RD a */
230189499Srnoland	mc_rd_a = R600_MCD_L1_TLB | R600_MCD_L1_FRAG_PROC | R600_MCD_SYSTEM_ACCESS_MODE_IN_SYS |
231189499Srnoland		R600_MCD_SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU | R600_MCD_EFFECTIVE_L1_TLB_SIZE(5) |
232189499Srnoland		R600_MCD_EFFECTIVE_L1_QUEUE_SIZE(5) | R600_MCD_WAIT_L2_QUERY;
233189499Srnoland
234189499Srnoland	RADEON_WRITE(R600_MCD_RD_A_CNTL, mc_rd_a);
235189499Srnoland	RADEON_WRITE(R600_MCD_RD_B_CNTL, mc_rd_a);
236189499Srnoland
237189499Srnoland	RADEON_WRITE(R600_MCD_WR_A_CNTL, mc_rd_a);
238189499Srnoland	RADEON_WRITE(R600_MCD_WR_B_CNTL, mc_rd_a);
239189499Srnoland
240189499Srnoland	RADEON_WRITE(R600_MCD_RD_GFX_CNTL, mc_rd_a);
241189499Srnoland	RADEON_WRITE(R600_MCD_WR_GFX_CNTL, mc_rd_a);
242189499Srnoland
243189499Srnoland	RADEON_WRITE(R600_MCD_RD_SYS_CNTL, mc_rd_a);
244189499Srnoland	RADEON_WRITE(R600_MCD_WR_SYS_CNTL, mc_rd_a);
245189499Srnoland
246189499Srnoland	RADEON_WRITE(R600_MCD_RD_HDP_CNTL, mc_rd_a | R600_MCD_L1_STRICT_ORDERING);
247189499Srnoland	RADEON_WRITE(R600_MCD_WR_HDP_CNTL, mc_rd_a /*| R600_MCD_L1_STRICT_ORDERING*/);
248189499Srnoland
249189499Srnoland	RADEON_WRITE(R600_MCD_RD_PDMA_CNTL, mc_rd_a);
250189499Srnoland	RADEON_WRITE(R600_MCD_WR_PDMA_CNTL, mc_rd_a);
251189499Srnoland
252189499Srnoland	RADEON_WRITE(R600_MCD_RD_SEM_CNTL, mc_rd_a | R600_MCD_SEMAPHORE_MODE);
253189499Srnoland	RADEON_WRITE(R600_MCD_WR_SEM_CNTL, mc_rd_a);
254189499Srnoland
255189499Srnoland	vm_l2_cntl = R600_VM_L2_CACHE_EN | R600_VM_L2_FRAG_PROC | R600_VM_ENABLE_PTE_CACHE_LRU_W;
256189499Srnoland	vm_l2_cntl |= R600_VM_L2_CNTL_QUEUE_SIZE(7);
257189499Srnoland	RADEON_WRITE(R600_VM_L2_CNTL, vm_l2_cntl);
258189499Srnoland
259189499Srnoland	RADEON_WRITE(R600_VM_L2_CNTL2, 0);
260189499Srnoland	vm_l2_cntl3 = (R600_VM_L2_CNTL3_BANK_SELECT_0(0) |
261189499Srnoland		       R600_VM_L2_CNTL3_BANK_SELECT_1(1) |
262189499Srnoland		       R600_VM_L2_CNTL3_CACHE_UPDATE_MODE(2));
263189499Srnoland	RADEON_WRITE(R600_VM_L2_CNTL3, vm_l2_cntl3);
264189499Srnoland
265189499Srnoland	vm_c0 = R600_VM_ENABLE_CONTEXT | R600_VM_PAGE_TABLE_DEPTH_FLAT;
266189499Srnoland
267189499Srnoland	RADEON_WRITE(R600_VM_CONTEXT0_CNTL, vm_c0);
268189499Srnoland
269189499Srnoland	vm_c0 &= ~R600_VM_ENABLE_CONTEXT;
270189499Srnoland
271189499Srnoland	/* disable all other contexts */
272189499Srnoland	for (i = 1; i < 8; i++)
273189499Srnoland		RADEON_WRITE(R600_VM_CONTEXT0_CNTL + (i * 4), vm_c0);
274189499Srnoland
275189499Srnoland	RADEON_WRITE(R600_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, dev_priv->gart_info.bus_addr >> 12);
276189499Srnoland	RADEON_WRITE(R600_VM_CONTEXT0_PAGE_TABLE_START_ADDR, dev_priv->gart_vm_start >> 12);
277189499Srnoland	RADEON_WRITE(R600_VM_CONTEXT0_PAGE_TABLE_END_ADDR, (dev_priv->gart_vm_start + dev_priv->gart_size - 1) >> 12);
278189499Srnoland
279189499Srnoland	r600_vm_flush_gart_range(dev);
280189499Srnoland}
281189499Srnoland
282189499Srnoland/* load r600 microcode */
283189499Srnolandstatic void r600_cp_load_microcode(drm_radeon_private_t *dev_priv)
284189499Srnoland{
285189499Srnoland	int i;
286189499Srnoland
287189499Srnoland	r600_do_cp_stop(dev_priv);
288189499Srnoland
289189499Srnoland	RADEON_WRITE(R600_CP_RB_CNTL,
290189499Srnoland		     R600_RB_NO_UPDATE |
291189499Srnoland		     R600_RB_BLKSZ(15) |
292189499Srnoland		     R600_RB_BUFSZ(3));
293189499Srnoland
294189499Srnoland	RADEON_WRITE(R600_GRBM_SOFT_RESET, R600_SOFT_RESET_CP);
295189499Srnoland	RADEON_READ(R600_GRBM_SOFT_RESET);
296189499Srnoland	DRM_UDELAY(15000);
297189499Srnoland	RADEON_WRITE(R600_GRBM_SOFT_RESET, 0);
298189499Srnoland
299189499Srnoland	RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
300189499Srnoland
301189499Srnoland	if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R600)) {
302189499Srnoland		DRM_INFO("Loading R600 CP Microcode\n");
303189499Srnoland		for (i = 0; i < PM4_UCODE_SIZE; i++) {
304189499Srnoland			RADEON_WRITE(R600_CP_ME_RAM_DATA,
305189499Srnoland				     R600_cp_microcode[i][0]);
306189499Srnoland			RADEON_WRITE(R600_CP_ME_RAM_DATA,
307189499Srnoland				     R600_cp_microcode[i][1]);
308189499Srnoland			RADEON_WRITE(R600_CP_ME_RAM_DATA,
309189499Srnoland				     R600_cp_microcode[i][2]);
310189499Srnoland		}
311189499Srnoland
312189499Srnoland		RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
313189499Srnoland		DRM_INFO("Loading R600 PFP Microcode\n");
314189499Srnoland		for (i = 0; i < PFP_UCODE_SIZE; i++)
315189499Srnoland			RADEON_WRITE(R600_CP_PFP_UCODE_DATA, R600_pfp_microcode[i]);
316189499Srnoland	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV610)) {
317189499Srnoland		DRM_INFO("Loading RV610 CP Microcode\n");
318189499Srnoland		for (i = 0; i < PM4_UCODE_SIZE; i++) {
319189499Srnoland			RADEON_WRITE(R600_CP_ME_RAM_DATA,
320189499Srnoland				     RV610_cp_microcode[i][0]);
321189499Srnoland			RADEON_WRITE(R600_CP_ME_RAM_DATA,
322189499Srnoland				     RV610_cp_microcode[i][1]);
323189499Srnoland			RADEON_WRITE(R600_CP_ME_RAM_DATA,
324189499Srnoland				     RV610_cp_microcode[i][2]);
325189499Srnoland		}
326189499Srnoland
327189499Srnoland		RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
328189499Srnoland		DRM_INFO("Loading RV610 PFP Microcode\n");
329189499Srnoland		for (i = 0; i < PFP_UCODE_SIZE; i++)
330189499Srnoland			RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV610_pfp_microcode[i]);
331189499Srnoland	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV630)) {
332189499Srnoland		DRM_INFO("Loading RV630 CP Microcode\n");
333189499Srnoland		for (i = 0; i < PM4_UCODE_SIZE; i++) {
334189499Srnoland			RADEON_WRITE(R600_CP_ME_RAM_DATA,
335189499Srnoland				     RV630_cp_microcode[i][0]);
336189499Srnoland			RADEON_WRITE(R600_CP_ME_RAM_DATA,
337189499Srnoland				     RV630_cp_microcode[i][1]);
338189499Srnoland			RADEON_WRITE(R600_CP_ME_RAM_DATA,
339189499Srnoland				     RV630_cp_microcode[i][2]);
340189499Srnoland		}
341189499Srnoland
342189499Srnoland		RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
343189499Srnoland		DRM_INFO("Loading RV630 PFP Microcode\n");
344189499Srnoland		for (i = 0; i < PFP_UCODE_SIZE; i++)
345189499Srnoland			RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV630_pfp_microcode[i]);
346189499Srnoland	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV620)) {
347189499Srnoland		DRM_INFO("Loading RV620 CP Microcode\n");
348189499Srnoland		for (i = 0; i < PM4_UCODE_SIZE; i++) {
349189499Srnoland			RADEON_WRITE(R600_CP_ME_RAM_DATA,
350189499Srnoland				     RV620_cp_microcode[i][0]);
351189499Srnoland			RADEON_WRITE(R600_CP_ME_RAM_DATA,
352189499Srnoland				     RV620_cp_microcode[i][1]);
353189499Srnoland			RADEON_WRITE(R600_CP_ME_RAM_DATA,
354189499Srnoland				     RV620_cp_microcode[i][2]);
355189499Srnoland		}
356189499Srnoland
357189499Srnoland		RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
358189499Srnoland		DRM_INFO("Loading RV620 PFP Microcode\n");
359189499Srnoland		for (i = 0; i < PFP_UCODE_SIZE; i++)
360189499Srnoland			RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV620_pfp_microcode[i]);
361189499Srnoland	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV635)) {
362189499Srnoland		DRM_INFO("Loading RV635 CP Microcode\n");
363189499Srnoland		for (i = 0; i < PM4_UCODE_SIZE; i++) {
364189499Srnoland			RADEON_WRITE(R600_CP_ME_RAM_DATA,
365189499Srnoland				     RV635_cp_microcode[i][0]);
366189499Srnoland			RADEON_WRITE(R600_CP_ME_RAM_DATA,
367189499Srnoland				     RV635_cp_microcode[i][1]);
368189499Srnoland			RADEON_WRITE(R600_CP_ME_RAM_DATA,
369189499Srnoland				     RV635_cp_microcode[i][2]);
370189499Srnoland		}
371189499Srnoland
372189499Srnoland		RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
373189499Srnoland		DRM_INFO("Loading RV635 PFP Microcode\n");
374189499Srnoland		for (i = 0; i < PFP_UCODE_SIZE; i++)
375189499Srnoland			RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV635_pfp_microcode[i]);
376189499Srnoland	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV670)) {
377189499Srnoland		DRM_INFO("Loading RV670 CP Microcode\n");
378189499Srnoland		for (i = 0; i < PM4_UCODE_SIZE; i++) {
379189499Srnoland			RADEON_WRITE(R600_CP_ME_RAM_DATA,
380189499Srnoland				     RV670_cp_microcode[i][0]);
381189499Srnoland			RADEON_WRITE(R600_CP_ME_RAM_DATA,
382189499Srnoland				     RV670_cp_microcode[i][1]);
383189499Srnoland			RADEON_WRITE(R600_CP_ME_RAM_DATA,
384189499Srnoland				     RV670_cp_microcode[i][2]);
385189499Srnoland		}
386189499Srnoland
387189499Srnoland		RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
388189499Srnoland		DRM_INFO("Loading RV670 PFP Microcode\n");
389189499Srnoland		for (i = 0; i < PFP_UCODE_SIZE; i++)
390189499Srnoland			RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV670_pfp_microcode[i]);
391189499Srnoland	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780)) {
392189499Srnoland		DRM_INFO("Loading RS780 CP Microcode\n");
393189499Srnoland		for (i = 0; i < PM4_UCODE_SIZE; i++) {
394189499Srnoland			RADEON_WRITE(R600_CP_ME_RAM_DATA,
395189499Srnoland				     RV670_cp_microcode[i][0]);
396189499Srnoland			RADEON_WRITE(R600_CP_ME_RAM_DATA,
397189499Srnoland				     RV670_cp_microcode[i][1]);
398189499Srnoland			RADEON_WRITE(R600_CP_ME_RAM_DATA,
399189499Srnoland				     RV670_cp_microcode[i][2]);
400189499Srnoland		}
401189499Srnoland
402189499Srnoland		RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
403189499Srnoland		DRM_INFO("Loading RS780 PFP Microcode\n");
404189499Srnoland		for (i = 0; i < PFP_UCODE_SIZE; i++)
405189499Srnoland			RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV670_pfp_microcode[i]);
406189499Srnoland	}
407189499Srnoland	RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
408189499Srnoland	RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
409189499Srnoland	RADEON_WRITE(R600_CP_ME_RAM_RADDR, 0);
410189499Srnoland
411189499Srnoland}
412189499Srnoland
413189499Srnolandstatic void r700_vm_init(struct drm_device *dev)
414189499Srnoland{
415189499Srnoland	drm_radeon_private_t *dev_priv = dev->dev_private;
416189499Srnoland	/* initialise the VM to use the page table we constructed up there */
417189499Srnoland	u32 vm_c0, i;
418189499Srnoland	u32 mc_vm_md_l1;
419189499Srnoland	u32 vm_l2_cntl, vm_l2_cntl3;
420189499Srnoland	/* okay set up the PCIE aperture type thingo */
421189499Srnoland	RADEON_WRITE(R700_MC_VM_SYSTEM_APERTURE_LOW_ADDR, dev_priv->gart_vm_start >> 12);
422189499Srnoland	RADEON_WRITE(R700_MC_VM_SYSTEM_APERTURE_HIGH_ADDR, (dev_priv->gart_vm_start + dev_priv->gart_size - 1) >> 12);
423189499Srnoland	RADEON_WRITE(R700_MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, 0);
424189499Srnoland
425189499Srnoland	mc_vm_md_l1 = R700_ENABLE_L1_TLB |
426189499Srnoland	    R700_ENABLE_L1_FRAGMENT_PROCESSING |
427189499Srnoland	    R700_SYSTEM_ACCESS_MODE_IN_SYS |
428189499Srnoland	    R700_SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU |
429189499Srnoland	    R700_EFFECTIVE_L1_TLB_SIZE(5) |
430189499Srnoland	    R700_EFFECTIVE_L1_QUEUE_SIZE(5);
431189499Srnoland
432189499Srnoland	RADEON_WRITE(R700_MC_VM_MD_L1_TLB0_CNTL, mc_vm_md_l1);
433189499Srnoland	RADEON_WRITE(R700_MC_VM_MD_L1_TLB1_CNTL, mc_vm_md_l1);
434189499Srnoland	RADEON_WRITE(R700_MC_VM_MD_L1_TLB2_CNTL, mc_vm_md_l1);
435189499Srnoland	RADEON_WRITE(R700_MC_VM_MB_L1_TLB0_CNTL, mc_vm_md_l1);
436189499Srnoland	RADEON_WRITE(R700_MC_VM_MB_L1_TLB1_CNTL, mc_vm_md_l1);
437189499Srnoland	RADEON_WRITE(R700_MC_VM_MB_L1_TLB2_CNTL, mc_vm_md_l1);
438189499Srnoland	RADEON_WRITE(R700_MC_VM_MB_L1_TLB3_CNTL, mc_vm_md_l1);
439189499Srnoland
440189499Srnoland	vm_l2_cntl = R600_VM_L2_CACHE_EN | R600_VM_L2_FRAG_PROC | R600_VM_ENABLE_PTE_CACHE_LRU_W;
441189499Srnoland	vm_l2_cntl |= R700_VM_L2_CNTL_QUEUE_SIZE(7);
442189499Srnoland	RADEON_WRITE(R600_VM_L2_CNTL, vm_l2_cntl);
443189499Srnoland
444189499Srnoland	RADEON_WRITE(R600_VM_L2_CNTL2, 0);
445189499Srnoland	vm_l2_cntl3 = R700_VM_L2_CNTL3_BANK_SELECT(0) | R700_VM_L2_CNTL3_CACHE_UPDATE_MODE(2);
446189499Srnoland	RADEON_WRITE(R600_VM_L2_CNTL3, vm_l2_cntl3);
447189499Srnoland
448189499Srnoland	vm_c0 = R600_VM_ENABLE_CONTEXT | R600_VM_PAGE_TABLE_DEPTH_FLAT;
449189499Srnoland
450189499Srnoland	RADEON_WRITE(R600_VM_CONTEXT0_CNTL, vm_c0);
451189499Srnoland
452189499Srnoland	vm_c0 &= ~R600_VM_ENABLE_CONTEXT;
453189499Srnoland
454189499Srnoland	/* disable all other contexts */
455189499Srnoland	for (i = 1; i < 8; i++)
456189499Srnoland		RADEON_WRITE(R600_VM_CONTEXT0_CNTL + (i * 4), vm_c0);
457189499Srnoland
458189499Srnoland	RADEON_WRITE(R700_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, dev_priv->gart_info.bus_addr >> 12);
459189499Srnoland	RADEON_WRITE(R700_VM_CONTEXT0_PAGE_TABLE_START_ADDR, dev_priv->gart_vm_start >> 12);
460189499Srnoland	RADEON_WRITE(R700_VM_CONTEXT0_PAGE_TABLE_END_ADDR, (dev_priv->gart_vm_start + dev_priv->gart_size - 1) >> 12);
461189499Srnoland
462189499Srnoland	r600_vm_flush_gart_range(dev);
463189499Srnoland}
464189499Srnoland
465189499Srnoland/* load r600 microcode */
466189499Srnolandstatic void r700_cp_load_microcode(drm_radeon_private_t *dev_priv)
467189499Srnoland{
468189499Srnoland	int i;
469189499Srnoland
470189499Srnoland	r600_do_cp_stop(dev_priv);
471189499Srnoland
472189499Srnoland	RADEON_WRITE(R600_CP_RB_CNTL,
473189499Srnoland		     R600_RB_NO_UPDATE |
474189499Srnoland		     (15 << 8) |
475189499Srnoland		     (3 << 0));
476189499Srnoland
477189499Srnoland	RADEON_WRITE(R600_GRBM_SOFT_RESET, R600_SOFT_RESET_CP);
478189499Srnoland	RADEON_READ(R600_GRBM_SOFT_RESET);
479189499Srnoland	DRM_UDELAY(15000);
480189499Srnoland	RADEON_WRITE(R600_GRBM_SOFT_RESET, 0);
481189499Srnoland
482189499Srnoland
483189499Srnoland	if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV770)) {
484189499Srnoland		RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
485189499Srnoland		DRM_INFO("Loading RV770 PFP Microcode\n");
486189499Srnoland		for (i = 0; i < R700_PFP_UCODE_SIZE; i++)
487189499Srnoland			RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV770_pfp_microcode[i]);
488189499Srnoland		RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
489189499Srnoland
490189499Srnoland		RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
491189499Srnoland		DRM_INFO("Loading RV770 CP Microcode\n");
492189499Srnoland		for (i = 0; i < R700_PM4_UCODE_SIZE; i++)
493189499Srnoland			RADEON_WRITE(R600_CP_ME_RAM_DATA, RV770_cp_microcode[i]);
494189499Srnoland		RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
495189499Srnoland
496189499Srnoland	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV730)) {
497189499Srnoland		RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
498189499Srnoland		DRM_INFO("Loading RV730 PFP Microcode\n");
499189499Srnoland		for (i = 0; i < R700_PFP_UCODE_SIZE; i++)
500189499Srnoland			RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV730_pfp_microcode[i]);
501189499Srnoland		RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
502189499Srnoland
503189499Srnoland		RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
504189499Srnoland		DRM_INFO("Loading RV730 CP Microcode\n");
505189499Srnoland		for (i = 0; i < R700_PM4_UCODE_SIZE; i++)
506189499Srnoland			RADEON_WRITE(R600_CP_ME_RAM_DATA, RV730_cp_microcode[i]);
507189499Srnoland		RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
508189499Srnoland
509189499Srnoland	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV710)) {
510189499Srnoland		RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
511189499Srnoland		DRM_INFO("Loading RV710 PFP Microcode\n");
512189499Srnoland		for (i = 0; i < R700_PFP_UCODE_SIZE; i++)
513189499Srnoland			RADEON_WRITE(R600_CP_PFP_UCODE_DATA, RV710_pfp_microcode[i]);
514189499Srnoland		RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
515189499Srnoland
516189499Srnoland		RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
517189499Srnoland		DRM_INFO("Loading RV710 CP Microcode\n");
518189499Srnoland		for (i = 0; i < R700_PM4_UCODE_SIZE; i++)
519189499Srnoland			RADEON_WRITE(R600_CP_ME_RAM_DATA, RV710_cp_microcode[i]);
520189499Srnoland		RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
521189499Srnoland
522189499Srnoland	}
523189499Srnoland	RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
524189499Srnoland	RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
525189499Srnoland	RADEON_WRITE(R600_CP_ME_RAM_RADDR, 0);
526189499Srnoland
527189499Srnoland}
528189499Srnoland
529189499Srnolandstatic void r600_test_writeback(drm_radeon_private_t *dev_priv)
530189499Srnoland{
531189499Srnoland	u32 tmp;
532189499Srnoland
533189499Srnoland	/* Start with assuming that writeback doesn't work */
534189499Srnoland	dev_priv->writeback_works = 0;
535189499Srnoland
536189499Srnoland	/* Writeback doesn't seem to work everywhere, test it here and possibly
537189499Srnoland	 * enable it if it appears to work
538189499Srnoland	 */
539189499Srnoland	radeon_write_ring_rptr(dev_priv, R600_SCRATCHOFF(1), 0);
540189499Srnoland
541189499Srnoland	RADEON_WRITE(R600_SCRATCH_REG1, 0xdeadbeef);
542189499Srnoland
543189499Srnoland	for (tmp = 0; tmp < dev_priv->usec_timeout; tmp++) {
544189499Srnoland		u32 val;
545189499Srnoland
546189499Srnoland		val = radeon_read_ring_rptr(dev_priv, R600_SCRATCHOFF(1));
547189499Srnoland		if (val == 0xdeadbeef)
548189499Srnoland			break;
549189499Srnoland		DRM_UDELAY(1);
550189499Srnoland	}
551189499Srnoland
552189499Srnoland	if (tmp < dev_priv->usec_timeout) {
553189499Srnoland		dev_priv->writeback_works = 1;
554189499Srnoland		DRM_INFO("writeback test succeeded in %d usecs\n", tmp);
555189499Srnoland	} else {
556189499Srnoland		dev_priv->writeback_works = 0;
557189499Srnoland		DRM_INFO("writeback test failed\n");
558189499Srnoland	}
559189499Srnoland	if (radeon_no_wb == 1) {
560189499Srnoland		dev_priv->writeback_works = 0;
561189499Srnoland		DRM_INFO("writeback forced off\n");
562189499Srnoland	}
563189499Srnoland
564189499Srnoland	if (!dev_priv->writeback_works) {
565189499Srnoland		/* Disable writeback to avoid unnecessary bus master transfer */
566189499Srnoland		RADEON_WRITE(R600_CP_RB_CNTL, RADEON_READ(R600_CP_RB_CNTL) |
567189499Srnoland			     RADEON_RB_NO_UPDATE);
568189499Srnoland		RADEON_WRITE(R600_SCRATCH_UMSK, 0);
569189499Srnoland	}
570189499Srnoland}
571189499Srnoland
572189499Srnolandint r600_do_engine_reset(struct drm_device *dev)
573189499Srnoland{
574189499Srnoland	drm_radeon_private_t *dev_priv = dev->dev_private;
575189499Srnoland	u32 cp_ptr, cp_me_cntl, cp_rb_cntl;
576189499Srnoland
577189499Srnoland	DRM_INFO("Resetting GPU\n");
578189499Srnoland
579189499Srnoland	cp_ptr = RADEON_READ(R600_CP_RB_WPTR);
580189499Srnoland	cp_me_cntl = RADEON_READ(R600_CP_ME_CNTL);
581189499Srnoland	RADEON_WRITE(R600_CP_ME_CNTL, R600_CP_ME_HALT);
582189499Srnoland
583189499Srnoland	RADEON_WRITE(R600_GRBM_SOFT_RESET, 0x7fff);
584189499Srnoland	RADEON_READ(R600_GRBM_SOFT_RESET);
585189499Srnoland	DRM_UDELAY(50);
586189499Srnoland	RADEON_WRITE(R600_GRBM_SOFT_RESET, 0);
587189499Srnoland	RADEON_READ(R600_GRBM_SOFT_RESET);
588189499Srnoland
589189499Srnoland	RADEON_WRITE(R600_CP_RB_WPTR_DELAY, 0);
590189499Srnoland	cp_rb_cntl = RADEON_READ(R600_CP_RB_CNTL);
591189499Srnoland	RADEON_WRITE(R600_CP_RB_CNTL, R600_RB_RPTR_WR_ENA);
592189499Srnoland
593189499Srnoland	RADEON_WRITE(R600_CP_RB_RPTR_WR, cp_ptr);
594189499Srnoland	RADEON_WRITE(R600_CP_RB_WPTR, cp_ptr);
595189499Srnoland	RADEON_WRITE(R600_CP_RB_CNTL, cp_rb_cntl);
596189499Srnoland	RADEON_WRITE(R600_CP_ME_CNTL, cp_me_cntl);
597189499Srnoland
598189499Srnoland	/* Reset the CP ring */
599189499Srnoland	r600_do_cp_reset(dev_priv);
600189499Srnoland
601189499Srnoland	/* The CP is no longer running after an engine reset */
602189499Srnoland	dev_priv->cp_running = 0;
603189499Srnoland
604189499Srnoland	/* Reset any pending vertex, indirect buffers */
605189499Srnoland	radeon_freelist_reset(dev);
606189499Srnoland
607189499Srnoland	return 0;
608189499Srnoland
609189499Srnoland}
610189499Srnoland
611189499Srnolandstatic u32 r600_get_tile_pipe_to_backend_map(u32 num_tile_pipes,
612189499Srnoland					     u32 num_backends,
613189499Srnoland					     u32 backend_disable_mask)
614189499Srnoland{
615189499Srnoland	u32 backend_map = 0;
616189499Srnoland	u32 enabled_backends_mask;
617189499Srnoland	u32 enabled_backends_count;
618189499Srnoland	u32 cur_pipe;
619189499Srnoland	u32 swizzle_pipe[R6XX_MAX_PIPES];
620189499Srnoland	u32 cur_backend;
621189499Srnoland	u32 i;
622189499Srnoland
623189499Srnoland	if (num_tile_pipes > R6XX_MAX_PIPES)
624189499Srnoland		num_tile_pipes = R6XX_MAX_PIPES;
625189499Srnoland	if (num_tile_pipes < 1)
626189499Srnoland		num_tile_pipes = 1;
627189499Srnoland	if (num_backends > R6XX_MAX_BACKENDS)
628189499Srnoland		num_backends = R6XX_MAX_BACKENDS;
629189499Srnoland	if (num_backends < 1)
630189499Srnoland		num_backends = 1;
631189499Srnoland
632189499Srnoland	enabled_backends_mask = 0;
633189499Srnoland	enabled_backends_count = 0;
634189499Srnoland	for (i = 0; i < R6XX_MAX_BACKENDS; ++i) {
635189499Srnoland		if (((backend_disable_mask >> i) & 1) == 0) {
636189499Srnoland			enabled_backends_mask |= (1 << i);
637189499Srnoland			++enabled_backends_count;
638189499Srnoland		}
639189499Srnoland		if (enabled_backends_count == num_backends)
640189499Srnoland			break;
641189499Srnoland	}
642189499Srnoland
643189499Srnoland	if (enabled_backends_count == 0) {
644189499Srnoland		enabled_backends_mask = 1;
645189499Srnoland		enabled_backends_count = 1;
646189499Srnoland	}
647189499Srnoland
648189499Srnoland	if (enabled_backends_count != num_backends)
649189499Srnoland		num_backends = enabled_backends_count;
650189499Srnoland
651189499Srnoland	memset((uint8_t *)&swizzle_pipe[0], 0, sizeof(u32) * R6XX_MAX_PIPES);
652189499Srnoland	switch (num_tile_pipes) {
653189499Srnoland	case 1:
654189499Srnoland		swizzle_pipe[0] = 0;
655189499Srnoland		break;
656189499Srnoland	case 2:
657189499Srnoland		swizzle_pipe[0] = 0;
658189499Srnoland		swizzle_pipe[1] = 1;
659189499Srnoland		break;
660189499Srnoland	case 3:
661189499Srnoland		swizzle_pipe[0] = 0;
662189499Srnoland		swizzle_pipe[1] = 1;
663189499Srnoland		swizzle_pipe[2] = 2;
664189499Srnoland		break;
665189499Srnoland	case 4:
666189499Srnoland		swizzle_pipe[0] = 0;
667189499Srnoland		swizzle_pipe[1] = 1;
668189499Srnoland		swizzle_pipe[2] = 2;
669189499Srnoland		swizzle_pipe[3] = 3;
670189499Srnoland		break;
671189499Srnoland	case 5:
672189499Srnoland		swizzle_pipe[0] = 0;
673189499Srnoland		swizzle_pipe[1] = 1;
674189499Srnoland		swizzle_pipe[2] = 2;
675189499Srnoland		swizzle_pipe[3] = 3;
676189499Srnoland		swizzle_pipe[4] = 4;
677189499Srnoland		break;
678189499Srnoland	case 6:
679189499Srnoland		swizzle_pipe[0] = 0;
680189499Srnoland		swizzle_pipe[1] = 2;
681189499Srnoland		swizzle_pipe[2] = 4;
682189499Srnoland		swizzle_pipe[3] = 5;
683189499Srnoland		swizzle_pipe[4] = 1;
684189499Srnoland		swizzle_pipe[5] = 3;
685189499Srnoland		break;
686189499Srnoland	case 7:
687189499Srnoland		swizzle_pipe[0] = 0;
688189499Srnoland		swizzle_pipe[1] = 2;
689189499Srnoland		swizzle_pipe[2] = 4;
690189499Srnoland		swizzle_pipe[3] = 6;
691189499Srnoland		swizzle_pipe[4] = 1;
692189499Srnoland		swizzle_pipe[5] = 3;
693189499Srnoland		swizzle_pipe[6] = 5;
694189499Srnoland		break;
695189499Srnoland	case 8:
696189499Srnoland		swizzle_pipe[0] = 0;
697189499Srnoland		swizzle_pipe[1] = 2;
698189499Srnoland		swizzle_pipe[2] = 4;
699189499Srnoland		swizzle_pipe[3] = 6;
700189499Srnoland		swizzle_pipe[4] = 1;
701189499Srnoland		swizzle_pipe[5] = 3;
702189499Srnoland		swizzle_pipe[6] = 5;
703189499Srnoland		swizzle_pipe[7] = 7;
704189499Srnoland		break;
705189499Srnoland	}
706189499Srnoland
707189499Srnoland	cur_backend = 0;
708189499Srnoland	for (cur_pipe = 0; cur_pipe < num_tile_pipes; ++cur_pipe) {
709189499Srnoland		while (((1 << cur_backend) & enabled_backends_mask) == 0)
710189499Srnoland			cur_backend = (cur_backend + 1) % R6XX_MAX_BACKENDS;
711189499Srnoland
712189499Srnoland		backend_map |= (u32)(((cur_backend & 3) << (swizzle_pipe[cur_pipe] * 2)));
713189499Srnoland
714189499Srnoland		cur_backend = (cur_backend + 1) % R6XX_MAX_BACKENDS;
715189499Srnoland	}
716189499Srnoland
717189499Srnoland	return backend_map;
718189499Srnoland}
719189499Srnoland
720189499Srnolandstatic int r600_count_pipe_bits(uint32_t val)
721189499Srnoland{
722189499Srnoland	int i, ret = 0;
723189499Srnoland	for (i = 0; i < 32; i++) {
724189499Srnoland		ret += val & 1;
725189499Srnoland		val >>= 1;
726189499Srnoland	}
727189499Srnoland	return ret;
728189499Srnoland}
729189499Srnoland
730189499Srnolandstatic void r600_gfx_init(struct drm_device *dev,
731189499Srnoland			  drm_radeon_private_t *dev_priv)
732189499Srnoland{
733189499Srnoland	int i, j, num_qd_pipes;
734189499Srnoland	u32 sx_debug_1;
735189499Srnoland	u32 tc_cntl;
736189499Srnoland	u32 arb_pop;
737189499Srnoland	u32 num_gs_verts_per_thread;
738189499Srnoland	u32 vgt_gs_per_es;
739189499Srnoland	u32 gs_prim_buffer_depth = 0;
740189499Srnoland	u32 sq_ms_fifo_sizes;
741189499Srnoland	u32 sq_config;
742189499Srnoland	u32 sq_gpr_resource_mgmt_1 = 0;
743189499Srnoland	u32 sq_gpr_resource_mgmt_2 = 0;
744189499Srnoland	u32 sq_thread_resource_mgmt = 0;
745189499Srnoland	u32 sq_stack_resource_mgmt_1 = 0;
746189499Srnoland	u32 sq_stack_resource_mgmt_2 = 0;
747189499Srnoland	u32 hdp_host_path_cntl;
748189499Srnoland	u32 backend_map;
749189499Srnoland	u32 gb_tiling_config = 0;
750189499Srnoland	u32 cc_rb_backend_disable = 0;
751189499Srnoland	u32 cc_gc_shader_pipe_config = 0;
752189499Srnoland	u32 ramcfg;
753189499Srnoland
754189499Srnoland	/* setup chip specs */
755189499Srnoland	switch (dev_priv->flags & RADEON_FAMILY_MASK) {
756189499Srnoland	case CHIP_R600:
757189499Srnoland		dev_priv->r600_max_pipes = 4;
758189499Srnoland		dev_priv->r600_max_tile_pipes = 8;
759189499Srnoland		dev_priv->r600_max_simds = 4;
760189499Srnoland		dev_priv->r600_max_backends = 4;
761189499Srnoland		dev_priv->r600_max_gprs = 256;
762189499Srnoland		dev_priv->r600_max_threads = 192;
763189499Srnoland		dev_priv->r600_max_stack_entries = 256;
764189499Srnoland		dev_priv->r600_max_hw_contexts = 8;
765189499Srnoland		dev_priv->r600_max_gs_threads = 16;
766189499Srnoland		dev_priv->r600_sx_max_export_size = 128;
767189499Srnoland		dev_priv->r600_sx_max_export_pos_size = 16;
768189499Srnoland		dev_priv->r600_sx_max_export_smx_size = 128;
769189499Srnoland		dev_priv->r600_sq_num_cf_insts = 2;
770189499Srnoland		break;
771189499Srnoland	case CHIP_RV630:
772189499Srnoland	case CHIP_RV635:
773189499Srnoland		dev_priv->r600_max_pipes = 2;
774189499Srnoland		dev_priv->r600_max_tile_pipes = 2;
775189499Srnoland		dev_priv->r600_max_simds = 3;
776189499Srnoland		dev_priv->r600_max_backends = 1;
777189499Srnoland		dev_priv->r600_max_gprs = 128;
778189499Srnoland		dev_priv->r600_max_threads = 192;
779189499Srnoland		dev_priv->r600_max_stack_entries = 128;
780189499Srnoland		dev_priv->r600_max_hw_contexts = 8;
781189499Srnoland		dev_priv->r600_max_gs_threads = 4;
782189499Srnoland		dev_priv->r600_sx_max_export_size = 128;
783189499Srnoland		dev_priv->r600_sx_max_export_pos_size = 16;
784189499Srnoland		dev_priv->r600_sx_max_export_smx_size = 128;
785189499Srnoland		dev_priv->r600_sq_num_cf_insts = 2;
786189499Srnoland		break;
787189499Srnoland	case CHIP_RV610:
788189499Srnoland	case CHIP_RS780:
789189499Srnoland	case CHIP_RV620:
790189499Srnoland		dev_priv->r600_max_pipes = 1;
791189499Srnoland		dev_priv->r600_max_tile_pipes = 1;
792189499Srnoland		dev_priv->r600_max_simds = 2;
793189499Srnoland		dev_priv->r600_max_backends = 1;
794189499Srnoland		dev_priv->r600_max_gprs = 128;
795189499Srnoland		dev_priv->r600_max_threads = 192;
796189499Srnoland		dev_priv->r600_max_stack_entries = 128;
797189499Srnoland		dev_priv->r600_max_hw_contexts = 4;
798189499Srnoland		dev_priv->r600_max_gs_threads = 4;
799189499Srnoland		dev_priv->r600_sx_max_export_size = 128;
800189499Srnoland		dev_priv->r600_sx_max_export_pos_size = 16;
801189499Srnoland		dev_priv->r600_sx_max_export_smx_size = 128;
802189499Srnoland		dev_priv->r600_sq_num_cf_insts = 1;
803189499Srnoland		break;
804189499Srnoland	case CHIP_RV670:
805189499Srnoland		dev_priv->r600_max_pipes = 4;
806189499Srnoland		dev_priv->r600_max_tile_pipes = 4;
807189499Srnoland		dev_priv->r600_max_simds = 4;
808189499Srnoland		dev_priv->r600_max_backends = 4;
809189499Srnoland		dev_priv->r600_max_gprs = 192;
810189499Srnoland		dev_priv->r600_max_threads = 192;
811189499Srnoland		dev_priv->r600_max_stack_entries = 256;
812189499Srnoland		dev_priv->r600_max_hw_contexts = 8;
813189499Srnoland		dev_priv->r600_max_gs_threads = 16;
814189499Srnoland		dev_priv->r600_sx_max_export_size = 128;
815189499Srnoland		dev_priv->r600_sx_max_export_pos_size = 16;
816189499Srnoland		dev_priv->r600_sx_max_export_smx_size = 128;
817189499Srnoland		dev_priv->r600_sq_num_cf_insts = 2;
818189499Srnoland		break;
819189499Srnoland	default:
820189499Srnoland		break;
821189499Srnoland	}
822189499Srnoland
823189499Srnoland	/* Initialize HDP */
824189499Srnoland	j = 0;
825189499Srnoland	for (i = 0; i < 32; i++) {
826189499Srnoland		RADEON_WRITE((0x2c14 + j), 0x00000000);
827189499Srnoland		RADEON_WRITE((0x2c18 + j), 0x00000000);
828189499Srnoland		RADEON_WRITE((0x2c1c + j), 0x00000000);
829189499Srnoland		RADEON_WRITE((0x2c20 + j), 0x00000000);
830189499Srnoland		RADEON_WRITE((0x2c24 + j), 0x00000000);
831189499Srnoland		j += 0x18;
832189499Srnoland	}
833189499Srnoland
834189499Srnoland	RADEON_WRITE(R600_GRBM_CNTL, R600_GRBM_READ_TIMEOUT(0xff));
835189499Srnoland
836189499Srnoland	/* setup tiling, simd, pipe config */
837189499Srnoland	ramcfg = RADEON_READ(R600_RAMCFG);
838189499Srnoland
839189499Srnoland	switch (dev_priv->r600_max_tile_pipes) {
840189499Srnoland	case 1:
841189499Srnoland		gb_tiling_config |= R600_PIPE_TILING(0);
842189499Srnoland		break;
843189499Srnoland	case 2:
844189499Srnoland		gb_tiling_config |= R600_PIPE_TILING(1);
845189499Srnoland		break;
846189499Srnoland	case 4:
847189499Srnoland		gb_tiling_config |= R600_PIPE_TILING(2);
848189499Srnoland		break;
849189499Srnoland	case 8:
850189499Srnoland		gb_tiling_config |= R600_PIPE_TILING(3);
851189499Srnoland		break;
852189499Srnoland	default:
853189499Srnoland		break;
854189499Srnoland	}
855189499Srnoland
856189499Srnoland	gb_tiling_config |= R600_BANK_TILING((ramcfg >> R600_NOOFBANK_SHIFT) & R600_NOOFBANK_MASK);
857189499Srnoland
858189499Srnoland	gb_tiling_config |= R600_GROUP_SIZE(0);
859189499Srnoland
860189499Srnoland	if (((ramcfg >> R600_NOOFROWS_SHIFT) & R600_NOOFROWS_MASK) > 3) {
861189499Srnoland		gb_tiling_config |= R600_ROW_TILING(3);
862189499Srnoland		gb_tiling_config |= R600_SAMPLE_SPLIT(3);
863189499Srnoland	} else {
864189499Srnoland		gb_tiling_config |=
865189499Srnoland			R600_ROW_TILING(((ramcfg >> R600_NOOFROWS_SHIFT) & R600_NOOFROWS_MASK));
866189499Srnoland		gb_tiling_config |=
867189499Srnoland			R600_SAMPLE_SPLIT(((ramcfg >> R600_NOOFROWS_SHIFT) & R600_NOOFROWS_MASK));
868189499Srnoland	}
869189499Srnoland
870189499Srnoland	gb_tiling_config |= R600_BANK_SWAPS(1);
871189499Srnoland
872189499Srnoland	backend_map = r600_get_tile_pipe_to_backend_map(dev_priv->r600_max_tile_pipes,
873189499Srnoland							dev_priv->r600_max_backends,
874189499Srnoland							(0xff << dev_priv->r600_max_backends) & 0xff);
875189499Srnoland	gb_tiling_config |= R600_BACKEND_MAP(backend_map);
876189499Srnoland
877189499Srnoland	cc_gc_shader_pipe_config =
878189499Srnoland		R600_INACTIVE_QD_PIPES((R6XX_MAX_PIPES_MASK << dev_priv->r600_max_pipes) & R6XX_MAX_PIPES_MASK);
879189499Srnoland	cc_gc_shader_pipe_config |=
880189499Srnoland		R600_INACTIVE_SIMDS((R6XX_MAX_SIMDS_MASK << dev_priv->r600_max_simds) & R6XX_MAX_SIMDS_MASK);
881189499Srnoland
882189499Srnoland	cc_rb_backend_disable =
883189499Srnoland		R600_BACKEND_DISABLE((R6XX_MAX_BACKENDS_MASK << dev_priv->r600_max_backends) & R6XX_MAX_BACKENDS_MASK);
884189499Srnoland
885189499Srnoland	RADEON_WRITE(R600_GB_TILING_CONFIG,      gb_tiling_config);
886189499Srnoland	RADEON_WRITE(R600_DCP_TILING_CONFIG,    (gb_tiling_config & 0xffff));
887189499Srnoland	RADEON_WRITE(R600_HDP_TILING_CONFIG,    (gb_tiling_config & 0xffff));
888189499Srnoland
889189499Srnoland	RADEON_WRITE(R600_CC_RB_BACKEND_DISABLE,      cc_rb_backend_disable);
890189499Srnoland	RADEON_WRITE(R600_CC_GC_SHADER_PIPE_CONFIG,   cc_gc_shader_pipe_config);
891189499Srnoland	RADEON_WRITE(R600_GC_USER_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config);
892189499Srnoland
893189499Srnoland	num_qd_pipes =
894189499Srnoland		R6XX_MAX_BACKENDS - r600_count_pipe_bits(cc_gc_shader_pipe_config & R600_INACTIVE_QD_PIPES_MASK);
895189499Srnoland	RADEON_WRITE(R600_VGT_OUT_DEALLOC_CNTL, (num_qd_pipes * 4) & R600_DEALLOC_DIST_MASK);
896189499Srnoland	RADEON_WRITE(R600_VGT_VERTEX_REUSE_BLOCK_CNTL, ((num_qd_pipes * 4) - 2) & R600_VTX_REUSE_DEPTH_MASK);
897189499Srnoland
898189499Srnoland	/* set HW defaults for 3D engine */
899189499Srnoland	RADEON_WRITE(R600_CP_QUEUE_THRESHOLDS, (R600_ROQ_IB1_START(0x16) |
900189499Srnoland						R600_ROQ_IB2_START(0x2b)));
901189499Srnoland
902189499Srnoland	RADEON_WRITE(R600_CP_MEQ_THRESHOLDS, (R600_MEQ_END(0x40) |
903189499Srnoland					      R600_ROQ_END(0x40)));
904189499Srnoland
905189499Srnoland	RADEON_WRITE(R600_TA_CNTL_AUX, (R600_DISABLE_CUBE_ANISO |
906189499Srnoland					R600_SYNC_GRADIENT |
907189499Srnoland					R600_SYNC_WALKER |
908189499Srnoland					R600_SYNC_ALIGNER));
909189499Srnoland
910189499Srnoland	if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV670)
911189499Srnoland		RADEON_WRITE(R600_ARB_GDEC_RD_CNTL, 0x00000021);
912189499Srnoland
913189499Srnoland	sx_debug_1 = RADEON_READ(R600_SX_DEBUG_1);
914189499Srnoland	sx_debug_1 |= R600_SMX_EVENT_RELEASE;
915189499Srnoland	if (((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_R600))
916189499Srnoland		sx_debug_1 |= R600_ENABLE_NEW_SMX_ADDRESS;
917189499Srnoland	RADEON_WRITE(R600_SX_DEBUG_1, sx_debug_1);
918189499Srnoland
919189499Srnoland	if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R600) ||
920189499Srnoland	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV630) ||
921189499Srnoland	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV610) ||
922189499Srnoland	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV620) ||
923189499Srnoland	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780))
924189499Srnoland		RADEON_WRITE(R600_DB_DEBUG, R600_PREZ_MUST_WAIT_FOR_POSTZ_DONE);
925189499Srnoland	else
926189499Srnoland		RADEON_WRITE(R600_DB_DEBUG, 0);
927189499Srnoland
928189499Srnoland	RADEON_WRITE(R600_DB_WATERMARKS, (R600_DEPTH_FREE(4) |
929189499Srnoland					  R600_DEPTH_FLUSH(16) |
930189499Srnoland					  R600_DEPTH_PENDING_FREE(4) |
931189499Srnoland					  R600_DEPTH_CACHELINE_FREE(16)));
932189499Srnoland	RADEON_WRITE(R600_PA_SC_MULTI_CHIP_CNTL, 0);
933189499Srnoland	RADEON_WRITE(R600_VGT_NUM_INSTANCES, 0);
934189499Srnoland
935189499Srnoland	RADEON_WRITE(R600_SPI_CONFIG_CNTL, R600_GPR_WRITE_PRIORITY(0));
936189499Srnoland	RADEON_WRITE(R600_SPI_CONFIG_CNTL_1, R600_VTX_DONE_DELAY(0));
937189499Srnoland
938189499Srnoland	sq_ms_fifo_sizes = RADEON_READ(R600_SQ_MS_FIFO_SIZES);
939189499Srnoland	if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV610) ||
940189499Srnoland	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV620) ||
941189499Srnoland	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780)) {
942189499Srnoland		sq_ms_fifo_sizes = (R600_CACHE_FIFO_SIZE(0xa) |
943189499Srnoland				    R600_FETCH_FIFO_HIWATER(0xa) |
944189499Srnoland				    R600_DONE_FIFO_HIWATER(0xe0) |
945189499Srnoland				    R600_ALU_UPDATE_FIFO_HIWATER(0x8));
946189499Srnoland	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R600) ||
947189499Srnoland		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV630)) {
948189499Srnoland		sq_ms_fifo_sizes &= ~R600_DONE_FIFO_HIWATER(0xff);
949189499Srnoland		sq_ms_fifo_sizes |= R600_DONE_FIFO_HIWATER(0x4);
950189499Srnoland	}
951189499Srnoland	RADEON_WRITE(R600_SQ_MS_FIFO_SIZES, sq_ms_fifo_sizes);
952189499Srnoland
953189499Srnoland	/* SQ_CONFIG, SQ_GPR_RESOURCE_MGMT, SQ_THREAD_RESOURCE_MGMT, SQ_STACK_RESOURCE_MGMT
954189499Srnoland	 * should be adjusted as needed by the 2D/3D drivers.  This just sets default values
955189499Srnoland	 */
956189499Srnoland	sq_config = RADEON_READ(R600_SQ_CONFIG);
957189499Srnoland	sq_config &= ~(R600_PS_PRIO(3) |
958189499Srnoland		       R600_VS_PRIO(3) |
959189499Srnoland		       R600_GS_PRIO(3) |
960189499Srnoland		       R600_ES_PRIO(3));
961189499Srnoland	sq_config |= (R600_DX9_CONSTS |
962189499Srnoland		      R600_VC_ENABLE |
963189499Srnoland		      R600_PS_PRIO(0) |
964189499Srnoland		      R600_VS_PRIO(1) |
965189499Srnoland		      R600_GS_PRIO(2) |
966189499Srnoland		      R600_ES_PRIO(3));
967189499Srnoland
968189499Srnoland	if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R600) {
969189499Srnoland		sq_gpr_resource_mgmt_1 = (R600_NUM_PS_GPRS(124) |
970189499Srnoland					  R600_NUM_VS_GPRS(124) |
971189499Srnoland					  R600_NUM_CLAUSE_TEMP_GPRS(4));
972189499Srnoland		sq_gpr_resource_mgmt_2 = (R600_NUM_GS_GPRS(0) |
973189499Srnoland					  R600_NUM_ES_GPRS(0));
974189499Srnoland		sq_thread_resource_mgmt = (R600_NUM_PS_THREADS(136) |
975189499Srnoland					   R600_NUM_VS_THREADS(48) |
976189499Srnoland					   R600_NUM_GS_THREADS(4) |
977189499Srnoland					   R600_NUM_ES_THREADS(4));
978189499Srnoland		sq_stack_resource_mgmt_1 = (R600_NUM_PS_STACK_ENTRIES(128) |
979189499Srnoland					    R600_NUM_VS_STACK_ENTRIES(128));
980189499Srnoland		sq_stack_resource_mgmt_2 = (R600_NUM_GS_STACK_ENTRIES(0) |
981189499Srnoland					    R600_NUM_ES_STACK_ENTRIES(0));
982189499Srnoland	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV610) ||
983189499Srnoland		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV620) ||
984189499Srnoland		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780)) {
985189499Srnoland		/* no vertex cache */
986189499Srnoland		sq_config &= ~R600_VC_ENABLE;
987189499Srnoland
988189499Srnoland		sq_gpr_resource_mgmt_1 = (R600_NUM_PS_GPRS(44) |
989189499Srnoland					  R600_NUM_VS_GPRS(44) |
990189499Srnoland					  R600_NUM_CLAUSE_TEMP_GPRS(2));
991189499Srnoland		sq_gpr_resource_mgmt_2 = (R600_NUM_GS_GPRS(17) |
992189499Srnoland					  R600_NUM_ES_GPRS(17));
993189499Srnoland		sq_thread_resource_mgmt = (R600_NUM_PS_THREADS(79) |
994189499Srnoland					   R600_NUM_VS_THREADS(78) |
995189499Srnoland					   R600_NUM_GS_THREADS(4) |
996189499Srnoland					   R600_NUM_ES_THREADS(31));
997189499Srnoland		sq_stack_resource_mgmt_1 = (R600_NUM_PS_STACK_ENTRIES(40) |
998189499Srnoland					    R600_NUM_VS_STACK_ENTRIES(40));
999189499Srnoland		sq_stack_resource_mgmt_2 = (R600_NUM_GS_STACK_ENTRIES(32) |
1000189499Srnoland					    R600_NUM_ES_STACK_ENTRIES(16));
1001189499Srnoland	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV630) ||
1002189499Srnoland		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV635)) {
1003189499Srnoland		sq_gpr_resource_mgmt_1 = (R600_NUM_PS_GPRS(44) |
1004189499Srnoland					  R600_NUM_VS_GPRS(44) |
1005189499Srnoland					  R600_NUM_CLAUSE_TEMP_GPRS(2));
1006189499Srnoland		sq_gpr_resource_mgmt_2 = (R600_NUM_GS_GPRS(18) |
1007189499Srnoland					  R600_NUM_ES_GPRS(18));
1008189499Srnoland		sq_thread_resource_mgmt = (R600_NUM_PS_THREADS(79) |
1009189499Srnoland					   R600_NUM_VS_THREADS(78) |
1010189499Srnoland					   R600_NUM_GS_THREADS(4) |
1011189499Srnoland					   R600_NUM_ES_THREADS(31));
1012189499Srnoland		sq_stack_resource_mgmt_1 = (R600_NUM_PS_STACK_ENTRIES(40) |
1013189499Srnoland					    R600_NUM_VS_STACK_ENTRIES(40));
1014189499Srnoland		sq_stack_resource_mgmt_2 = (R600_NUM_GS_STACK_ENTRIES(32) |
1015189499Srnoland					    R600_NUM_ES_STACK_ENTRIES(16));
1016189499Srnoland	} else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV670) {
1017189499Srnoland		sq_gpr_resource_mgmt_1 = (R600_NUM_PS_GPRS(44) |
1018189499Srnoland					  R600_NUM_VS_GPRS(44) |
1019189499Srnoland					  R600_NUM_CLAUSE_TEMP_GPRS(2));
1020189499Srnoland		sq_gpr_resource_mgmt_2 = (R600_NUM_GS_GPRS(17) |
1021189499Srnoland					  R600_NUM_ES_GPRS(17));
1022189499Srnoland		sq_thread_resource_mgmt = (R600_NUM_PS_THREADS(79) |
1023189499Srnoland					   R600_NUM_VS_THREADS(78) |
1024189499Srnoland					   R600_NUM_GS_THREADS(4) |
1025189499Srnoland					   R600_NUM_ES_THREADS(31));
1026189499Srnoland		sq_stack_resource_mgmt_1 = (R600_NUM_PS_STACK_ENTRIES(64) |
1027189499Srnoland					    R600_NUM_VS_STACK_ENTRIES(64));
1028189499Srnoland		sq_stack_resource_mgmt_2 = (R600_NUM_GS_STACK_ENTRIES(64) |
1029189499Srnoland					    R600_NUM_ES_STACK_ENTRIES(64));
1030189499Srnoland	}
1031189499Srnoland
1032189499Srnoland	RADEON_WRITE(R600_SQ_CONFIG, sq_config);
1033189499Srnoland	RADEON_WRITE(R600_SQ_GPR_RESOURCE_MGMT_1,  sq_gpr_resource_mgmt_1);
1034189499Srnoland	RADEON_WRITE(R600_SQ_GPR_RESOURCE_MGMT_2,  sq_gpr_resource_mgmt_2);
1035189499Srnoland	RADEON_WRITE(R600_SQ_THREAD_RESOURCE_MGMT, sq_thread_resource_mgmt);
1036189499Srnoland	RADEON_WRITE(R600_SQ_STACK_RESOURCE_MGMT_1, sq_stack_resource_mgmt_1);
1037189499Srnoland	RADEON_WRITE(R600_SQ_STACK_RESOURCE_MGMT_2, sq_stack_resource_mgmt_2);
1038189499Srnoland
1039189499Srnoland	if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV610) ||
1040189499Srnoland	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV620) ||
1041189499Srnoland	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780))
1042189499Srnoland		RADEON_WRITE(R600_VGT_CACHE_INVALIDATION, R600_CACHE_INVALIDATION(R600_TC_ONLY));
1043189499Srnoland	else
1044189499Srnoland		RADEON_WRITE(R600_VGT_CACHE_INVALIDATION, R600_CACHE_INVALIDATION(R600_VC_AND_TC));
1045189499Srnoland
1046189499Srnoland	RADEON_WRITE(R600_PA_SC_AA_SAMPLE_LOCS_2S, (R600_S0_X(0xc) |
1047189499Srnoland						    R600_S0_Y(0x4) |
1048189499Srnoland						    R600_S1_X(0x4) |
1049189499Srnoland						    R600_S1_Y(0xc)));
1050189499Srnoland	RADEON_WRITE(R600_PA_SC_AA_SAMPLE_LOCS_4S, (R600_S0_X(0xe) |
1051189499Srnoland						    R600_S0_Y(0xe) |
1052189499Srnoland						    R600_S1_X(0x2) |
1053189499Srnoland						    R600_S1_Y(0x2) |
1054189499Srnoland						    R600_S2_X(0xa) |
1055189499Srnoland						    R600_S2_Y(0x6) |
1056189499Srnoland						    R600_S3_X(0x6) |
1057189499Srnoland						    R600_S3_Y(0xa)));
1058189499Srnoland	RADEON_WRITE(R600_PA_SC_AA_SAMPLE_LOCS_8S_WD0, (R600_S0_X(0xe) |
1059189499Srnoland							R600_S0_Y(0xb) |
1060189499Srnoland							R600_S1_X(0x4) |
1061189499Srnoland							R600_S1_Y(0xc) |
1062189499Srnoland							R600_S2_X(0x1) |
1063189499Srnoland							R600_S2_Y(0x6) |
1064189499Srnoland							R600_S3_X(0xa) |
1065189499Srnoland							R600_S3_Y(0xe)));
1066189499Srnoland	RADEON_WRITE(R600_PA_SC_AA_SAMPLE_LOCS_8S_WD1, (R600_S4_X(0x6) |
1067189499Srnoland							R600_S4_Y(0x1) |
1068189499Srnoland							R600_S5_X(0x0) |
1069189499Srnoland							R600_S5_Y(0x0) |
1070189499Srnoland							R600_S6_X(0xb) |
1071189499Srnoland							R600_S6_Y(0x4) |
1072189499Srnoland							R600_S7_X(0x7) |
1073189499Srnoland							R600_S7_Y(0x8)));
1074189499Srnoland
1075189499Srnoland
1076189499Srnoland	switch (dev_priv->flags & RADEON_FAMILY_MASK) {
1077189499Srnoland	case CHIP_R600:
1078189499Srnoland	case CHIP_RV630:
1079189499Srnoland	case CHIP_RV635:
1080189499Srnoland		gs_prim_buffer_depth = 0;
1081189499Srnoland		break;
1082189499Srnoland	case CHIP_RV610:
1083189499Srnoland	case CHIP_RS780:
1084189499Srnoland	case CHIP_RV620:
1085189499Srnoland		gs_prim_buffer_depth = 32;
1086189499Srnoland		break;
1087189499Srnoland	case CHIP_RV670:
1088189499Srnoland		gs_prim_buffer_depth = 128;
1089189499Srnoland		break;
1090189499Srnoland	default:
1091189499Srnoland		break;
1092189499Srnoland	}
1093189499Srnoland
1094189499Srnoland	num_gs_verts_per_thread = dev_priv->r600_max_pipes * 16;
1095189499Srnoland	vgt_gs_per_es = gs_prim_buffer_depth + num_gs_verts_per_thread;
1096189499Srnoland	/* Max value for this is 256 */
1097189499Srnoland	if (vgt_gs_per_es > 256)
1098189499Srnoland		vgt_gs_per_es = 256;
1099189499Srnoland
1100189499Srnoland	RADEON_WRITE(R600_VGT_ES_PER_GS, 128);
1101189499Srnoland	RADEON_WRITE(R600_VGT_GS_PER_ES, vgt_gs_per_es);
1102189499Srnoland	RADEON_WRITE(R600_VGT_GS_PER_VS, 2);
1103189499Srnoland	RADEON_WRITE(R600_VGT_GS_VERTEX_REUSE, 16);
1104189499Srnoland
1105189499Srnoland	/* more default values. 2D/3D driver should adjust as needed */
1106189499Srnoland	RADEON_WRITE(R600_PA_SC_LINE_STIPPLE_STATE, 0);
1107189499Srnoland	RADEON_WRITE(R600_VGT_STRMOUT_EN, 0);
1108189499Srnoland	RADEON_WRITE(R600_SX_MISC, 0);
1109189499Srnoland	RADEON_WRITE(R600_PA_SC_MODE_CNTL, 0);
1110189499Srnoland	RADEON_WRITE(R600_PA_SC_AA_CONFIG, 0);
1111189499Srnoland	RADEON_WRITE(R600_PA_SC_LINE_STIPPLE, 0);
1112189499Srnoland	RADEON_WRITE(R600_SPI_INPUT_Z, 0);
1113189499Srnoland	RADEON_WRITE(R600_SPI_PS_IN_CONTROL_0, R600_NUM_INTERP(2));
1114189499Srnoland	RADEON_WRITE(R600_CB_COLOR7_FRAG, 0);
1115189499Srnoland
1116189499Srnoland	/* clear render buffer base addresses */
1117189499Srnoland	RADEON_WRITE(R600_CB_COLOR0_BASE, 0);
1118189499Srnoland	RADEON_WRITE(R600_CB_COLOR1_BASE, 0);
1119189499Srnoland	RADEON_WRITE(R600_CB_COLOR2_BASE, 0);
1120189499Srnoland	RADEON_WRITE(R600_CB_COLOR3_BASE, 0);
1121189499Srnoland	RADEON_WRITE(R600_CB_COLOR4_BASE, 0);
1122189499Srnoland	RADEON_WRITE(R600_CB_COLOR5_BASE, 0);
1123189499Srnoland	RADEON_WRITE(R600_CB_COLOR6_BASE, 0);
1124189499Srnoland	RADEON_WRITE(R600_CB_COLOR7_BASE, 0);
1125189499Srnoland
1126189499Srnoland	switch (dev_priv->flags & RADEON_FAMILY_MASK) {
1127189499Srnoland	case CHIP_RV610:
1128189499Srnoland	case CHIP_RS780:
1129189499Srnoland	case CHIP_RV620:
1130189499Srnoland		tc_cntl = R600_TC_L2_SIZE(8);
1131189499Srnoland		break;
1132189499Srnoland	case CHIP_RV630:
1133189499Srnoland	case CHIP_RV635:
1134189499Srnoland		tc_cntl = R600_TC_L2_SIZE(4);
1135189499Srnoland		break;
1136189499Srnoland	case CHIP_R600:
1137189499Srnoland		tc_cntl = R600_TC_L2_SIZE(0) | R600_L2_DISABLE_LATE_HIT;
1138189499Srnoland		break;
1139189499Srnoland	default:
1140189499Srnoland		tc_cntl = R600_TC_L2_SIZE(0);
1141189499Srnoland		break;
1142189499Srnoland	}
1143189499Srnoland
1144189499Srnoland	RADEON_WRITE(R600_TC_CNTL, tc_cntl);
1145189499Srnoland
1146189499Srnoland	hdp_host_path_cntl = RADEON_READ(R600_HDP_HOST_PATH_CNTL);
1147189499Srnoland	RADEON_WRITE(R600_HDP_HOST_PATH_CNTL, hdp_host_path_cntl);
1148189499Srnoland
1149189499Srnoland	arb_pop = RADEON_READ(R600_ARB_POP);
1150189499Srnoland	arb_pop |= R600_ENABLE_TC128;
1151189499Srnoland	RADEON_WRITE(R600_ARB_POP, arb_pop);
1152189499Srnoland
1153189499Srnoland	RADEON_WRITE(R600_PA_SC_MULTI_CHIP_CNTL, 0);
1154189499Srnoland	RADEON_WRITE(R600_PA_CL_ENHANCE, (R600_CLIP_VTX_REORDER_ENA |
1155189499Srnoland					  R600_NUM_CLIP_SEQ(3)));
1156189499Srnoland	RADEON_WRITE(R600_PA_SC_ENHANCE, R600_FORCE_EOV_MAX_CLK_CNT(4095));
1157189499Srnoland
1158189499Srnoland}
1159189499Srnoland
1160189499Srnolandstatic u32 r700_get_tile_pipe_to_backend_map(u32 num_tile_pipes,
1161189499Srnoland					     u32 num_backends,
1162189499Srnoland					     u32 backend_disable_mask)
1163189499Srnoland{
1164189499Srnoland	u32 backend_map = 0;
1165189499Srnoland	u32 enabled_backends_mask;
1166189499Srnoland	u32 enabled_backends_count;
1167189499Srnoland	u32 cur_pipe;
1168189499Srnoland	u32 swizzle_pipe[R7XX_MAX_PIPES];
1169189499Srnoland	u32 cur_backend;
1170189499Srnoland	u32 i;
1171189499Srnoland
1172189499Srnoland	if (num_tile_pipes > R7XX_MAX_PIPES)
1173189499Srnoland		num_tile_pipes = R7XX_MAX_PIPES;
1174189499Srnoland	if (num_tile_pipes < 1)
1175189499Srnoland		num_tile_pipes = 1;
1176189499Srnoland	if (num_backends > R7XX_MAX_BACKENDS)
1177189499Srnoland		num_backends = R7XX_MAX_BACKENDS;
1178189499Srnoland	if (num_backends < 1)
1179189499Srnoland		num_backends = 1;
1180189499Srnoland
1181189499Srnoland	enabled_backends_mask = 0;
1182189499Srnoland	enabled_backends_count = 0;
1183189499Srnoland	for (i = 0; i < R7XX_MAX_BACKENDS; ++i) {
1184189499Srnoland		if (((backend_disable_mask >> i) & 1) == 0) {
1185189499Srnoland			enabled_backends_mask |= (1 << i);
1186189499Srnoland			++enabled_backends_count;
1187189499Srnoland		}
1188189499Srnoland		if (enabled_backends_count == num_backends)
1189189499Srnoland			break;
1190189499Srnoland	}
1191189499Srnoland
1192189499Srnoland	if (enabled_backends_count == 0) {
1193189499Srnoland		enabled_backends_mask = 1;
1194189499Srnoland		enabled_backends_count = 1;
1195189499Srnoland	}
1196189499Srnoland
1197189499Srnoland	if (enabled_backends_count != num_backends)
1198189499Srnoland		num_backends = enabled_backends_count;
1199189499Srnoland
1200189499Srnoland	memset((uint8_t *)&swizzle_pipe[0], 0, sizeof(u32) * R7XX_MAX_PIPES);
1201189499Srnoland	switch (num_tile_pipes) {
1202189499Srnoland	case 1:
1203189499Srnoland		swizzle_pipe[0] = 0;
1204189499Srnoland		break;
1205189499Srnoland	case 2:
1206189499Srnoland		swizzle_pipe[0] = 0;
1207189499Srnoland		swizzle_pipe[1] = 1;
1208189499Srnoland		break;
1209189499Srnoland	case 3:
1210189499Srnoland		swizzle_pipe[0] = 0;
1211189499Srnoland		swizzle_pipe[1] = 2;
1212189499Srnoland		swizzle_pipe[2] = 1;
1213189499Srnoland		break;
1214189499Srnoland	case 4:
1215189499Srnoland		swizzle_pipe[0] = 0;
1216189499Srnoland		swizzle_pipe[1] = 2;
1217189499Srnoland		swizzle_pipe[2] = 3;
1218189499Srnoland		swizzle_pipe[3] = 1;
1219189499Srnoland		break;
1220189499Srnoland	case 5:
1221189499Srnoland		swizzle_pipe[0] = 0;
1222189499Srnoland		swizzle_pipe[1] = 2;
1223189499Srnoland		swizzle_pipe[2] = 4;
1224189499Srnoland		swizzle_pipe[3] = 1;
1225189499Srnoland		swizzle_pipe[4] = 3;
1226189499Srnoland		break;
1227189499Srnoland	case 6:
1228189499Srnoland		swizzle_pipe[0] = 0;
1229189499Srnoland		swizzle_pipe[1] = 2;
1230189499Srnoland		swizzle_pipe[2] = 4;
1231189499Srnoland		swizzle_pipe[3] = 5;
1232189499Srnoland		swizzle_pipe[4] = 3;
1233189499Srnoland		swizzle_pipe[5] = 1;
1234189499Srnoland		break;
1235189499Srnoland	case 7:
1236189499Srnoland		swizzle_pipe[0] = 0;
1237189499Srnoland		swizzle_pipe[1] = 2;
1238189499Srnoland		swizzle_pipe[2] = 4;
1239189499Srnoland		swizzle_pipe[3] = 6;
1240189499Srnoland		swizzle_pipe[4] = 3;
1241189499Srnoland		swizzle_pipe[5] = 1;
1242189499Srnoland		swizzle_pipe[6] = 5;
1243189499Srnoland		break;
1244189499Srnoland	case 8:
1245189499Srnoland		swizzle_pipe[0] = 0;
1246189499Srnoland		swizzle_pipe[1] = 2;
1247189499Srnoland		swizzle_pipe[2] = 4;
1248189499Srnoland		swizzle_pipe[3] = 6;
1249189499Srnoland		swizzle_pipe[4] = 3;
1250189499Srnoland		swizzle_pipe[5] = 1;
1251189499Srnoland		swizzle_pipe[6] = 7;
1252189499Srnoland		swizzle_pipe[7] = 5;
1253189499Srnoland		break;
1254189499Srnoland	}
1255189499Srnoland
1256189499Srnoland	cur_backend = 0;
1257189499Srnoland	for (cur_pipe = 0; cur_pipe < num_tile_pipes; ++cur_pipe) {
1258189499Srnoland		while (((1 << cur_backend) & enabled_backends_mask) == 0)
1259189499Srnoland			cur_backend = (cur_backend + 1) % R7XX_MAX_BACKENDS;
1260189499Srnoland
1261189499Srnoland		backend_map |= (u32)(((cur_backend & 3) << (swizzle_pipe[cur_pipe] * 2)));
1262189499Srnoland
1263189499Srnoland		cur_backend = (cur_backend + 1) % R7XX_MAX_BACKENDS;
1264189499Srnoland	}
1265189499Srnoland
1266189499Srnoland	return backend_map;
1267189499Srnoland}
1268189499Srnoland
1269189499Srnolandstatic void r700_gfx_init(struct drm_device *dev,
1270189499Srnoland			  drm_radeon_private_t *dev_priv)
1271189499Srnoland{
1272189499Srnoland	int i, j, num_qd_pipes;
1273189499Srnoland	u32 sx_debug_1;
1274189499Srnoland	u32 smx_dc_ctl0;
1275189499Srnoland	u32 num_gs_verts_per_thread;
1276189499Srnoland	u32 vgt_gs_per_es;
1277189499Srnoland	u32 gs_prim_buffer_depth = 0;
1278189499Srnoland	u32 sq_ms_fifo_sizes;
1279189499Srnoland	u32 sq_config;
1280189499Srnoland	u32 sq_thread_resource_mgmt;
1281189499Srnoland	u32 hdp_host_path_cntl;
1282189499Srnoland	u32 sq_dyn_gpr_size_simd_ab_0;
1283189499Srnoland	u32 backend_map;
1284189499Srnoland	u32 gb_tiling_config = 0;
1285189499Srnoland	u32 cc_rb_backend_disable = 0;
1286189499Srnoland	u32 cc_gc_shader_pipe_config = 0;
1287189499Srnoland	u32 mc_arb_ramcfg;
1288189499Srnoland	u32 db_debug4;
1289189499Srnoland
1290189499Srnoland	/* setup chip specs */
1291189499Srnoland	switch (dev_priv->flags & RADEON_FAMILY_MASK) {
1292189499Srnoland	case CHIP_RV770:
1293189499Srnoland		dev_priv->r600_max_pipes = 4;
1294189499Srnoland		dev_priv->r600_max_tile_pipes = 8;
1295189499Srnoland		dev_priv->r600_max_simds = 10;
1296189499Srnoland		dev_priv->r600_max_backends = 4;
1297189499Srnoland		dev_priv->r600_max_gprs = 256;
1298189499Srnoland		dev_priv->r600_max_threads = 248;
1299189499Srnoland		dev_priv->r600_max_stack_entries = 512;
1300189499Srnoland		dev_priv->r600_max_hw_contexts = 8;
1301189499Srnoland		dev_priv->r600_max_gs_threads = 16 * 2;
1302189499Srnoland		dev_priv->r600_sx_max_export_size = 128;
1303189499Srnoland		dev_priv->r600_sx_max_export_pos_size = 16;
1304189499Srnoland		dev_priv->r600_sx_max_export_smx_size = 112;
1305189499Srnoland		dev_priv->r600_sq_num_cf_insts = 2;
1306189499Srnoland
1307189499Srnoland		dev_priv->r700_sx_num_of_sets = 7;
1308189499Srnoland		dev_priv->r700_sc_prim_fifo_size = 0xF9;
1309189499Srnoland		dev_priv->r700_sc_hiz_tile_fifo_size = 0x30;
1310189499Srnoland		dev_priv->r700_sc_earlyz_tile_fifo_fize = 0x130;
1311189499Srnoland		break;
1312189499Srnoland	case CHIP_RV730:
1313189499Srnoland		dev_priv->r600_max_pipes = 2;
1314189499Srnoland		dev_priv->r600_max_tile_pipes = 4;
1315189499Srnoland		dev_priv->r600_max_simds = 8;
1316189499Srnoland		dev_priv->r600_max_backends = 2;
1317189499Srnoland		dev_priv->r600_max_gprs = 128;
1318189499Srnoland		dev_priv->r600_max_threads = 248;
1319189499Srnoland		dev_priv->r600_max_stack_entries = 256;
1320189499Srnoland		dev_priv->r600_max_hw_contexts = 8;
1321189499Srnoland		dev_priv->r600_max_gs_threads = 16 * 2;
1322189499Srnoland		dev_priv->r600_sx_max_export_size = 256;
1323189499Srnoland		dev_priv->r600_sx_max_export_pos_size = 32;
1324189499Srnoland		dev_priv->r600_sx_max_export_smx_size = 224;
1325189499Srnoland		dev_priv->r600_sq_num_cf_insts = 2;
1326189499Srnoland
1327189499Srnoland		dev_priv->r700_sx_num_of_sets = 7;
1328189499Srnoland		dev_priv->r700_sc_prim_fifo_size = 0xf9;
1329189499Srnoland		dev_priv->r700_sc_hiz_tile_fifo_size = 0x30;
1330189499Srnoland		dev_priv->r700_sc_earlyz_tile_fifo_fize = 0x130;
1331189499Srnoland		break;
1332189499Srnoland	case CHIP_RV710:
1333189499Srnoland		dev_priv->r600_max_pipes = 2;
1334189499Srnoland		dev_priv->r600_max_tile_pipes = 2;
1335189499Srnoland		dev_priv->r600_max_simds = 2;
1336189499Srnoland		dev_priv->r600_max_backends = 1;
1337189499Srnoland		dev_priv->r600_max_gprs = 256;
1338189499Srnoland		dev_priv->r600_max_threads = 192;
1339189499Srnoland		dev_priv->r600_max_stack_entries = 256;
1340189499Srnoland		dev_priv->r600_max_hw_contexts = 4;
1341189499Srnoland		dev_priv->r600_max_gs_threads = 8 * 2;
1342189499Srnoland		dev_priv->r600_sx_max_export_size = 128;
1343189499Srnoland		dev_priv->r600_sx_max_export_pos_size = 16;
1344189499Srnoland		dev_priv->r600_sx_max_export_smx_size = 112;
1345189499Srnoland		dev_priv->r600_sq_num_cf_insts = 1;
1346189499Srnoland
1347189499Srnoland		dev_priv->r700_sx_num_of_sets = 7;
1348189499Srnoland		dev_priv->r700_sc_prim_fifo_size = 0x40;
1349189499Srnoland		dev_priv->r700_sc_hiz_tile_fifo_size = 0x30;
1350189499Srnoland		dev_priv->r700_sc_earlyz_tile_fifo_fize = 0x130;
1351189499Srnoland		break;
1352189499Srnoland	default:
1353189499Srnoland		break;
1354189499Srnoland	}
1355189499Srnoland
1356189499Srnoland	/* Initialize HDP */
1357189499Srnoland	j = 0;
1358189499Srnoland	for (i = 0; i < 32; i++) {
1359189499Srnoland		RADEON_WRITE((0x2c14 + j), 0x00000000);
1360189499Srnoland		RADEON_WRITE((0x2c18 + j), 0x00000000);
1361189499Srnoland		RADEON_WRITE((0x2c1c + j), 0x00000000);
1362189499Srnoland		RADEON_WRITE((0x2c20 + j), 0x00000000);
1363189499Srnoland		RADEON_WRITE((0x2c24 + j), 0x00000000);
1364189499Srnoland		j += 0x18;
1365189499Srnoland	}
1366189499Srnoland
1367189499Srnoland	RADEON_WRITE(R600_GRBM_CNTL, R600_GRBM_READ_TIMEOUT(0xff));
1368189499Srnoland
1369189499Srnoland	/* setup tiling, simd, pipe config */
1370189499Srnoland	mc_arb_ramcfg = RADEON_READ(R700_MC_ARB_RAMCFG);
1371189499Srnoland
1372189499Srnoland	switch (dev_priv->r600_max_tile_pipes) {
1373189499Srnoland	case 1:
1374189499Srnoland		gb_tiling_config |= R600_PIPE_TILING(0);
1375189499Srnoland		break;
1376189499Srnoland	case 2:
1377189499Srnoland		gb_tiling_config |= R600_PIPE_TILING(1);
1378189499Srnoland		break;
1379189499Srnoland	case 4:
1380189499Srnoland		gb_tiling_config |= R600_PIPE_TILING(2);
1381189499Srnoland		break;
1382189499Srnoland	case 8:
1383189499Srnoland		gb_tiling_config |= R600_PIPE_TILING(3);
1384189499Srnoland		break;
1385189499Srnoland	default:
1386189499Srnoland		break;
1387189499Srnoland	}
1388189499Srnoland
1389189499Srnoland	if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV770)
1390189499Srnoland		gb_tiling_config |= R600_BANK_TILING(1);
1391189499Srnoland	else
1392189499Srnoland		gb_tiling_config |= R600_BANK_TILING((mc_arb_ramcfg >> R700_NOOFBANK_SHIFT) & R700_NOOFBANK_MASK);
1393189499Srnoland
1394189499Srnoland	gb_tiling_config |= R600_GROUP_SIZE(0);
1395189499Srnoland
1396189499Srnoland	if (((mc_arb_ramcfg >> R700_NOOFROWS_SHIFT) & R700_NOOFROWS_MASK) > 3) {
1397189499Srnoland		gb_tiling_config |= R600_ROW_TILING(3);
1398189499Srnoland		gb_tiling_config |= R600_SAMPLE_SPLIT(3);
1399189499Srnoland	} else {
1400189499Srnoland		gb_tiling_config |=
1401189499Srnoland			R600_ROW_TILING(((mc_arb_ramcfg >> R700_NOOFROWS_SHIFT) & R700_NOOFROWS_MASK));
1402189499Srnoland		gb_tiling_config |=
1403189499Srnoland			R600_SAMPLE_SPLIT(((mc_arb_ramcfg >> R700_NOOFROWS_SHIFT) & R700_NOOFROWS_MASK));
1404189499Srnoland	}
1405189499Srnoland
1406189499Srnoland	gb_tiling_config |= R600_BANK_SWAPS(1);
1407189499Srnoland
1408189499Srnoland	backend_map = r700_get_tile_pipe_to_backend_map(dev_priv->r600_max_tile_pipes,
1409189499Srnoland							dev_priv->r600_max_backends,
1410189499Srnoland							(0xff << dev_priv->r600_max_backends) & 0xff);
1411189499Srnoland	gb_tiling_config |= R600_BACKEND_MAP(backend_map);
1412189499Srnoland
1413189499Srnoland	cc_gc_shader_pipe_config =
1414189499Srnoland		R600_INACTIVE_QD_PIPES((R7XX_MAX_PIPES_MASK << dev_priv->r600_max_pipes) & R7XX_MAX_PIPES_MASK);
1415189499Srnoland	cc_gc_shader_pipe_config |=
1416189499Srnoland		R600_INACTIVE_SIMDS((R7XX_MAX_SIMDS_MASK << dev_priv->r600_max_simds) & R7XX_MAX_SIMDS_MASK);
1417189499Srnoland
1418189499Srnoland	cc_rb_backend_disable =
1419189499Srnoland		R600_BACKEND_DISABLE((R7XX_MAX_BACKENDS_MASK << dev_priv->r600_max_backends) & R7XX_MAX_BACKENDS_MASK);
1420189499Srnoland
1421189499Srnoland	RADEON_WRITE(R600_GB_TILING_CONFIG,      gb_tiling_config);
1422189499Srnoland	RADEON_WRITE(R600_DCP_TILING_CONFIG,    (gb_tiling_config & 0xffff));
1423189499Srnoland	RADEON_WRITE(R600_HDP_TILING_CONFIG,    (gb_tiling_config & 0xffff));
1424189499Srnoland
1425189499Srnoland	RADEON_WRITE(R600_CC_RB_BACKEND_DISABLE,      cc_rb_backend_disable);
1426189499Srnoland	RADEON_WRITE(R600_CC_GC_SHADER_PIPE_CONFIG,   cc_gc_shader_pipe_config);
1427189499Srnoland	RADEON_WRITE(R600_GC_USER_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config);
1428189499Srnoland
1429189499Srnoland	RADEON_WRITE(R700_CC_SYS_RB_BACKEND_DISABLE, cc_rb_backend_disable);
1430189499Srnoland	RADEON_WRITE(R700_CGTS_SYS_TCC_DISABLE, 0);
1431189499Srnoland	RADEON_WRITE(R700_CGTS_TCC_DISABLE, 0);
1432189499Srnoland	RADEON_WRITE(R700_CGTS_USER_SYS_TCC_DISABLE, 0);
1433189499Srnoland	RADEON_WRITE(R700_CGTS_USER_TCC_DISABLE, 0);
1434189499Srnoland
1435189499Srnoland	num_qd_pipes =
1436189499Srnoland		R7XX_MAX_BACKENDS - r600_count_pipe_bits(cc_gc_shader_pipe_config & R600_INACTIVE_QD_PIPES_MASK);
1437189499Srnoland	RADEON_WRITE(R600_VGT_OUT_DEALLOC_CNTL, (num_qd_pipes * 4) & R600_DEALLOC_DIST_MASK);
1438189499Srnoland	RADEON_WRITE(R600_VGT_VERTEX_REUSE_BLOCK_CNTL, ((num_qd_pipes * 4) - 2) & R600_VTX_REUSE_DEPTH_MASK);
1439189499Srnoland
1440189499Srnoland	/* set HW defaults for 3D engine */
1441189499Srnoland	RADEON_WRITE(R600_CP_QUEUE_THRESHOLDS, (R600_ROQ_IB1_START(0x16) |
1442189499Srnoland						R600_ROQ_IB2_START(0x2b)));
1443189499Srnoland
1444189499Srnoland	RADEON_WRITE(R600_CP_MEQ_THRESHOLDS, R700_STQ_SPLIT(0x30));
1445189499Srnoland
1446189499Srnoland	RADEON_WRITE(R600_TA_CNTL_AUX, (R600_DISABLE_CUBE_ANISO |
1447189499Srnoland					R600_SYNC_GRADIENT |
1448189499Srnoland					R600_SYNC_WALKER |
1449189499Srnoland					R600_SYNC_ALIGNER));
1450189499Srnoland
1451189499Srnoland	sx_debug_1 = RADEON_READ(R700_SX_DEBUG_1);
1452189499Srnoland	sx_debug_1 |= R700_ENABLE_NEW_SMX_ADDRESS;
1453189499Srnoland	RADEON_WRITE(R700_SX_DEBUG_1, sx_debug_1);
1454189499Srnoland
1455189499Srnoland	smx_dc_ctl0 = RADEON_READ(R600_SMX_DC_CTL0);
1456189499Srnoland	smx_dc_ctl0 &= ~R700_CACHE_DEPTH(0x1ff);
1457189499Srnoland	smx_dc_ctl0 |= R700_CACHE_DEPTH((dev_priv->r700_sx_num_of_sets * 64) - 1);
1458189499Srnoland	RADEON_WRITE(R600_SMX_DC_CTL0, smx_dc_ctl0);
1459189499Srnoland
1460189499Srnoland	RADEON_WRITE(R700_SMX_EVENT_CTL, (R700_ES_FLUSH_CTL(4) |
1461189499Srnoland					  R700_GS_FLUSH_CTL(4) |
1462189499Srnoland					  R700_ACK_FLUSH_CTL(3) |
1463189499Srnoland					  R700_SYNC_FLUSH_CTL));
1464189499Srnoland
1465189499Srnoland	if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV770)
1466189499Srnoland		RADEON_WRITE(R700_DB_DEBUG3, R700_DB_CLK_OFF_DELAY(0x1f));
1467189499Srnoland	else {
1468189499Srnoland		db_debug4 = RADEON_READ(RV700_DB_DEBUG4);
1469189499Srnoland		db_debug4 |= RV700_DISABLE_TILE_COVERED_FOR_PS_ITER;
1470189499Srnoland		RADEON_WRITE(RV700_DB_DEBUG4, db_debug4);
1471189499Srnoland	}
1472189499Srnoland
1473189499Srnoland	RADEON_WRITE(R600_SX_EXPORT_BUFFER_SIZES, (R600_COLOR_BUFFER_SIZE((dev_priv->r600_sx_max_export_size / 4) - 1) |
1474189499Srnoland						   R600_POSITION_BUFFER_SIZE((dev_priv->r600_sx_max_export_pos_size / 4) - 1) |
1475189499Srnoland						   R600_SMX_BUFFER_SIZE((dev_priv->r600_sx_max_export_smx_size / 4) - 1)));
1476189499Srnoland
1477189499Srnoland	RADEON_WRITE(R700_PA_SC_FIFO_SIZE_R7XX, (R700_SC_PRIM_FIFO_SIZE(dev_priv->r700_sc_prim_fifo_size) |
1478189499Srnoland						 R700_SC_HIZ_TILE_FIFO_SIZE(dev_priv->r700_sc_hiz_tile_fifo_size) |
1479189499Srnoland						 R700_SC_EARLYZ_TILE_FIFO_SIZE(dev_priv->r700_sc_earlyz_tile_fifo_fize)));
1480189499Srnoland
1481189499Srnoland	RADEON_WRITE(R600_PA_SC_MULTI_CHIP_CNTL, 0);
1482189499Srnoland
1483189499Srnoland	RADEON_WRITE(R600_VGT_NUM_INSTANCES, 1);
1484189499Srnoland
1485189499Srnoland	RADEON_WRITE(R600_SPI_CONFIG_CNTL, R600_GPR_WRITE_PRIORITY(0));
1486189499Srnoland
1487189499Srnoland	RADEON_WRITE(R600_SPI_CONFIG_CNTL_1, R600_VTX_DONE_DELAY(4));
1488189499Srnoland
1489189499Srnoland	RADEON_WRITE(R600_CP_PERFMON_CNTL, 0);
1490189499Srnoland
1491189499Srnoland	sq_ms_fifo_sizes = (R600_CACHE_FIFO_SIZE(16 * dev_priv->r600_sq_num_cf_insts) |
1492189499Srnoland			    R600_DONE_FIFO_HIWATER(0xe0) |
1493189499Srnoland			    R600_ALU_UPDATE_FIFO_HIWATER(0x8));
1494189499Srnoland	switch (dev_priv->flags & RADEON_FAMILY_MASK) {
1495189499Srnoland	case CHIP_RV770:
1496189499Srnoland		sq_ms_fifo_sizes |= R600_FETCH_FIFO_HIWATER(0x1);
1497189499Srnoland		break;
1498189499Srnoland	case CHIP_RV730:
1499189499Srnoland	case CHIP_RV710:
1500189499Srnoland	default:
1501189499Srnoland		sq_ms_fifo_sizes |= R600_FETCH_FIFO_HIWATER(0x4);
1502189499Srnoland		break;
1503189499Srnoland	}
1504189499Srnoland	RADEON_WRITE(R600_SQ_MS_FIFO_SIZES, sq_ms_fifo_sizes);
1505189499Srnoland
1506189499Srnoland	/* SQ_CONFIG, SQ_GPR_RESOURCE_MGMT, SQ_THREAD_RESOURCE_MGMT, SQ_STACK_RESOURCE_MGMT
1507189499Srnoland	 * should be adjusted as needed by the 2D/3D drivers.  This just sets default values
1508189499Srnoland	 */
1509189499Srnoland	sq_config = RADEON_READ(R600_SQ_CONFIG);
1510189499Srnoland	sq_config &= ~(R600_PS_PRIO(3) |
1511189499Srnoland		       R600_VS_PRIO(3) |
1512189499Srnoland		       R600_GS_PRIO(3) |
1513189499Srnoland		       R600_ES_PRIO(3));
1514189499Srnoland	sq_config |= (R600_DX9_CONSTS |
1515189499Srnoland		      R600_VC_ENABLE |
1516189499Srnoland		      R600_EXPORT_SRC_C |
1517189499Srnoland		      R600_PS_PRIO(0) |
1518189499Srnoland		      R600_VS_PRIO(1) |
1519189499Srnoland		      R600_GS_PRIO(2) |
1520189499Srnoland		      R600_ES_PRIO(3));
1521189499Srnoland	if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV710)
1522189499Srnoland		/* no vertex cache */
1523189499Srnoland		sq_config &= ~R600_VC_ENABLE;
1524189499Srnoland
1525189499Srnoland	RADEON_WRITE(R600_SQ_CONFIG, sq_config);
1526189499Srnoland
1527189499Srnoland	RADEON_WRITE(R600_SQ_GPR_RESOURCE_MGMT_1,  (R600_NUM_PS_GPRS((dev_priv->r600_max_gprs * 24)/64) |
1528189499Srnoland						    R600_NUM_VS_GPRS((dev_priv->r600_max_gprs * 24)/64) |
1529189499Srnoland						    R600_NUM_CLAUSE_TEMP_GPRS(((dev_priv->r600_max_gprs * 24)/64)/2)));
1530189499Srnoland
1531189499Srnoland	RADEON_WRITE(R600_SQ_GPR_RESOURCE_MGMT_2,  (R600_NUM_GS_GPRS((dev_priv->r600_max_gprs * 7)/64) |
1532189499Srnoland						    R600_NUM_ES_GPRS((dev_priv->r600_max_gprs * 7)/64)));
1533189499Srnoland
1534189499Srnoland	sq_thread_resource_mgmt = (R600_NUM_PS_THREADS((dev_priv->r600_max_threads * 4)/8) |
1535189499Srnoland				   R600_NUM_VS_THREADS((dev_priv->r600_max_threads * 2)/8) |
1536189499Srnoland				   R600_NUM_ES_THREADS((dev_priv->r600_max_threads * 1)/8));
1537189499Srnoland	if (((dev_priv->r600_max_threads * 1) / 8) > dev_priv->r600_max_gs_threads)
1538189499Srnoland		sq_thread_resource_mgmt |= R600_NUM_GS_THREADS(dev_priv->r600_max_gs_threads);
1539189499Srnoland	else
1540189499Srnoland		sq_thread_resource_mgmt |= R600_NUM_GS_THREADS((dev_priv->r600_max_gs_threads * 1)/8);
1541189499Srnoland	RADEON_WRITE(R600_SQ_THREAD_RESOURCE_MGMT, sq_thread_resource_mgmt);
1542189499Srnoland
1543189499Srnoland	RADEON_WRITE(R600_SQ_STACK_RESOURCE_MGMT_1, (R600_NUM_PS_STACK_ENTRIES((dev_priv->r600_max_stack_entries * 1)/4) |
1544189499Srnoland						     R600_NUM_VS_STACK_ENTRIES((dev_priv->r600_max_stack_entries * 1)/4)));
1545189499Srnoland
1546189499Srnoland	RADEON_WRITE(R600_SQ_STACK_RESOURCE_MGMT_2, (R600_NUM_GS_STACK_ENTRIES((dev_priv->r600_max_stack_entries * 1)/4) |
1547189499Srnoland						     R600_NUM_ES_STACK_ENTRIES((dev_priv->r600_max_stack_entries * 1)/4)));
1548189499Srnoland
1549189499Srnoland	sq_dyn_gpr_size_simd_ab_0 = (R700_SIMDA_RING0((dev_priv->r600_max_gprs * 38)/64) |
1550189499Srnoland				     R700_SIMDA_RING1((dev_priv->r600_max_gprs * 38)/64) |
1551189499Srnoland				     R700_SIMDB_RING0((dev_priv->r600_max_gprs * 38)/64) |
1552189499Srnoland				     R700_SIMDB_RING1((dev_priv->r600_max_gprs * 38)/64));
1553189499Srnoland
1554189499Srnoland	RADEON_WRITE(R700_SQ_DYN_GPR_SIZE_SIMD_AB_0, sq_dyn_gpr_size_simd_ab_0);
1555189499Srnoland	RADEON_WRITE(R700_SQ_DYN_GPR_SIZE_SIMD_AB_1, sq_dyn_gpr_size_simd_ab_0);
1556189499Srnoland	RADEON_WRITE(R700_SQ_DYN_GPR_SIZE_SIMD_AB_2, sq_dyn_gpr_size_simd_ab_0);
1557189499Srnoland	RADEON_WRITE(R700_SQ_DYN_GPR_SIZE_SIMD_AB_3, sq_dyn_gpr_size_simd_ab_0);
1558189499Srnoland	RADEON_WRITE(R700_SQ_DYN_GPR_SIZE_SIMD_AB_4, sq_dyn_gpr_size_simd_ab_0);
1559189499Srnoland	RADEON_WRITE(R700_SQ_DYN_GPR_SIZE_SIMD_AB_5, sq_dyn_gpr_size_simd_ab_0);
1560189499Srnoland	RADEON_WRITE(R700_SQ_DYN_GPR_SIZE_SIMD_AB_6, sq_dyn_gpr_size_simd_ab_0);
1561189499Srnoland	RADEON_WRITE(R700_SQ_DYN_GPR_SIZE_SIMD_AB_7, sq_dyn_gpr_size_simd_ab_0);
1562189499Srnoland
1563189499Srnoland	RADEON_WRITE(R700_PA_SC_FORCE_EOV_MAX_CNTS, (R700_FORCE_EOV_MAX_CLK_CNT(4095) |
1564189499Srnoland						     R700_FORCE_EOV_MAX_REZ_CNT(255)));
1565189499Srnoland
1566189499Srnoland	if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV710)
1567189499Srnoland		RADEON_WRITE(R600_VGT_CACHE_INVALIDATION, (R600_CACHE_INVALIDATION(R600_TC_ONLY) |
1568189499Srnoland							   R700_AUTO_INVLD_EN(R700_ES_AND_GS_AUTO)));
1569189499Srnoland	else
1570189499Srnoland		RADEON_WRITE(R600_VGT_CACHE_INVALIDATION, (R600_CACHE_INVALIDATION(R600_VC_AND_TC) |
1571189499Srnoland							   R700_AUTO_INVLD_EN(R700_ES_AND_GS_AUTO)));
1572189499Srnoland
1573189499Srnoland	switch (dev_priv->flags & RADEON_FAMILY_MASK) {
1574189499Srnoland	case CHIP_RV770:
1575189499Srnoland	case CHIP_RV730:
1576189499Srnoland		gs_prim_buffer_depth = 384;
1577189499Srnoland		break;
1578189499Srnoland	case CHIP_RV710:
1579189499Srnoland		gs_prim_buffer_depth = 128;
1580189499Srnoland		break;
1581189499Srnoland	default:
1582189499Srnoland		break;
1583189499Srnoland	}
1584189499Srnoland
1585189499Srnoland	num_gs_verts_per_thread = dev_priv->r600_max_pipes * 16;
1586189499Srnoland	vgt_gs_per_es = gs_prim_buffer_depth + num_gs_verts_per_thread;
1587189499Srnoland	/* Max value for this is 256 */
1588189499Srnoland	if (vgt_gs_per_es > 256)
1589189499Srnoland		vgt_gs_per_es = 256;
1590189499Srnoland
1591189499Srnoland	RADEON_WRITE(R600_VGT_ES_PER_GS, 128);
1592189499Srnoland	RADEON_WRITE(R600_VGT_GS_PER_ES, vgt_gs_per_es);
1593189499Srnoland	RADEON_WRITE(R600_VGT_GS_PER_VS, 2);
1594189499Srnoland
1595189499Srnoland	/* more default values. 2D/3D driver should adjust as needed */
1596189499Srnoland	RADEON_WRITE(R600_VGT_GS_VERTEX_REUSE, 16);
1597189499Srnoland	RADEON_WRITE(R600_PA_SC_LINE_STIPPLE_STATE, 0);
1598189499Srnoland	RADEON_WRITE(R600_VGT_STRMOUT_EN, 0);
1599189499Srnoland	RADEON_WRITE(R600_SX_MISC, 0);
1600189499Srnoland	RADEON_WRITE(R600_PA_SC_MODE_CNTL, 0);
1601189499Srnoland	RADEON_WRITE(R700_PA_SC_EDGERULE, 0xaaaaaaaa);
1602189499Srnoland	RADEON_WRITE(R600_PA_SC_AA_CONFIG, 0);
1603189499Srnoland	RADEON_WRITE(R600_PA_SC_CLIPRECT_RULE, 0xffff);
1604189499Srnoland	RADEON_WRITE(R600_PA_SC_LINE_STIPPLE, 0);
1605189499Srnoland	RADEON_WRITE(R600_SPI_INPUT_Z, 0);
1606189499Srnoland	RADEON_WRITE(R600_SPI_PS_IN_CONTROL_0, R600_NUM_INTERP(2));
1607189499Srnoland	RADEON_WRITE(R600_CB_COLOR7_FRAG, 0);
1608189499Srnoland
1609189499Srnoland	/* clear render buffer base addresses */
1610189499Srnoland	RADEON_WRITE(R600_CB_COLOR0_BASE, 0);
1611189499Srnoland	RADEON_WRITE(R600_CB_COLOR1_BASE, 0);
1612189499Srnoland	RADEON_WRITE(R600_CB_COLOR2_BASE, 0);
1613189499Srnoland	RADEON_WRITE(R600_CB_COLOR3_BASE, 0);
1614189499Srnoland	RADEON_WRITE(R600_CB_COLOR4_BASE, 0);
1615189499Srnoland	RADEON_WRITE(R600_CB_COLOR5_BASE, 0);
1616189499Srnoland	RADEON_WRITE(R600_CB_COLOR6_BASE, 0);
1617189499Srnoland	RADEON_WRITE(R600_CB_COLOR7_BASE, 0);
1618189499Srnoland
1619189499Srnoland	RADEON_WRITE(R700_TCP_CNTL, 0);
1620189499Srnoland
1621189499Srnoland	hdp_host_path_cntl = RADEON_READ(R600_HDP_HOST_PATH_CNTL);
1622189499Srnoland	RADEON_WRITE(R600_HDP_HOST_PATH_CNTL, hdp_host_path_cntl);
1623189499Srnoland
1624189499Srnoland	RADEON_WRITE(R600_PA_SC_MULTI_CHIP_CNTL, 0);
1625189499Srnoland
1626189499Srnoland	RADEON_WRITE(R600_PA_CL_ENHANCE, (R600_CLIP_VTX_REORDER_ENA |
1627189499Srnoland					  R600_NUM_CLIP_SEQ(3)));
1628189499Srnoland
1629189499Srnoland}
1630189499Srnoland
1631189499Srnolandstatic void r600_cp_init_ring_buffer(struct drm_device *dev,
1632189499Srnoland				       drm_radeon_private_t *dev_priv,
1633189499Srnoland				       struct drm_file *file_priv)
1634189499Srnoland{
1635189499Srnoland	u32 ring_start;
1636189499Srnoland
1637189499Srnoland	if (((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770))
1638189499Srnoland		r700_gfx_init(dev, dev_priv);
1639189499Srnoland	else
1640189499Srnoland		r600_gfx_init(dev, dev_priv);
1641189499Srnoland
1642189499Srnoland	RADEON_WRITE(R600_GRBM_SOFT_RESET, R600_SOFT_RESET_CP);
1643189499Srnoland	RADEON_READ(R600_GRBM_SOFT_RESET);
1644189499Srnoland	DRM_UDELAY(15000);
1645189499Srnoland	RADEON_WRITE(R600_GRBM_SOFT_RESET, 0);
1646189499Srnoland
1647189499Srnoland
1648189499Srnoland	/* Set ring buffer size */
1649189499Srnoland#ifdef __BIG_ENDIAN
1650189499Srnoland	RADEON_WRITE(R600_CP_RB_CNTL,
1651189499Srnoland		     RADEON_BUF_SWAP_32BIT |
1652189499Srnoland		     RADEON_RB_NO_UPDATE |
1653189499Srnoland		     (dev_priv->ring.rptr_update_l2qw << 8) |
1654189499Srnoland		     dev_priv->ring.size_l2qw);
1655189499Srnoland#else
1656189499Srnoland	RADEON_WRITE(R600_CP_RB_CNTL,
1657189499Srnoland		     RADEON_RB_NO_UPDATE |
1658189499Srnoland		     (dev_priv->ring.rptr_update_l2qw << 8) |
1659189499Srnoland		     dev_priv->ring.size_l2qw);
1660189499Srnoland#endif
1661189499Srnoland
1662189499Srnoland	RADEON_WRITE(R600_CP_SEM_WAIT_TIMER, 0x4);
1663189499Srnoland
1664189499Srnoland	/* Set the write pointer delay */
1665189499Srnoland	RADEON_WRITE(R600_CP_RB_WPTR_DELAY, 0);
1666189499Srnoland
1667189499Srnoland#ifdef __BIG_ENDIAN
1668189499Srnoland	RADEON_WRITE(R600_CP_RB_CNTL,
1669189499Srnoland		     RADEON_BUF_SWAP_32BIT |
1670189499Srnoland		     RADEON_RB_NO_UPDATE |
1671189499Srnoland		     RADEON_RB_RPTR_WR_ENA |
1672189499Srnoland		     (dev_priv->ring.rptr_update_l2qw << 8) |
1673189499Srnoland		     dev_priv->ring.size_l2qw);
1674189499Srnoland#else
1675189499Srnoland	RADEON_WRITE(R600_CP_RB_CNTL,
1676189499Srnoland		     RADEON_RB_NO_UPDATE |
1677189499Srnoland		     RADEON_RB_RPTR_WR_ENA |
1678189499Srnoland		     (dev_priv->ring.rptr_update_l2qw << 8) |
1679189499Srnoland		     dev_priv->ring.size_l2qw);
1680189499Srnoland#endif
1681189499Srnoland
1682189499Srnoland	/* Initialize the ring buffer's read and write pointers */
1683189499Srnoland	RADEON_WRITE(R600_CP_RB_RPTR_WR, 0);
1684189499Srnoland	RADEON_WRITE(R600_CP_RB_WPTR, 0);
1685189499Srnoland	SET_RING_HEAD(dev_priv, 0);
1686189499Srnoland	dev_priv->ring.tail = 0;
1687189499Srnoland
1688189499Srnoland#if __OS_HAS_AGP
1689189499Srnoland	if (dev_priv->flags & RADEON_IS_AGP) {
1690189499Srnoland		/* XXX */
1691189499Srnoland		RADEON_WRITE(R600_CP_RB_RPTR_ADDR,
1692189499Srnoland			     (dev_priv->ring_rptr->offset
1693189499Srnoland			     - dev->agp->base + dev_priv->gart_vm_start) >> 8);
1694189499Srnoland		RADEON_WRITE(R600_CP_RB_RPTR_ADDR_HI, 0);
1695189499Srnoland	} else
1696189499Srnoland#endif
1697189499Srnoland	{
1698189499Srnoland		struct drm_sg_mem *entry = dev->sg;
1699189499Srnoland		unsigned long tmp_ofs, page_ofs;
1700189499Srnoland
1701189499Srnoland		tmp_ofs = dev_priv->ring_rptr->offset -
1702189499Srnoland			  (unsigned long)dev->sg->virtual;
1703189499Srnoland		page_ofs = tmp_ofs >> PAGE_SHIFT;
1704189499Srnoland
1705189499Srnoland		RADEON_WRITE(R600_CP_RB_RPTR_ADDR, entry->busaddr[page_ofs] >> 8);
1706189499Srnoland		RADEON_WRITE(R600_CP_RB_RPTR_ADDR_HI, 0);
1707189499Srnoland		DRM_DEBUG("ring rptr: offset=0x%08lx handle=0x%08lx\n",
1708189499Srnoland			  (unsigned long)entry->busaddr[page_ofs],
1709189499Srnoland			  entry->handle + tmp_ofs);
1710189499Srnoland	}
1711189499Srnoland
1712189499Srnoland#ifdef __BIG_ENDIAN
1713189499Srnoland	RADEON_WRITE(R600_CP_RB_CNTL,
1714189499Srnoland		     RADEON_BUF_SWAP_32BIT |
1715189499Srnoland		     (dev_priv->ring.rptr_update_l2qw << 8) |
1716189499Srnoland		     dev_priv->ring.size_l2qw);
1717189499Srnoland#else
1718189499Srnoland	RADEON_WRITE(R600_CP_RB_CNTL,
1719189499Srnoland		     (dev_priv->ring.rptr_update_l2qw << 8) |
1720189499Srnoland		     dev_priv->ring.size_l2qw);
1721189499Srnoland#endif
1722189499Srnoland
1723189499Srnoland#if __OS_HAS_AGP
1724189499Srnoland	if (dev_priv->flags & RADEON_IS_AGP) {
1725189499Srnoland		/* XXX */
1726189499Srnoland		radeon_write_agp_base(dev_priv, dev->agp->base);
1727189499Srnoland
1728189499Srnoland		/* XXX */
1729189499Srnoland		radeon_write_agp_location(dev_priv,
1730189499Srnoland			     (((dev_priv->gart_vm_start - 1 +
1731189499Srnoland				dev_priv->gart_size) & 0xffff0000) |
1732189499Srnoland			      (dev_priv->gart_vm_start >> 16)));
1733189499Srnoland
1734189499Srnoland		ring_start = (dev_priv->cp_ring->offset
1735189499Srnoland			      - dev->agp->base
1736189499Srnoland			      + dev_priv->gart_vm_start);
1737189499Srnoland	} else
1738189499Srnoland#endif
1739189499Srnoland		ring_start = (dev_priv->cp_ring->offset
1740189499Srnoland			      - (unsigned long)dev->sg->virtual
1741189499Srnoland			      + dev_priv->gart_vm_start);
1742189499Srnoland
1743189499Srnoland	RADEON_WRITE(R600_CP_RB_BASE, ring_start >> 8);
1744189499Srnoland
1745189499Srnoland	RADEON_WRITE(R600_CP_ME_CNTL, 0xff);
1746189499Srnoland
1747189499Srnoland	RADEON_WRITE(R600_CP_DEBUG, (1 << 27) | (1 << 28));
1748189499Srnoland
1749189499Srnoland	/* Start with assuming that writeback doesn't work */
1750189499Srnoland	dev_priv->writeback_works = 0;
1751189499Srnoland
1752189499Srnoland	/* Initialize the scratch register pointer.  This will cause
1753189499Srnoland	 * the scratch register values to be written out to memory
1754189499Srnoland	 * whenever they are updated.
1755189499Srnoland	 *
1756189499Srnoland	 * We simply put this behind the ring read pointer, this works
1757189499Srnoland	 * with PCI GART as well as (whatever kind of) AGP GART
1758189499Srnoland	 */
1759189499Srnoland	RADEON_WRITE(R600_SCRATCH_ADDR, ((RADEON_READ(R600_CP_RB_RPTR_ADDR) << 8)
1760189499Srnoland					 + R600_SCRATCH_REG_OFFSET) >> 8);
1761189499Srnoland
1762189499Srnoland	RADEON_WRITE(R600_SCRATCH_UMSK, 0x7);
1763189499Srnoland
1764189499Srnoland	/* Turn on bus mastering */
1765189499Srnoland	radeon_enable_bm(dev_priv);
1766189499Srnoland
1767189499Srnoland	radeon_write_ring_rptr(dev_priv, R600_SCRATCHOFF(0), 0);
1768189499Srnoland	RADEON_WRITE(R600_LAST_FRAME_REG, 0);
1769189499Srnoland
1770189499Srnoland	radeon_write_ring_rptr(dev_priv, R600_SCRATCHOFF(1), 0);
1771189499Srnoland	RADEON_WRITE(R600_LAST_DISPATCH_REG, 0);
1772189499Srnoland
1773189499Srnoland	radeon_write_ring_rptr(dev_priv, R600_SCRATCHOFF(2), 0);
1774189499Srnoland	RADEON_WRITE(R600_LAST_CLEAR_REG, 0);
1775189499Srnoland
1776189499Srnoland	/* reset sarea copies of these */
1777189499Srnoland	if (dev_priv->sarea_priv) {
1778189499Srnoland		dev_priv->sarea_priv->last_frame = 0;
1779189499Srnoland		dev_priv->sarea_priv->last_dispatch = 0;
1780189499Srnoland		dev_priv->sarea_priv->last_clear = 0;
1781189499Srnoland	}
1782189499Srnoland
1783189499Srnoland	r600_do_wait_for_idle(dev_priv);
1784189499Srnoland
1785189499Srnoland}
1786189499Srnoland
1787189499Srnolandint r600_do_cleanup_cp(struct drm_device *dev)
1788189499Srnoland{
1789189499Srnoland	drm_radeon_private_t *dev_priv = dev->dev_private;
1790189499Srnoland	DRM_DEBUG("\n");
1791189499Srnoland
1792189499Srnoland	/* Make sure interrupts are disabled here because the uninstall ioctl
1793189499Srnoland	 * may not have been called from userspace and after dev_private
1794189499Srnoland	 * is freed, it's too late.
1795189499Srnoland	 */
1796189499Srnoland	if (dev->irq_enabled)
1797189499Srnoland		drm_irq_uninstall(dev);
1798189499Srnoland
1799189499Srnoland#if __OS_HAS_AGP
1800189499Srnoland	if (dev_priv->flags & RADEON_IS_AGP) {
1801189499Srnoland		if (dev_priv->cp_ring != NULL) {
1802189499Srnoland			drm_core_ioremapfree(dev_priv->cp_ring, dev);
1803189499Srnoland			dev_priv->cp_ring = NULL;
1804189499Srnoland		}
1805189499Srnoland		if (dev_priv->ring_rptr != NULL) {
1806189499Srnoland			drm_core_ioremapfree(dev_priv->ring_rptr, dev);
1807189499Srnoland			dev_priv->ring_rptr = NULL;
1808189499Srnoland		}
1809189499Srnoland		if (dev->agp_buffer_map != NULL) {
1810189499Srnoland			drm_core_ioremapfree(dev->agp_buffer_map, dev);
1811189499Srnoland			dev->agp_buffer_map = NULL;
1812189499Srnoland		}
1813189499Srnoland	} else
1814189499Srnoland#endif
1815189499Srnoland	{
1816189499Srnoland
1817189499Srnoland		if (dev_priv->gart_info.bus_addr)
1818189499Srnoland			r600_page_table_cleanup(dev, &dev_priv->gart_info);
1819189499Srnoland
1820189499Srnoland		if (dev_priv->gart_info.gart_table_location == DRM_ATI_GART_FB) {
1821189499Srnoland			drm_core_ioremapfree(&dev_priv->gart_info.mapping, dev);
1822189499Srnoland			dev_priv->gart_info.addr = 0;
1823189499Srnoland		}
1824189499Srnoland	}
1825189499Srnoland	/* only clear to the start of flags */
1826189499Srnoland	memset(dev_priv, 0, offsetof(drm_radeon_private_t, flags));
1827189499Srnoland
1828189499Srnoland	return 0;
1829189499Srnoland}
1830189499Srnoland
1831189499Srnolandint r600_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
1832189499Srnoland		    struct drm_file *file_priv)
1833189499Srnoland{
1834189499Srnoland	drm_radeon_private_t *dev_priv = dev->dev_private;
1835189499Srnoland
1836189499Srnoland	DRM_DEBUG("\n");
1837189499Srnoland
1838189499Srnoland	/* if we require new memory map but we don't have it fail */
1839189499Srnoland	if ((dev_priv->flags & RADEON_NEW_MEMMAP) && !dev_priv->new_memmap) {
1840189499Srnoland		DRM_ERROR("Cannot initialise DRM on this card\nThis card requires a new X.org DDX for 3D\n");
1841189499Srnoland		r600_do_cleanup_cp(dev);
1842189499Srnoland		return -EINVAL;
1843189499Srnoland	}
1844189499Srnoland
1845189499Srnoland	if (init->is_pci && (dev_priv->flags & RADEON_IS_AGP)) {
1846189499Srnoland		DRM_DEBUG("Forcing AGP card to PCI mode\n");
1847189499Srnoland		dev_priv->flags &= ~RADEON_IS_AGP;
1848189499Srnoland		/* The writeback test succeeds, but when writeback is enabled,
1849189499Srnoland		 * the ring buffer read ptr update fails after first 128 bytes.
1850189499Srnoland		 */
1851189499Srnoland		radeon_no_wb = 1;
1852189499Srnoland	} else if (!(dev_priv->flags & (RADEON_IS_AGP | RADEON_IS_PCI | RADEON_IS_PCIE))
1853189499Srnoland		 && !init->is_pci) {
1854189499Srnoland		DRM_DEBUG("Restoring AGP flag\n");
1855189499Srnoland		dev_priv->flags |= RADEON_IS_AGP;
1856189499Srnoland	}
1857189499Srnoland
1858189499Srnoland	dev_priv->usec_timeout = init->usec_timeout;
1859189499Srnoland	if (dev_priv->usec_timeout < 1 ||
1860189499Srnoland	    dev_priv->usec_timeout > RADEON_MAX_USEC_TIMEOUT) {
1861189499Srnoland		DRM_DEBUG("TIMEOUT problem!\n");
1862189499Srnoland		r600_do_cleanup_cp(dev);
1863189499Srnoland		return -EINVAL;
1864189499Srnoland	}
1865189499Srnoland
1866189499Srnoland	/* Enable vblank on CRTC1 for older X servers
1867189499Srnoland	 */
1868189499Srnoland	dev_priv->vblank_crtc = DRM_RADEON_VBLANK_CRTC1;
1869189499Srnoland
1870189499Srnoland	dev_priv->cp_mode = init->cp_mode;
1871189499Srnoland
1872189499Srnoland	/* We don't support anything other than bus-mastering ring mode,
1873189499Srnoland	 * but the ring can be in either AGP or PCI space for the ring
1874189499Srnoland	 * read pointer.
1875189499Srnoland	 */
1876189499Srnoland	if ((init->cp_mode != RADEON_CSQ_PRIBM_INDDIS) &&
1877189499Srnoland	    (init->cp_mode != RADEON_CSQ_PRIBM_INDBM)) {
1878189499Srnoland		DRM_DEBUG("BAD cp_mode (%x)!\n", init->cp_mode);
1879189499Srnoland		r600_do_cleanup_cp(dev);
1880189499Srnoland		return -EINVAL;
1881189499Srnoland	}
1882189499Srnoland
1883189499Srnoland	switch (init->fb_bpp) {
1884189499Srnoland	case 16:
1885189499Srnoland		dev_priv->color_fmt = RADEON_COLOR_FORMAT_RGB565;
1886189499Srnoland		break;
1887189499Srnoland	case 32:
1888189499Srnoland	default:
1889189499Srnoland		dev_priv->color_fmt = RADEON_COLOR_FORMAT_ARGB8888;
1890189499Srnoland		break;
1891189499Srnoland	}
1892189499Srnoland	dev_priv->front_offset = init->front_offset;
1893189499Srnoland	dev_priv->front_pitch = init->front_pitch;
1894189499Srnoland	dev_priv->back_offset = init->back_offset;
1895189499Srnoland	dev_priv->back_pitch = init->back_pitch;
1896189499Srnoland
1897189499Srnoland	dev_priv->ring_offset = init->ring_offset;
1898189499Srnoland	dev_priv->ring_rptr_offset = init->ring_rptr_offset;
1899189499Srnoland	dev_priv->buffers_offset = init->buffers_offset;
1900189499Srnoland	dev_priv->gart_textures_offset = init->gart_textures_offset;
1901189499Srnoland
1902189499Srnoland	dev_priv->sarea = drm_getsarea(dev);
1903189499Srnoland	if (!dev_priv->sarea) {
1904189499Srnoland		DRM_ERROR("could not find sarea!\n");
1905189499Srnoland		r600_do_cleanup_cp(dev);
1906189499Srnoland		return -EINVAL;
1907189499Srnoland	}
1908189499Srnoland
1909189499Srnoland	dev_priv->cp_ring = drm_core_findmap(dev, init->ring_offset);
1910189499Srnoland	if (!dev_priv->cp_ring) {
1911189499Srnoland		DRM_ERROR("could not find cp ring region!\n");
1912189499Srnoland		r600_do_cleanup_cp(dev);
1913189499Srnoland		return -EINVAL;
1914189499Srnoland	}
1915189499Srnoland	dev_priv->ring_rptr = drm_core_findmap(dev, init->ring_rptr_offset);
1916189499Srnoland	if (!dev_priv->ring_rptr) {
1917189499Srnoland		DRM_ERROR("could not find ring read pointer!\n");
1918189499Srnoland		r600_do_cleanup_cp(dev);
1919189499Srnoland		return -EINVAL;
1920189499Srnoland	}
1921189499Srnoland	dev->agp_buffer_token = init->buffers_offset;
1922189499Srnoland	dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
1923189499Srnoland	if (!dev->agp_buffer_map) {
1924189499Srnoland		DRM_ERROR("could not find dma buffer region!\n");
1925189499Srnoland		r600_do_cleanup_cp(dev);
1926189499Srnoland		return -EINVAL;
1927189499Srnoland	}
1928189499Srnoland
1929189499Srnoland	if (init->gart_textures_offset) {
1930189499Srnoland		dev_priv->gart_textures =
1931189499Srnoland		    drm_core_findmap(dev, init->gart_textures_offset);
1932189499Srnoland		if (!dev_priv->gart_textures) {
1933189499Srnoland			DRM_ERROR("could not find GART texture region!\n");
1934189499Srnoland			r600_do_cleanup_cp(dev);
1935189499Srnoland			return -EINVAL;
1936189499Srnoland		}
1937189499Srnoland	}
1938189499Srnoland
1939189499Srnoland	dev_priv->sarea_priv =
1940189499Srnoland	    (drm_radeon_sarea_t *) ((u8 *) dev_priv->sarea->handle +
1941189499Srnoland				    init->sarea_priv_offset);
1942189499Srnoland
1943189499Srnoland#if __OS_HAS_AGP
1944189499Srnoland	/* XXX */
1945189499Srnoland	if (dev_priv->flags & RADEON_IS_AGP) {
1946189499Srnoland		drm_core_ioremap_wc(dev_priv->cp_ring, dev);
1947189499Srnoland		drm_core_ioremap_wc(dev_priv->ring_rptr, dev);
1948189499Srnoland		drm_core_ioremap_wc(dev->agp_buffer_map, dev);
1949189499Srnoland		if (!dev_priv->cp_ring->handle ||
1950189499Srnoland		    !dev_priv->ring_rptr->handle ||
1951189499Srnoland		    !dev->agp_buffer_map->handle) {
1952189499Srnoland			DRM_ERROR("could not find ioremap agp regions!\n");
1953189499Srnoland			r600_do_cleanup_cp(dev);
1954189499Srnoland			return -EINVAL;
1955189499Srnoland		}
1956189499Srnoland	} else
1957189499Srnoland#endif
1958189499Srnoland	{
1959189499Srnoland		dev_priv->cp_ring->handle = (void *)dev_priv->cp_ring->offset;
1960189499Srnoland		dev_priv->ring_rptr->handle =
1961189499Srnoland		    (void *)dev_priv->ring_rptr->offset;
1962189499Srnoland		dev->agp_buffer_map->handle =
1963189499Srnoland		    (void *)dev->agp_buffer_map->offset;
1964189499Srnoland
1965189499Srnoland		DRM_DEBUG("dev_priv->cp_ring->handle %p\n",
1966189499Srnoland			  dev_priv->cp_ring->handle);
1967189499Srnoland		DRM_DEBUG("dev_priv->ring_rptr->handle %p\n",
1968189499Srnoland			  dev_priv->ring_rptr->handle);
1969189499Srnoland		DRM_DEBUG("dev->agp_buffer_map->handle %p\n",
1970189499Srnoland			  dev->agp_buffer_map->handle);
1971189499Srnoland	}
1972189499Srnoland
1973189499Srnoland	dev_priv->fb_location = (radeon_read_fb_location(dev_priv) & 0xffff) << 24;
1974189499Srnoland	dev_priv->fb_size =
1975189499Srnoland		(((radeon_read_fb_location(dev_priv) & 0xffff0000u) << 8) + 0x1000000)
1976189499Srnoland		- dev_priv->fb_location;
1977189499Srnoland
1978189499Srnoland	dev_priv->front_pitch_offset = (((dev_priv->front_pitch / 64) << 22) |
1979189499Srnoland					((dev_priv->front_offset
1980189499Srnoland					  + dev_priv->fb_location) >> 10));
1981189499Srnoland
1982189499Srnoland	dev_priv->back_pitch_offset = (((dev_priv->back_pitch / 64) << 22) |
1983189499Srnoland				       ((dev_priv->back_offset
1984189499Srnoland					 + dev_priv->fb_location) >> 10));
1985189499Srnoland
1986189499Srnoland	dev_priv->depth_pitch_offset = (((dev_priv->depth_pitch / 64) << 22) |
1987189499Srnoland					((dev_priv->depth_offset
1988189499Srnoland					  + dev_priv->fb_location) >> 10));
1989189499Srnoland
1990189499Srnoland	dev_priv->gart_size = init->gart_size;
1991189499Srnoland
1992189499Srnoland	/* New let's set the memory map ... */
1993189499Srnoland	if (dev_priv->new_memmap) {
1994189499Srnoland		u32 base = 0;
1995189499Srnoland
1996189499Srnoland		DRM_INFO("Setting GART location based on new memory map\n");
1997189499Srnoland
1998189499Srnoland		/* If using AGP, try to locate the AGP aperture at the same
1999189499Srnoland		 * location in the card and on the bus, though we have to
2000189499Srnoland		 * align it down.
2001189499Srnoland		 */
2002189499Srnoland#if __OS_HAS_AGP
2003189499Srnoland		/* XXX */
2004189499Srnoland		if (dev_priv->flags & RADEON_IS_AGP) {
2005189499Srnoland			base = dev->agp->base;
2006189499Srnoland			/* Check if valid */
2007189499Srnoland			if ((base + dev_priv->gart_size - 1) >= dev_priv->fb_location &&
2008189499Srnoland			    base < (dev_priv->fb_location + dev_priv->fb_size - 1)) {
2009189499Srnoland				DRM_INFO("Can't use AGP base @0x%08lx, won't fit\n",
2010189499Srnoland					 dev->agp->base);
2011189499Srnoland				base = 0;
2012189499Srnoland			}
2013189499Srnoland		}
2014189499Srnoland#endif
2015189499Srnoland		/* If not or if AGP is at 0 (Macs), try to put it elsewhere */
2016189499Srnoland		if (base == 0) {
2017189499Srnoland			base = dev_priv->fb_location + dev_priv->fb_size;
2018189499Srnoland			if (base < dev_priv->fb_location ||
2019189499Srnoland			    ((base + dev_priv->gart_size) & 0xfffffffful) < base)
2020189499Srnoland				base = dev_priv->fb_location
2021189499Srnoland					- dev_priv->gart_size;
2022189499Srnoland		}
2023189499Srnoland		dev_priv->gart_vm_start = base & 0xffc00000u;
2024189499Srnoland		if (dev_priv->gart_vm_start != base)
2025189499Srnoland			DRM_INFO("GART aligned down from 0x%08x to 0x%08x\n",
2026189499Srnoland				 base, dev_priv->gart_vm_start);
2027189499Srnoland	}
2028189499Srnoland
2029189499Srnoland#if __OS_HAS_AGP
2030189499Srnoland	/* XXX */
2031189499Srnoland	if (dev_priv->flags & RADEON_IS_AGP)
2032189499Srnoland		dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset
2033189499Srnoland						 - dev->agp->base
2034189499Srnoland						 + dev_priv->gart_vm_start);
2035189499Srnoland	else
2036189499Srnoland#endif
2037189499Srnoland		dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset
2038189499Srnoland						 - (unsigned long)dev->sg->virtual
2039189499Srnoland						 + dev_priv->gart_vm_start);
2040189499Srnoland
2041189499Srnoland	DRM_DEBUG("fb 0x%08x size %d\n",
2042189499Srnoland		  (unsigned int) dev_priv->fb_location,
2043189499Srnoland		  (unsigned int) dev_priv->fb_size);
2044189499Srnoland	DRM_DEBUG("dev_priv->gart_size %d\n", dev_priv->gart_size);
2045189499Srnoland	DRM_DEBUG("dev_priv->gart_vm_start 0x%08x\n",
2046189499Srnoland		  (unsigned int) dev_priv->gart_vm_start);
2047189499Srnoland	DRM_DEBUG("dev_priv->gart_buffers_offset 0x%08lx\n",
2048189499Srnoland		  dev_priv->gart_buffers_offset);
2049189499Srnoland
2050189499Srnoland	dev_priv->ring.start = (u32 *) dev_priv->cp_ring->handle;
2051189499Srnoland	dev_priv->ring.end = ((u32 *) dev_priv->cp_ring->handle
2052189499Srnoland			      + init->ring_size / sizeof(u32));
2053189499Srnoland	dev_priv->ring.size = init->ring_size;
2054189499Srnoland	dev_priv->ring.size_l2qw = drm_order(init->ring_size / 8);
2055189499Srnoland
2056189499Srnoland	dev_priv->ring.rptr_update = /* init->rptr_update */ 4096;
2057189499Srnoland	dev_priv->ring.rptr_update_l2qw = drm_order(/* init->rptr_update */ 4096 / 8);
2058189499Srnoland
2059189499Srnoland	dev_priv->ring.fetch_size = /* init->fetch_size */ 32;
2060189499Srnoland	dev_priv->ring.fetch_size_l2ow = drm_order(/* init->fetch_size */ 32 / 16);
2061189499Srnoland
2062189499Srnoland	dev_priv->ring.tail_mask = (dev_priv->ring.size / sizeof(u32)) - 1;
2063189499Srnoland
2064189499Srnoland	dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK;
2065189499Srnoland
2066189499Srnoland#if __OS_HAS_AGP
2067189499Srnoland	if (dev_priv->flags & RADEON_IS_AGP) {
2068189499Srnoland		/* XXX turn off pcie gart */
2069189499Srnoland	} else
2070189499Srnoland#endif
2071189499Srnoland	{
2072189499Srnoland		dev_priv->gart_info.table_mask = DMA_BIT_MASK(32);
2073189499Srnoland		/* if we have an offset set from userspace */
2074189499Srnoland		if (!dev_priv->pcigart_offset_set) {
2075189499Srnoland			DRM_ERROR("Need gart offset from userspace\n");
2076189499Srnoland			r600_do_cleanup_cp(dev);
2077189499Srnoland			return -EINVAL;
2078189499Srnoland		}
2079189499Srnoland
2080189499Srnoland		DRM_DEBUG("Using gart offset 0x%08lx\n", dev_priv->pcigart_offset);
2081189499Srnoland
2082189499Srnoland		dev_priv->gart_info.bus_addr =
2083189499Srnoland			dev_priv->pcigart_offset + dev_priv->fb_location;
2084189499Srnoland		dev_priv->gart_info.mapping.offset =
2085189499Srnoland			dev_priv->pcigart_offset + dev_priv->fb_aper_offset;
2086189499Srnoland		dev_priv->gart_info.mapping.size =
2087189499Srnoland			dev_priv->gart_info.table_size;
2088189499Srnoland
2089189499Srnoland		drm_core_ioremap_wc(&dev_priv->gart_info.mapping, dev);
2090189499Srnoland		if (!dev_priv->gart_info.mapping.handle) {
2091189499Srnoland			DRM_ERROR("ioremap failed.\n");
2092189499Srnoland			r600_do_cleanup_cp(dev);
2093189499Srnoland			return -EINVAL;
2094189499Srnoland		}
2095189499Srnoland
2096189499Srnoland		dev_priv->gart_info.addr =
2097189499Srnoland			dev_priv->gart_info.mapping.handle;
2098189499Srnoland
2099189499Srnoland		DRM_DEBUG("Setting phys_pci_gart to %p %08lX\n",
2100189499Srnoland			  dev_priv->gart_info.addr,
2101189499Srnoland			  dev_priv->pcigart_offset);
2102189499Srnoland
2103189499Srnoland		if (r600_page_table_init(dev)) {
2104189499Srnoland			DRM_ERROR("Failed to init GART table\n");
2105189499Srnoland			r600_do_cleanup_cp(dev);
2106189499Srnoland			return -EINVAL;
2107189499Srnoland		}
2108189499Srnoland
2109189499Srnoland		if (((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770))
2110189499Srnoland			r700_vm_init(dev);
2111189499Srnoland		else
2112189499Srnoland			r600_vm_init(dev);
2113189499Srnoland	}
2114189499Srnoland
2115189499Srnoland	if (((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770))
2116189499Srnoland		r700_cp_load_microcode(dev_priv);
2117189499Srnoland	else
2118189499Srnoland		r600_cp_load_microcode(dev_priv);
2119189499Srnoland
2120189499Srnoland	r600_cp_init_ring_buffer(dev, dev_priv, file_priv);
2121189499Srnoland
2122189499Srnoland	dev_priv->last_buf = 0;
2123189499Srnoland
2124189499Srnoland	r600_do_engine_reset(dev);
2125189499Srnoland	r600_test_writeback(dev_priv);
2126189499Srnoland
2127189499Srnoland	return 0;
2128189499Srnoland}
2129189499Srnoland
2130189499Srnolandint r600_do_resume_cp(struct drm_device *dev, struct drm_file *file_priv)
2131189499Srnoland{
2132189499Srnoland	drm_radeon_private_t *dev_priv = dev->dev_private;
2133189499Srnoland
2134189499Srnoland	DRM_DEBUG("\n");
2135189499Srnoland	if (((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770)) {
2136189499Srnoland		r700_vm_init(dev);
2137189499Srnoland		r700_cp_load_microcode(dev_priv);
2138189499Srnoland	} else {
2139189499Srnoland		r600_vm_init(dev);
2140189499Srnoland		r600_cp_load_microcode(dev_priv);
2141189499Srnoland	}
2142189499Srnoland	r600_cp_init_ring_buffer(dev, dev_priv, file_priv);
2143189499Srnoland	r600_do_engine_reset(dev);
2144189499Srnoland
2145189499Srnoland	return 0;
2146189499Srnoland}
2147189499Srnoland
2148189499Srnoland/* Wait for the CP to go idle.
2149189499Srnoland */
2150189499Srnolandint r600_do_cp_idle(drm_radeon_private_t *dev_priv)
2151189499Srnoland{
2152189499Srnoland	RING_LOCALS;
2153189499Srnoland	DRM_DEBUG("\n");
2154189499Srnoland
2155189499Srnoland	BEGIN_RING(5);
2156189499Srnoland	OUT_RING(CP_PACKET3(R600_IT_EVENT_WRITE, 0));
2157189499Srnoland	OUT_RING(R600_CACHE_FLUSH_AND_INV_EVENT);
2158189499Srnoland	/* wait for 3D idle clean */
2159189499Srnoland	OUT_RING(CP_PACKET3(R600_IT_SET_CONFIG_REG, 1));
2160189499Srnoland	OUT_RING((R600_WAIT_UNTIL - R600_SET_CONFIG_REG_OFFSET) >> 2);
2161189499Srnoland	OUT_RING(RADEON_WAIT_3D_IDLE | RADEON_WAIT_3D_IDLECLEAN);
2162189499Srnoland
2163189499Srnoland	ADVANCE_RING();
2164189499Srnoland	COMMIT_RING();
2165189499Srnoland
2166189499Srnoland	return r600_do_wait_for_idle(dev_priv);
2167189499Srnoland}
2168189499Srnoland
2169189499Srnoland/* Start the Command Processor.
2170189499Srnoland */
2171189499Srnolandvoid r600_do_cp_start(drm_radeon_private_t *dev_priv)
2172189499Srnoland{
2173189499Srnoland	u32 cp_me;
2174189499Srnoland	RING_LOCALS;
2175189499Srnoland	DRM_DEBUG("\n");
2176189499Srnoland
2177189499Srnoland	BEGIN_RING(7);
2178189499Srnoland	OUT_RING(CP_PACKET3(R600_IT_ME_INITIALIZE, 5));
2179189499Srnoland	OUT_RING(0x00000001);
2180189499Srnoland	if (((dev_priv->flags & RADEON_FAMILY_MASK) < CHIP_RV770))
2181189499Srnoland		OUT_RING(0x00000003);
2182189499Srnoland	else
2183189499Srnoland		OUT_RING(0x00000000);
2184189499Srnoland	OUT_RING((dev_priv->r600_max_hw_contexts - 1));
2185189499Srnoland	OUT_RING(R600_ME_INITIALIZE_DEVICE_ID(1));
2186189499Srnoland	OUT_RING(0x00000000);
2187189499Srnoland	OUT_RING(0x00000000);
2188189499Srnoland	ADVANCE_RING();
2189189499Srnoland	COMMIT_RING();
2190189499Srnoland
2191189499Srnoland	/* set the mux and reset the halt bit */
2192189499Srnoland	cp_me = 0xff;
2193189499Srnoland	RADEON_WRITE(R600_CP_ME_CNTL, cp_me);
2194189499Srnoland
2195189499Srnoland	dev_priv->cp_running = 1;
2196189499Srnoland
2197189499Srnoland}
2198189499Srnoland
2199189499Srnolandvoid r600_do_cp_reset(drm_radeon_private_t *dev_priv)
2200189499Srnoland{
2201189499Srnoland	u32 cur_read_ptr;
2202189499Srnoland	DRM_DEBUG("\n");
2203189499Srnoland
2204189499Srnoland	cur_read_ptr = RADEON_READ(R600_CP_RB_RPTR);
2205189499Srnoland	RADEON_WRITE(R600_CP_RB_WPTR, cur_read_ptr);
2206189499Srnoland	SET_RING_HEAD(dev_priv, cur_read_ptr);
2207189499Srnoland	dev_priv->ring.tail = cur_read_ptr;
2208189499Srnoland}
2209189499Srnoland
2210189499Srnolandvoid r600_do_cp_stop(drm_radeon_private_t *dev_priv)
2211189499Srnoland{
2212189499Srnoland	uint32_t cp_me;
2213189499Srnoland
2214189499Srnoland	DRM_DEBUG("\n");
2215189499Srnoland
2216189499Srnoland	cp_me = 0xff | R600_CP_ME_HALT;
2217189499Srnoland
2218189499Srnoland	RADEON_WRITE(R600_CP_ME_CNTL, cp_me);
2219189499Srnoland
2220189499Srnoland	dev_priv->cp_running = 0;
2221189499Srnoland}
2222189499Srnoland
2223189499Srnolandint r600_cp_dispatch_indirect(struct drm_device *dev,
2224189499Srnoland			      struct drm_buf *buf, int start, int end)
2225189499Srnoland{
2226189499Srnoland	drm_radeon_private_t *dev_priv = dev->dev_private;
2227189499Srnoland	RING_LOCALS;
2228189499Srnoland
2229189499Srnoland	if (start != end) {
2230189499Srnoland		unsigned long offset = (dev_priv->gart_buffers_offset
2231189499Srnoland					+ buf->offset + start);
2232189499Srnoland		int dwords = (end - start + 3) / sizeof(u32);
2233189499Srnoland
2234189499Srnoland		DRM_DEBUG("dwords:%d\n", dwords);
2235189499Srnoland		DRM_DEBUG("offset 0x%lx\n", offset);
2236189499Srnoland
2237189499Srnoland
2238189499Srnoland		/* Indirect buffer data must be a multiple of 16 dwords.
2239189499Srnoland		 * pad the data with a Type-2 CP packet.
2240189499Srnoland		 */
2241189499Srnoland		while (dwords & 0xf) {
2242189499Srnoland			u32 *data = (u32 *)
2243189499Srnoland			    ((char *)dev->agp_buffer_map->handle
2244189499Srnoland			     + buf->offset + start);
2245189499Srnoland			data[dwords++] = RADEON_CP_PACKET2;
2246189499Srnoland		}
2247189499Srnoland
2248189499Srnoland		/* Fire off the indirect buffer */
2249189499Srnoland		BEGIN_RING(4);
2250189499Srnoland		OUT_RING(CP_PACKET3(R600_IT_INDIRECT_BUFFER, 2));
2251189499Srnoland		OUT_RING((offset & 0xfffffffc));
2252189499Srnoland		OUT_RING((upper_32_bits(offset) & 0xff));
2253189499Srnoland		OUT_RING(dwords);
2254189499Srnoland		ADVANCE_RING();
2255189499Srnoland	}
2256189499Srnoland
2257189499Srnoland	return 0;
2258189499Srnoland}
2259