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$");
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			goto done;
178189499Srnoland		}
179189499Srnoland#endif
180189499Srnoland		entry_addr = entry->busaddr[i];
181189499Srnoland		for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) {
182189499Srnoland			page_base = (u64) entry_addr & ATI_PCIGART_PAGE_MASK;
183207069Srnoland			page_base |= R600_PTE_VALID | R600_PTE_SYSTEM;
184189499Srnoland			page_base |= R600_PTE_READABLE | R600_PTE_WRITEABLE;
185189499Srnoland
186189499Srnoland			*pci_gart = page_base;
187189499Srnoland
188189499Srnoland			if ((i % 128) == 0)
189189499Srnoland				DRM_DEBUG("page entry %d: 0x%016llx\n",
190189499Srnoland				    i, (unsigned long long)page_base);
191189499Srnoland			pci_gart++;
192189499Srnoland			entry_addr += ATI_PCIGART_PAGE_SIZE;
193189499Srnoland		}
194189499Srnoland	}
195189909Srnoland	ret = 1;
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{
285190595Srnoland	const u32 (*cp)[3];
286190595Srnoland	const u32 *pfp;
287189499Srnoland	int i;
288189499Srnoland
289190595Srnoland	switch (dev_priv->flags & RADEON_FAMILY_MASK) {
290190595Srnoland	case CHIP_R600:
291190595Srnoland		DRM_INFO("Loading R600 Microcode\n");
292190595Srnoland		cp  = R600_cp_microcode;
293190595Srnoland		pfp = R600_pfp_microcode;
294190595Srnoland		break;
295190595Srnoland	case CHIP_RV610:
296190595Srnoland		DRM_INFO("Loading RV610 Microcode\n");
297190595Srnoland		cp  = RV610_cp_microcode;
298190595Srnoland		pfp = RV610_pfp_microcode;
299190595Srnoland		break;
300190595Srnoland	case CHIP_RV630:
301190595Srnoland		DRM_INFO("Loading RV630 Microcode\n");
302190595Srnoland		cp  = RV630_cp_microcode;
303190595Srnoland		pfp = RV630_pfp_microcode;
304190595Srnoland		break;
305190595Srnoland	case CHIP_RV620:
306190595Srnoland		DRM_INFO("Loading RV620 Microcode\n");
307190595Srnoland		cp  = RV620_cp_microcode;
308190595Srnoland		pfp = RV620_pfp_microcode;
309190595Srnoland		break;
310190595Srnoland	case CHIP_RV635:
311190595Srnoland		DRM_INFO("Loading RV635 Microcode\n");
312190595Srnoland		cp  = RV635_cp_microcode;
313190595Srnoland		pfp = RV635_pfp_microcode;
314190595Srnoland		break;
315190595Srnoland	case CHIP_RV670:
316190595Srnoland		DRM_INFO("Loading RV670 Microcode\n");
317190595Srnoland		cp  = RV670_cp_microcode;
318190595Srnoland		pfp = RV670_pfp_microcode;
319190595Srnoland		break;
320190595Srnoland	case CHIP_RS780:
321196142Srnoland	case CHIP_RS880:
322196142Srnoland		DRM_INFO("Loading RS780/RS880 Microcode\n");
323190595Srnoland		cp  = RS780_cp_microcode;
324190595Srnoland		pfp = RS780_pfp_microcode;
325190595Srnoland		break;
326190595Srnoland	default:
327190674Srnoland		return;
328190595Srnoland	}
329189499Srnoland
330190674Srnoland	r600_do_cp_stop(dev_priv);
331190674Srnoland
332190674Srnoland	RADEON_WRITE(R600_CP_RB_CNTL,
333190674Srnoland		     R600_RB_NO_UPDATE |
334190674Srnoland		     R600_RB_BLKSZ(15) |
335190674Srnoland		     R600_RB_BUFSZ(3));
336190674Srnoland
337190674Srnoland	RADEON_WRITE(R600_GRBM_SOFT_RESET, R600_SOFT_RESET_CP);
338190674Srnoland	RADEON_READ(R600_GRBM_SOFT_RESET);
339190674Srnoland	DRM_UDELAY(15000);
340190674Srnoland	RADEON_WRITE(R600_GRBM_SOFT_RESET, 0);
341190674Srnoland
342190674Srnoland	RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
343190674Srnoland
344190674Srnoland	for (i = 0; i < PM4_UCODE_SIZE; i++) {
345190595Srnoland		RADEON_WRITE(R600_CP_ME_RAM_DATA, cp[i][0]);
346190595Srnoland		RADEON_WRITE(R600_CP_ME_RAM_DATA, cp[i][1]);
347190595Srnoland		RADEON_WRITE(R600_CP_ME_RAM_DATA, cp[i][2]);
348190595Srnoland	}
349189499Srnoland
350190595Srnoland	RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
351190674Srnoland	for (i = 0; i < PFP_UCODE_SIZE; i++)
352190595Srnoland		RADEON_WRITE(R600_CP_PFP_UCODE_DATA, pfp[i]);
353189499Srnoland
354189499Srnoland	RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
355189499Srnoland	RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
356189499Srnoland	RADEON_WRITE(R600_CP_ME_RAM_RADDR, 0);
357189499Srnoland}
358189499Srnoland
359189499Srnolandstatic void r700_vm_init(struct drm_device *dev)
360189499Srnoland{
361189499Srnoland	drm_radeon_private_t *dev_priv = dev->dev_private;
362189499Srnoland	/* initialise the VM to use the page table we constructed up there */
363189499Srnoland	u32 vm_c0, i;
364189499Srnoland	u32 mc_vm_md_l1;
365189499Srnoland	u32 vm_l2_cntl, vm_l2_cntl3;
366189499Srnoland	/* okay set up the PCIE aperture type thingo */
367189499Srnoland	RADEON_WRITE(R700_MC_VM_SYSTEM_APERTURE_LOW_ADDR, dev_priv->gart_vm_start >> 12);
368189499Srnoland	RADEON_WRITE(R700_MC_VM_SYSTEM_APERTURE_HIGH_ADDR, (dev_priv->gart_vm_start + dev_priv->gart_size - 1) >> 12);
369189499Srnoland	RADEON_WRITE(R700_MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, 0);
370189499Srnoland
371189499Srnoland	mc_vm_md_l1 = R700_ENABLE_L1_TLB |
372189499Srnoland	    R700_ENABLE_L1_FRAGMENT_PROCESSING |
373189499Srnoland	    R700_SYSTEM_ACCESS_MODE_IN_SYS |
374189499Srnoland	    R700_SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU |
375189499Srnoland	    R700_EFFECTIVE_L1_TLB_SIZE(5) |
376189499Srnoland	    R700_EFFECTIVE_L1_QUEUE_SIZE(5);
377189499Srnoland
378189499Srnoland	RADEON_WRITE(R700_MC_VM_MD_L1_TLB0_CNTL, mc_vm_md_l1);
379189499Srnoland	RADEON_WRITE(R700_MC_VM_MD_L1_TLB1_CNTL, mc_vm_md_l1);
380189499Srnoland	RADEON_WRITE(R700_MC_VM_MD_L1_TLB2_CNTL, mc_vm_md_l1);
381189499Srnoland	RADEON_WRITE(R700_MC_VM_MB_L1_TLB0_CNTL, mc_vm_md_l1);
382189499Srnoland	RADEON_WRITE(R700_MC_VM_MB_L1_TLB1_CNTL, mc_vm_md_l1);
383189499Srnoland	RADEON_WRITE(R700_MC_VM_MB_L1_TLB2_CNTL, mc_vm_md_l1);
384189499Srnoland	RADEON_WRITE(R700_MC_VM_MB_L1_TLB3_CNTL, mc_vm_md_l1);
385189499Srnoland
386189499Srnoland	vm_l2_cntl = R600_VM_L2_CACHE_EN | R600_VM_L2_FRAG_PROC | R600_VM_ENABLE_PTE_CACHE_LRU_W;
387189499Srnoland	vm_l2_cntl |= R700_VM_L2_CNTL_QUEUE_SIZE(7);
388189499Srnoland	RADEON_WRITE(R600_VM_L2_CNTL, vm_l2_cntl);
389189499Srnoland
390189499Srnoland	RADEON_WRITE(R600_VM_L2_CNTL2, 0);
391189499Srnoland	vm_l2_cntl3 = R700_VM_L2_CNTL3_BANK_SELECT(0) | R700_VM_L2_CNTL3_CACHE_UPDATE_MODE(2);
392189499Srnoland	RADEON_WRITE(R600_VM_L2_CNTL3, vm_l2_cntl3);
393189499Srnoland
394189499Srnoland	vm_c0 = R600_VM_ENABLE_CONTEXT | R600_VM_PAGE_TABLE_DEPTH_FLAT;
395189499Srnoland
396189499Srnoland	RADEON_WRITE(R600_VM_CONTEXT0_CNTL, vm_c0);
397189499Srnoland
398189499Srnoland	vm_c0 &= ~R600_VM_ENABLE_CONTEXT;
399189499Srnoland
400189499Srnoland	/* disable all other contexts */
401189499Srnoland	for (i = 1; i < 8; i++)
402189499Srnoland		RADEON_WRITE(R600_VM_CONTEXT0_CNTL + (i * 4), vm_c0);
403189499Srnoland
404189499Srnoland	RADEON_WRITE(R700_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, dev_priv->gart_info.bus_addr >> 12);
405189499Srnoland	RADEON_WRITE(R700_VM_CONTEXT0_PAGE_TABLE_START_ADDR, dev_priv->gart_vm_start >> 12);
406189499Srnoland	RADEON_WRITE(R700_VM_CONTEXT0_PAGE_TABLE_END_ADDR, (dev_priv->gart_vm_start + dev_priv->gart_size - 1) >> 12);
407189499Srnoland
408189499Srnoland	r600_vm_flush_gart_range(dev);
409189499Srnoland}
410189499Srnoland
411189499Srnoland/* load r600 microcode */
412189499Srnolandstatic void r700_cp_load_microcode(drm_radeon_private_t *dev_priv)
413189499Srnoland{
414190595Srnoland	const u32 *pfp;
415190595Srnoland	const u32 *cp;
416189499Srnoland	int i;
417189499Srnoland
418190595Srnoland	switch (dev_priv->flags & RADEON_FAMILY_MASK) {
419190595Srnoland	case CHIP_RV770:
420190674Srnoland		DRM_INFO("Loading RV770/RV790 Microcode\n");
421190595Srnoland		pfp = RV770_pfp_microcode;
422190595Srnoland		cp  = RV770_cp_microcode;
423190595Srnoland		break;
424190595Srnoland	case CHIP_RV730:
425195501Srnoland	case CHIP_RV740:
426195501Srnoland		DRM_INFO("Loading RV730/RV740 Microcode\n");
427190595Srnoland		pfp = RV730_pfp_microcode;
428190595Srnoland		cp  = RV730_cp_microcode;
429190595Srnoland		break;
430190595Srnoland	case CHIP_RV710:
431190595Srnoland		DRM_INFO("Loading RV710 Microcode\n");
432190595Srnoland		pfp = RV710_pfp_microcode;
433190595Srnoland		cp  = RV710_cp_microcode;
434190595Srnoland		break;
435190595Srnoland	default:
436190674Srnoland		return;
437190595Srnoland	}
438189499Srnoland
439190674Srnoland	r600_do_cp_stop(dev_priv);
440190674Srnoland
441190674Srnoland	RADEON_WRITE(R600_CP_RB_CNTL,
442190674Srnoland		     R600_RB_NO_UPDATE |
443190674Srnoland		     (15 << 8) |
444190674Srnoland		     (3 << 0));
445190674Srnoland
446190674Srnoland	RADEON_WRITE(R600_GRBM_SOFT_RESET, R600_SOFT_RESET_CP);
447190674Srnoland	RADEON_READ(R600_GRBM_SOFT_RESET);
448190674Srnoland	DRM_UDELAY(15000);
449190674Srnoland	RADEON_WRITE(R600_GRBM_SOFT_RESET, 0);
450190674Srnoland
451190595Srnoland	RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
452190674Srnoland	for (i = 0; i < R700_PFP_UCODE_SIZE; i++)
453190595Srnoland		RADEON_WRITE(R600_CP_PFP_UCODE_DATA, pfp[i]);
454190595Srnoland	RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
455189499Srnoland
456190595Srnoland	RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
457190674Srnoland	for (i = 0; i < R700_PM4_UCODE_SIZE; i++)
458190595Srnoland		RADEON_WRITE(R600_CP_ME_RAM_DATA, cp[i]);
459190595Srnoland	RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
460189499Srnoland
461189499Srnoland	RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0);
462189499Srnoland	RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0);
463189499Srnoland	RADEON_WRITE(R600_CP_ME_RAM_RADDR, 0);
464189499Srnoland}
465189499Srnoland
466189499Srnolandstatic void r600_test_writeback(drm_radeon_private_t *dev_priv)
467189499Srnoland{
468189499Srnoland	u32 tmp;
469189499Srnoland
470189499Srnoland	/* Start with assuming that writeback doesn't work */
471189499Srnoland	dev_priv->writeback_works = 0;
472189499Srnoland
473189499Srnoland	/* Writeback doesn't seem to work everywhere, test it here and possibly
474189499Srnoland	 * enable it if it appears to work
475189499Srnoland	 */
476189499Srnoland	radeon_write_ring_rptr(dev_priv, R600_SCRATCHOFF(1), 0);
477189499Srnoland
478189499Srnoland	RADEON_WRITE(R600_SCRATCH_REG1, 0xdeadbeef);
479189499Srnoland
480189499Srnoland	for (tmp = 0; tmp < dev_priv->usec_timeout; tmp++) {
481189499Srnoland		u32 val;
482189499Srnoland
483189499Srnoland		val = radeon_read_ring_rptr(dev_priv, R600_SCRATCHOFF(1));
484189499Srnoland		if (val == 0xdeadbeef)
485189499Srnoland			break;
486189499Srnoland		DRM_UDELAY(1);
487189499Srnoland	}
488189499Srnoland
489189499Srnoland	if (tmp < dev_priv->usec_timeout) {
490189499Srnoland		dev_priv->writeback_works = 1;
491189499Srnoland		DRM_INFO("writeback test succeeded in %d usecs\n", tmp);
492189499Srnoland	} else {
493189499Srnoland		dev_priv->writeback_works = 0;
494189499Srnoland		DRM_INFO("writeback test failed\n");
495189499Srnoland	}
496189499Srnoland	if (radeon_no_wb == 1) {
497189499Srnoland		dev_priv->writeback_works = 0;
498189499Srnoland		DRM_INFO("writeback forced off\n");
499189499Srnoland	}
500189499Srnoland
501189499Srnoland	if (!dev_priv->writeback_works) {
502189499Srnoland		/* Disable writeback to avoid unnecessary bus master transfer */
503189499Srnoland		RADEON_WRITE(R600_CP_RB_CNTL, RADEON_READ(R600_CP_RB_CNTL) |
504189499Srnoland			     RADEON_RB_NO_UPDATE);
505189499Srnoland		RADEON_WRITE(R600_SCRATCH_UMSK, 0);
506189499Srnoland	}
507189499Srnoland}
508189499Srnoland
509189499Srnolandint r600_do_engine_reset(struct drm_device *dev)
510189499Srnoland{
511189499Srnoland	drm_radeon_private_t *dev_priv = dev->dev_private;
512189499Srnoland	u32 cp_ptr, cp_me_cntl, cp_rb_cntl;
513189499Srnoland
514189499Srnoland	DRM_INFO("Resetting GPU\n");
515189499Srnoland
516189499Srnoland	cp_ptr = RADEON_READ(R600_CP_RB_WPTR);
517189499Srnoland	cp_me_cntl = RADEON_READ(R600_CP_ME_CNTL);
518189499Srnoland	RADEON_WRITE(R600_CP_ME_CNTL, R600_CP_ME_HALT);
519189499Srnoland
520189499Srnoland	RADEON_WRITE(R600_GRBM_SOFT_RESET, 0x7fff);
521189499Srnoland	RADEON_READ(R600_GRBM_SOFT_RESET);
522189499Srnoland	DRM_UDELAY(50);
523189499Srnoland	RADEON_WRITE(R600_GRBM_SOFT_RESET, 0);
524189499Srnoland	RADEON_READ(R600_GRBM_SOFT_RESET);
525189499Srnoland
526189499Srnoland	RADEON_WRITE(R600_CP_RB_WPTR_DELAY, 0);
527189499Srnoland	cp_rb_cntl = RADEON_READ(R600_CP_RB_CNTL);
528189499Srnoland	RADEON_WRITE(R600_CP_RB_CNTL, R600_RB_RPTR_WR_ENA);
529189499Srnoland
530189499Srnoland	RADEON_WRITE(R600_CP_RB_RPTR_WR, cp_ptr);
531189499Srnoland	RADEON_WRITE(R600_CP_RB_WPTR, cp_ptr);
532189499Srnoland	RADEON_WRITE(R600_CP_RB_CNTL, cp_rb_cntl);
533189499Srnoland	RADEON_WRITE(R600_CP_ME_CNTL, cp_me_cntl);
534189499Srnoland
535189499Srnoland	/* Reset the CP ring */
536189499Srnoland	r600_do_cp_reset(dev_priv);
537189499Srnoland
538189499Srnoland	/* The CP is no longer running after an engine reset */
539189499Srnoland	dev_priv->cp_running = 0;
540189499Srnoland
541189499Srnoland	/* Reset any pending vertex, indirect buffers */
542189499Srnoland	radeon_freelist_reset(dev);
543189499Srnoland
544189499Srnoland	return 0;
545189499Srnoland
546189499Srnoland}
547189499Srnoland
548189499Srnolandstatic u32 r600_get_tile_pipe_to_backend_map(u32 num_tile_pipes,
549189499Srnoland					     u32 num_backends,
550189499Srnoland					     u32 backend_disable_mask)
551189499Srnoland{
552189499Srnoland	u32 backend_map = 0;
553189499Srnoland	u32 enabled_backends_mask;
554189499Srnoland	u32 enabled_backends_count;
555189499Srnoland	u32 cur_pipe;
556189499Srnoland	u32 swizzle_pipe[R6XX_MAX_PIPES];
557189499Srnoland	u32 cur_backend;
558189499Srnoland	u32 i;
559189499Srnoland
560189499Srnoland	if (num_tile_pipes > R6XX_MAX_PIPES)
561189499Srnoland		num_tile_pipes = R6XX_MAX_PIPES;
562189499Srnoland	if (num_tile_pipes < 1)
563189499Srnoland		num_tile_pipes = 1;
564189499Srnoland	if (num_backends > R6XX_MAX_BACKENDS)
565189499Srnoland		num_backends = R6XX_MAX_BACKENDS;
566189499Srnoland	if (num_backends < 1)
567189499Srnoland		num_backends = 1;
568189499Srnoland
569189499Srnoland	enabled_backends_mask = 0;
570189499Srnoland	enabled_backends_count = 0;
571189499Srnoland	for (i = 0; i < R6XX_MAX_BACKENDS; ++i) {
572189499Srnoland		if (((backend_disable_mask >> i) & 1) == 0) {
573189499Srnoland			enabled_backends_mask |= (1 << i);
574189499Srnoland			++enabled_backends_count;
575189499Srnoland		}
576189499Srnoland		if (enabled_backends_count == num_backends)
577189499Srnoland			break;
578189499Srnoland	}
579189499Srnoland
580189499Srnoland	if (enabled_backends_count == 0) {
581189499Srnoland		enabled_backends_mask = 1;
582189499Srnoland		enabled_backends_count = 1;
583189499Srnoland	}
584189499Srnoland
585189499Srnoland	if (enabled_backends_count != num_backends)
586189499Srnoland		num_backends = enabled_backends_count;
587189499Srnoland
588189499Srnoland	memset((uint8_t *)&swizzle_pipe[0], 0, sizeof(u32) * R6XX_MAX_PIPES);
589189499Srnoland	switch (num_tile_pipes) {
590189499Srnoland	case 1:
591189499Srnoland		swizzle_pipe[0] = 0;
592189499Srnoland		break;
593189499Srnoland	case 2:
594189499Srnoland		swizzle_pipe[0] = 0;
595189499Srnoland		swizzle_pipe[1] = 1;
596189499Srnoland		break;
597189499Srnoland	case 3:
598189499Srnoland		swizzle_pipe[0] = 0;
599189499Srnoland		swizzle_pipe[1] = 1;
600189499Srnoland		swizzle_pipe[2] = 2;
601189499Srnoland		break;
602189499Srnoland	case 4:
603189499Srnoland		swizzle_pipe[0] = 0;
604189499Srnoland		swizzle_pipe[1] = 1;
605189499Srnoland		swizzle_pipe[2] = 2;
606189499Srnoland		swizzle_pipe[3] = 3;
607189499Srnoland		break;
608189499Srnoland	case 5:
609189499Srnoland		swizzle_pipe[0] = 0;
610189499Srnoland		swizzle_pipe[1] = 1;
611189499Srnoland		swizzle_pipe[2] = 2;
612189499Srnoland		swizzle_pipe[3] = 3;
613189499Srnoland		swizzle_pipe[4] = 4;
614189499Srnoland		break;
615189499Srnoland	case 6:
616189499Srnoland		swizzle_pipe[0] = 0;
617189499Srnoland		swizzle_pipe[1] = 2;
618189499Srnoland		swizzle_pipe[2] = 4;
619189499Srnoland		swizzle_pipe[3] = 5;
620189499Srnoland		swizzle_pipe[4] = 1;
621189499Srnoland		swizzle_pipe[5] = 3;
622189499Srnoland		break;
623189499Srnoland	case 7:
624189499Srnoland		swizzle_pipe[0] = 0;
625189499Srnoland		swizzle_pipe[1] = 2;
626189499Srnoland		swizzle_pipe[2] = 4;
627189499Srnoland		swizzle_pipe[3] = 6;
628189499Srnoland		swizzle_pipe[4] = 1;
629189499Srnoland		swizzle_pipe[5] = 3;
630189499Srnoland		swizzle_pipe[6] = 5;
631189499Srnoland		break;
632189499Srnoland	case 8:
633189499Srnoland		swizzle_pipe[0] = 0;
634189499Srnoland		swizzle_pipe[1] = 2;
635189499Srnoland		swizzle_pipe[2] = 4;
636189499Srnoland		swizzle_pipe[3] = 6;
637189499Srnoland		swizzle_pipe[4] = 1;
638189499Srnoland		swizzle_pipe[5] = 3;
639189499Srnoland		swizzle_pipe[6] = 5;
640189499Srnoland		swizzle_pipe[7] = 7;
641189499Srnoland		break;
642189499Srnoland	}
643189499Srnoland
644189499Srnoland	cur_backend = 0;
645189499Srnoland	for (cur_pipe = 0; cur_pipe < num_tile_pipes; ++cur_pipe) {
646189499Srnoland		while (((1 << cur_backend) & enabled_backends_mask) == 0)
647189499Srnoland			cur_backend = (cur_backend + 1) % R6XX_MAX_BACKENDS;
648189499Srnoland
649189499Srnoland		backend_map |= (u32)(((cur_backend & 3) << (swizzle_pipe[cur_pipe] * 2)));
650189499Srnoland
651189499Srnoland		cur_backend = (cur_backend + 1) % R6XX_MAX_BACKENDS;
652189499Srnoland	}
653189499Srnoland
654189499Srnoland	return backend_map;
655189499Srnoland}
656189499Srnoland
657189499Srnolandstatic int r600_count_pipe_bits(uint32_t val)
658189499Srnoland{
659189499Srnoland	int i, ret = 0;
660189499Srnoland	for (i = 0; i < 32; i++) {
661189499Srnoland		ret += val & 1;
662189499Srnoland		val >>= 1;
663189499Srnoland	}
664189499Srnoland	return ret;
665189499Srnoland}
666189499Srnoland
667189499Srnolandstatic void r600_gfx_init(struct drm_device *dev,
668189499Srnoland			  drm_radeon_private_t *dev_priv)
669189499Srnoland{
670189499Srnoland	int i, j, num_qd_pipes;
671189499Srnoland	u32 sx_debug_1;
672189499Srnoland	u32 tc_cntl;
673189499Srnoland	u32 arb_pop;
674189499Srnoland	u32 num_gs_verts_per_thread;
675189499Srnoland	u32 vgt_gs_per_es;
676189499Srnoland	u32 gs_prim_buffer_depth = 0;
677189499Srnoland	u32 sq_ms_fifo_sizes;
678189499Srnoland	u32 sq_config;
679189499Srnoland	u32 sq_gpr_resource_mgmt_1 = 0;
680189499Srnoland	u32 sq_gpr_resource_mgmt_2 = 0;
681189499Srnoland	u32 sq_thread_resource_mgmt = 0;
682189499Srnoland	u32 sq_stack_resource_mgmt_1 = 0;
683189499Srnoland	u32 sq_stack_resource_mgmt_2 = 0;
684189499Srnoland	u32 hdp_host_path_cntl;
685189499Srnoland	u32 backend_map;
686189499Srnoland	u32 gb_tiling_config = 0;
687189499Srnoland	u32 cc_rb_backend_disable = 0;
688189499Srnoland	u32 cc_gc_shader_pipe_config = 0;
689189499Srnoland	u32 ramcfg;
690189499Srnoland
691189499Srnoland	/* setup chip specs */
692189499Srnoland	switch (dev_priv->flags & RADEON_FAMILY_MASK) {
693189499Srnoland	case CHIP_R600:
694189499Srnoland		dev_priv->r600_max_pipes = 4;
695189499Srnoland		dev_priv->r600_max_tile_pipes = 8;
696189499Srnoland		dev_priv->r600_max_simds = 4;
697189499Srnoland		dev_priv->r600_max_backends = 4;
698189499Srnoland		dev_priv->r600_max_gprs = 256;
699189499Srnoland		dev_priv->r600_max_threads = 192;
700189499Srnoland		dev_priv->r600_max_stack_entries = 256;
701189499Srnoland		dev_priv->r600_max_hw_contexts = 8;
702189499Srnoland		dev_priv->r600_max_gs_threads = 16;
703189499Srnoland		dev_priv->r600_sx_max_export_size = 128;
704189499Srnoland		dev_priv->r600_sx_max_export_pos_size = 16;
705189499Srnoland		dev_priv->r600_sx_max_export_smx_size = 128;
706189499Srnoland		dev_priv->r600_sq_num_cf_insts = 2;
707189499Srnoland		break;
708189499Srnoland	case CHIP_RV630:
709189499Srnoland	case CHIP_RV635:
710189499Srnoland		dev_priv->r600_max_pipes = 2;
711189499Srnoland		dev_priv->r600_max_tile_pipes = 2;
712189499Srnoland		dev_priv->r600_max_simds = 3;
713189499Srnoland		dev_priv->r600_max_backends = 1;
714189499Srnoland		dev_priv->r600_max_gprs = 128;
715189499Srnoland		dev_priv->r600_max_threads = 192;
716189499Srnoland		dev_priv->r600_max_stack_entries = 128;
717189499Srnoland		dev_priv->r600_max_hw_contexts = 8;
718189499Srnoland		dev_priv->r600_max_gs_threads = 4;
719189499Srnoland		dev_priv->r600_sx_max_export_size = 128;
720189499Srnoland		dev_priv->r600_sx_max_export_pos_size = 16;
721189499Srnoland		dev_priv->r600_sx_max_export_smx_size = 128;
722189499Srnoland		dev_priv->r600_sq_num_cf_insts = 2;
723189499Srnoland		break;
724189499Srnoland	case CHIP_RV610:
725189499Srnoland	case CHIP_RS780:
726196142Srnoland	case CHIP_RS880:
727189499Srnoland	case CHIP_RV620:
728189499Srnoland		dev_priv->r600_max_pipes = 1;
729189499Srnoland		dev_priv->r600_max_tile_pipes = 1;
730189499Srnoland		dev_priv->r600_max_simds = 2;
731189499Srnoland		dev_priv->r600_max_backends = 1;
732189499Srnoland		dev_priv->r600_max_gprs = 128;
733189499Srnoland		dev_priv->r600_max_threads = 192;
734189499Srnoland		dev_priv->r600_max_stack_entries = 128;
735189499Srnoland		dev_priv->r600_max_hw_contexts = 4;
736189499Srnoland		dev_priv->r600_max_gs_threads = 4;
737189499Srnoland		dev_priv->r600_sx_max_export_size = 128;
738189499Srnoland		dev_priv->r600_sx_max_export_pos_size = 16;
739189499Srnoland		dev_priv->r600_sx_max_export_smx_size = 128;
740189499Srnoland		dev_priv->r600_sq_num_cf_insts = 1;
741189499Srnoland		break;
742189499Srnoland	case CHIP_RV670:
743189499Srnoland		dev_priv->r600_max_pipes = 4;
744189499Srnoland		dev_priv->r600_max_tile_pipes = 4;
745189499Srnoland		dev_priv->r600_max_simds = 4;
746189499Srnoland		dev_priv->r600_max_backends = 4;
747189499Srnoland		dev_priv->r600_max_gprs = 192;
748189499Srnoland		dev_priv->r600_max_threads = 192;
749189499Srnoland		dev_priv->r600_max_stack_entries = 256;
750189499Srnoland		dev_priv->r600_max_hw_contexts = 8;
751189499Srnoland		dev_priv->r600_max_gs_threads = 16;
752189499Srnoland		dev_priv->r600_sx_max_export_size = 128;
753189499Srnoland		dev_priv->r600_sx_max_export_pos_size = 16;
754189499Srnoland		dev_priv->r600_sx_max_export_smx_size = 128;
755189499Srnoland		dev_priv->r600_sq_num_cf_insts = 2;
756189499Srnoland		break;
757189499Srnoland	default:
758189499Srnoland		break;
759189499Srnoland	}
760189499Srnoland
761189499Srnoland	/* Initialize HDP */
762189499Srnoland	j = 0;
763189499Srnoland	for (i = 0; i < 32; i++) {
764189499Srnoland		RADEON_WRITE((0x2c14 + j), 0x00000000);
765189499Srnoland		RADEON_WRITE((0x2c18 + j), 0x00000000);
766189499Srnoland		RADEON_WRITE((0x2c1c + j), 0x00000000);
767189499Srnoland		RADEON_WRITE((0x2c20 + j), 0x00000000);
768189499Srnoland		RADEON_WRITE((0x2c24 + j), 0x00000000);
769189499Srnoland		j += 0x18;
770189499Srnoland	}
771189499Srnoland
772189499Srnoland	RADEON_WRITE(R600_GRBM_CNTL, R600_GRBM_READ_TIMEOUT(0xff));
773189499Srnoland
774189499Srnoland	/* setup tiling, simd, pipe config */
775189499Srnoland	ramcfg = RADEON_READ(R600_RAMCFG);
776189499Srnoland
777189499Srnoland	switch (dev_priv->r600_max_tile_pipes) {
778189499Srnoland	case 1:
779189499Srnoland		gb_tiling_config |= R600_PIPE_TILING(0);
780189499Srnoland		break;
781189499Srnoland	case 2:
782189499Srnoland		gb_tiling_config |= R600_PIPE_TILING(1);
783189499Srnoland		break;
784189499Srnoland	case 4:
785189499Srnoland		gb_tiling_config |= R600_PIPE_TILING(2);
786189499Srnoland		break;
787189499Srnoland	case 8:
788189499Srnoland		gb_tiling_config |= R600_PIPE_TILING(3);
789189499Srnoland		break;
790189499Srnoland	default:
791189499Srnoland		break;
792189499Srnoland	}
793189499Srnoland
794189499Srnoland	gb_tiling_config |= R600_BANK_TILING((ramcfg >> R600_NOOFBANK_SHIFT) & R600_NOOFBANK_MASK);
795189499Srnoland
796189499Srnoland	gb_tiling_config |= R600_GROUP_SIZE(0);
797189499Srnoland
798189499Srnoland	if (((ramcfg >> R600_NOOFROWS_SHIFT) & R600_NOOFROWS_MASK) > 3) {
799189499Srnoland		gb_tiling_config |= R600_ROW_TILING(3);
800189499Srnoland		gb_tiling_config |= R600_SAMPLE_SPLIT(3);
801189499Srnoland	} else {
802189499Srnoland		gb_tiling_config |=
803189499Srnoland			R600_ROW_TILING(((ramcfg >> R600_NOOFROWS_SHIFT) & R600_NOOFROWS_MASK));
804189499Srnoland		gb_tiling_config |=
805189499Srnoland			R600_SAMPLE_SPLIT(((ramcfg >> R600_NOOFROWS_SHIFT) & R600_NOOFROWS_MASK));
806189499Srnoland	}
807189499Srnoland
808189499Srnoland	gb_tiling_config |= R600_BANK_SWAPS(1);
809189499Srnoland
810189499Srnoland	backend_map = r600_get_tile_pipe_to_backend_map(dev_priv->r600_max_tile_pipes,
811189499Srnoland							dev_priv->r600_max_backends,
812189499Srnoland							(0xff << dev_priv->r600_max_backends) & 0xff);
813189499Srnoland	gb_tiling_config |= R600_BACKEND_MAP(backend_map);
814189499Srnoland
815189499Srnoland	cc_gc_shader_pipe_config =
816189499Srnoland		R600_INACTIVE_QD_PIPES((R6XX_MAX_PIPES_MASK << dev_priv->r600_max_pipes) & R6XX_MAX_PIPES_MASK);
817189499Srnoland	cc_gc_shader_pipe_config |=
818189499Srnoland		R600_INACTIVE_SIMDS((R6XX_MAX_SIMDS_MASK << dev_priv->r600_max_simds) & R6XX_MAX_SIMDS_MASK);
819189499Srnoland
820189499Srnoland	cc_rb_backend_disable =
821189499Srnoland		R600_BACKEND_DISABLE((R6XX_MAX_BACKENDS_MASK << dev_priv->r600_max_backends) & R6XX_MAX_BACKENDS_MASK);
822189499Srnoland
823189499Srnoland	RADEON_WRITE(R600_GB_TILING_CONFIG,      gb_tiling_config);
824189499Srnoland	RADEON_WRITE(R600_DCP_TILING_CONFIG,    (gb_tiling_config & 0xffff));
825189499Srnoland	RADEON_WRITE(R600_HDP_TILING_CONFIG,    (gb_tiling_config & 0xffff));
826189499Srnoland
827189499Srnoland	RADEON_WRITE(R600_CC_RB_BACKEND_DISABLE,      cc_rb_backend_disable);
828189499Srnoland	RADEON_WRITE(R600_CC_GC_SHADER_PIPE_CONFIG,   cc_gc_shader_pipe_config);
829189499Srnoland	RADEON_WRITE(R600_GC_USER_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config);
830189499Srnoland
831189499Srnoland	num_qd_pipes =
832189499Srnoland		R6XX_MAX_BACKENDS - r600_count_pipe_bits(cc_gc_shader_pipe_config & R600_INACTIVE_QD_PIPES_MASK);
833189499Srnoland	RADEON_WRITE(R600_VGT_OUT_DEALLOC_CNTL, (num_qd_pipes * 4) & R600_DEALLOC_DIST_MASK);
834189499Srnoland	RADEON_WRITE(R600_VGT_VERTEX_REUSE_BLOCK_CNTL, ((num_qd_pipes * 4) - 2) & R600_VTX_REUSE_DEPTH_MASK);
835189499Srnoland
836189499Srnoland	/* set HW defaults for 3D engine */
837189499Srnoland	RADEON_WRITE(R600_CP_QUEUE_THRESHOLDS, (R600_ROQ_IB1_START(0x16) |
838189499Srnoland						R600_ROQ_IB2_START(0x2b)));
839189499Srnoland
840189499Srnoland	RADEON_WRITE(R600_CP_MEQ_THRESHOLDS, (R600_MEQ_END(0x40) |
841189499Srnoland					      R600_ROQ_END(0x40)));
842189499Srnoland
843189499Srnoland	RADEON_WRITE(R600_TA_CNTL_AUX, (R600_DISABLE_CUBE_ANISO |
844189499Srnoland					R600_SYNC_GRADIENT |
845189499Srnoland					R600_SYNC_WALKER |
846189499Srnoland					R600_SYNC_ALIGNER));
847189499Srnoland
848189499Srnoland	if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV670)
849189499Srnoland		RADEON_WRITE(R600_ARB_GDEC_RD_CNTL, 0x00000021);
850189499Srnoland
851189499Srnoland	sx_debug_1 = RADEON_READ(R600_SX_DEBUG_1);
852189499Srnoland	sx_debug_1 |= R600_SMX_EVENT_RELEASE;
853189499Srnoland	if (((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_R600))
854189499Srnoland		sx_debug_1 |= R600_ENABLE_NEW_SMX_ADDRESS;
855189499Srnoland	RADEON_WRITE(R600_SX_DEBUG_1, sx_debug_1);
856189499Srnoland
857189499Srnoland	if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R600) ||
858189499Srnoland	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV630) ||
859189499Srnoland	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV610) ||
860189499Srnoland	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV620) ||
861196142Srnoland	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780) ||
862196142Srnoland	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS880))
863189499Srnoland		RADEON_WRITE(R600_DB_DEBUG, R600_PREZ_MUST_WAIT_FOR_POSTZ_DONE);
864189499Srnoland	else
865189499Srnoland		RADEON_WRITE(R600_DB_DEBUG, 0);
866189499Srnoland
867189499Srnoland	RADEON_WRITE(R600_DB_WATERMARKS, (R600_DEPTH_FREE(4) |
868189499Srnoland					  R600_DEPTH_FLUSH(16) |
869189499Srnoland					  R600_DEPTH_PENDING_FREE(4) |
870189499Srnoland					  R600_DEPTH_CACHELINE_FREE(16)));
871189499Srnoland	RADEON_WRITE(R600_PA_SC_MULTI_CHIP_CNTL, 0);
872189499Srnoland	RADEON_WRITE(R600_VGT_NUM_INSTANCES, 0);
873189499Srnoland
874189499Srnoland	RADEON_WRITE(R600_SPI_CONFIG_CNTL, R600_GPR_WRITE_PRIORITY(0));
875189499Srnoland	RADEON_WRITE(R600_SPI_CONFIG_CNTL_1, R600_VTX_DONE_DELAY(0));
876189499Srnoland
877189499Srnoland	sq_ms_fifo_sizes = RADEON_READ(R600_SQ_MS_FIFO_SIZES);
878189499Srnoland	if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV610) ||
879189499Srnoland	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV620) ||
880196142Srnoland	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780) ||
881196142Srnoland	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS880)) {
882189499Srnoland		sq_ms_fifo_sizes = (R600_CACHE_FIFO_SIZE(0xa) |
883189499Srnoland				    R600_FETCH_FIFO_HIWATER(0xa) |
884189499Srnoland				    R600_DONE_FIFO_HIWATER(0xe0) |
885189499Srnoland				    R600_ALU_UPDATE_FIFO_HIWATER(0x8));
886189499Srnoland	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R600) ||
887189499Srnoland		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV630)) {
888189499Srnoland		sq_ms_fifo_sizes &= ~R600_DONE_FIFO_HIWATER(0xff);
889189499Srnoland		sq_ms_fifo_sizes |= R600_DONE_FIFO_HIWATER(0x4);
890189499Srnoland	}
891189499Srnoland	RADEON_WRITE(R600_SQ_MS_FIFO_SIZES, sq_ms_fifo_sizes);
892189499Srnoland
893189499Srnoland	/* SQ_CONFIG, SQ_GPR_RESOURCE_MGMT, SQ_THREAD_RESOURCE_MGMT, SQ_STACK_RESOURCE_MGMT
894189499Srnoland	 * should be adjusted as needed by the 2D/3D drivers.  This just sets default values
895189499Srnoland	 */
896189499Srnoland	sq_config = RADEON_READ(R600_SQ_CONFIG);
897189499Srnoland	sq_config &= ~(R600_PS_PRIO(3) |
898189499Srnoland		       R600_VS_PRIO(3) |
899189499Srnoland		       R600_GS_PRIO(3) |
900189499Srnoland		       R600_ES_PRIO(3));
901189499Srnoland	sq_config |= (R600_DX9_CONSTS |
902189499Srnoland		      R600_VC_ENABLE |
903189499Srnoland		      R600_PS_PRIO(0) |
904189499Srnoland		      R600_VS_PRIO(1) |
905189499Srnoland		      R600_GS_PRIO(2) |
906189499Srnoland		      R600_ES_PRIO(3));
907189499Srnoland
908189499Srnoland	if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R600) {
909189499Srnoland		sq_gpr_resource_mgmt_1 = (R600_NUM_PS_GPRS(124) |
910189499Srnoland					  R600_NUM_VS_GPRS(124) |
911189499Srnoland					  R600_NUM_CLAUSE_TEMP_GPRS(4));
912189499Srnoland		sq_gpr_resource_mgmt_2 = (R600_NUM_GS_GPRS(0) |
913189499Srnoland					  R600_NUM_ES_GPRS(0));
914189499Srnoland		sq_thread_resource_mgmt = (R600_NUM_PS_THREADS(136) |
915189499Srnoland					   R600_NUM_VS_THREADS(48) |
916189499Srnoland					   R600_NUM_GS_THREADS(4) |
917189499Srnoland					   R600_NUM_ES_THREADS(4));
918189499Srnoland		sq_stack_resource_mgmt_1 = (R600_NUM_PS_STACK_ENTRIES(128) |
919189499Srnoland					    R600_NUM_VS_STACK_ENTRIES(128));
920189499Srnoland		sq_stack_resource_mgmt_2 = (R600_NUM_GS_STACK_ENTRIES(0) |
921189499Srnoland					    R600_NUM_ES_STACK_ENTRIES(0));
922189499Srnoland	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV610) ||
923189499Srnoland		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV620) ||
924196142Srnoland		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780) ||
925196142Srnoland		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS880)) {
926189499Srnoland		/* no vertex cache */
927189499Srnoland		sq_config &= ~R600_VC_ENABLE;
928189499Srnoland
929189499Srnoland		sq_gpr_resource_mgmt_1 = (R600_NUM_PS_GPRS(44) |
930189499Srnoland					  R600_NUM_VS_GPRS(44) |
931189499Srnoland					  R600_NUM_CLAUSE_TEMP_GPRS(2));
932189499Srnoland		sq_gpr_resource_mgmt_2 = (R600_NUM_GS_GPRS(17) |
933189499Srnoland					  R600_NUM_ES_GPRS(17));
934189499Srnoland		sq_thread_resource_mgmt = (R600_NUM_PS_THREADS(79) |
935189499Srnoland					   R600_NUM_VS_THREADS(78) |
936189499Srnoland					   R600_NUM_GS_THREADS(4) |
937189499Srnoland					   R600_NUM_ES_THREADS(31));
938189499Srnoland		sq_stack_resource_mgmt_1 = (R600_NUM_PS_STACK_ENTRIES(40) |
939189499Srnoland					    R600_NUM_VS_STACK_ENTRIES(40));
940189499Srnoland		sq_stack_resource_mgmt_2 = (R600_NUM_GS_STACK_ENTRIES(32) |
941189499Srnoland					    R600_NUM_ES_STACK_ENTRIES(16));
942189499Srnoland	} else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV630) ||
943189499Srnoland		   ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV635)) {
944189499Srnoland		sq_gpr_resource_mgmt_1 = (R600_NUM_PS_GPRS(44) |
945189499Srnoland					  R600_NUM_VS_GPRS(44) |
946189499Srnoland					  R600_NUM_CLAUSE_TEMP_GPRS(2));
947189499Srnoland		sq_gpr_resource_mgmt_2 = (R600_NUM_GS_GPRS(18) |
948189499Srnoland					  R600_NUM_ES_GPRS(18));
949189499Srnoland		sq_thread_resource_mgmt = (R600_NUM_PS_THREADS(79) |
950189499Srnoland					   R600_NUM_VS_THREADS(78) |
951189499Srnoland					   R600_NUM_GS_THREADS(4) |
952189499Srnoland					   R600_NUM_ES_THREADS(31));
953189499Srnoland		sq_stack_resource_mgmt_1 = (R600_NUM_PS_STACK_ENTRIES(40) |
954189499Srnoland					    R600_NUM_VS_STACK_ENTRIES(40));
955189499Srnoland		sq_stack_resource_mgmt_2 = (R600_NUM_GS_STACK_ENTRIES(32) |
956189499Srnoland					    R600_NUM_ES_STACK_ENTRIES(16));
957189499Srnoland	} else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV670) {
958189499Srnoland		sq_gpr_resource_mgmt_1 = (R600_NUM_PS_GPRS(44) |
959189499Srnoland					  R600_NUM_VS_GPRS(44) |
960189499Srnoland					  R600_NUM_CLAUSE_TEMP_GPRS(2));
961189499Srnoland		sq_gpr_resource_mgmt_2 = (R600_NUM_GS_GPRS(17) |
962189499Srnoland					  R600_NUM_ES_GPRS(17));
963189499Srnoland		sq_thread_resource_mgmt = (R600_NUM_PS_THREADS(79) |
964189499Srnoland					   R600_NUM_VS_THREADS(78) |
965189499Srnoland					   R600_NUM_GS_THREADS(4) |
966189499Srnoland					   R600_NUM_ES_THREADS(31));
967189499Srnoland		sq_stack_resource_mgmt_1 = (R600_NUM_PS_STACK_ENTRIES(64) |
968189499Srnoland					    R600_NUM_VS_STACK_ENTRIES(64));
969189499Srnoland		sq_stack_resource_mgmt_2 = (R600_NUM_GS_STACK_ENTRIES(64) |
970189499Srnoland					    R600_NUM_ES_STACK_ENTRIES(64));
971189499Srnoland	}
972189499Srnoland
973189499Srnoland	RADEON_WRITE(R600_SQ_CONFIG, sq_config);
974189499Srnoland	RADEON_WRITE(R600_SQ_GPR_RESOURCE_MGMT_1,  sq_gpr_resource_mgmt_1);
975189499Srnoland	RADEON_WRITE(R600_SQ_GPR_RESOURCE_MGMT_2,  sq_gpr_resource_mgmt_2);
976189499Srnoland	RADEON_WRITE(R600_SQ_THREAD_RESOURCE_MGMT, sq_thread_resource_mgmt);
977189499Srnoland	RADEON_WRITE(R600_SQ_STACK_RESOURCE_MGMT_1, sq_stack_resource_mgmt_1);
978189499Srnoland	RADEON_WRITE(R600_SQ_STACK_RESOURCE_MGMT_2, sq_stack_resource_mgmt_2);
979189499Srnoland
980189499Srnoland	if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV610) ||
981189499Srnoland	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV620) ||
982196142Srnoland	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780) ||
983196142Srnoland	    ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS880))
984189499Srnoland		RADEON_WRITE(R600_VGT_CACHE_INVALIDATION, R600_CACHE_INVALIDATION(R600_TC_ONLY));
985189499Srnoland	else
986189499Srnoland		RADEON_WRITE(R600_VGT_CACHE_INVALIDATION, R600_CACHE_INVALIDATION(R600_VC_AND_TC));
987189499Srnoland
988189499Srnoland	RADEON_WRITE(R600_PA_SC_AA_SAMPLE_LOCS_2S, (R600_S0_X(0xc) |
989189499Srnoland						    R600_S0_Y(0x4) |
990189499Srnoland						    R600_S1_X(0x4) |
991189499Srnoland						    R600_S1_Y(0xc)));
992189499Srnoland	RADEON_WRITE(R600_PA_SC_AA_SAMPLE_LOCS_4S, (R600_S0_X(0xe) |
993189499Srnoland						    R600_S0_Y(0xe) |
994189499Srnoland						    R600_S1_X(0x2) |
995189499Srnoland						    R600_S1_Y(0x2) |
996189499Srnoland						    R600_S2_X(0xa) |
997189499Srnoland						    R600_S2_Y(0x6) |
998189499Srnoland						    R600_S3_X(0x6) |
999189499Srnoland						    R600_S3_Y(0xa)));
1000189499Srnoland	RADEON_WRITE(R600_PA_SC_AA_SAMPLE_LOCS_8S_WD0, (R600_S0_X(0xe) |
1001189499Srnoland							R600_S0_Y(0xb) |
1002189499Srnoland							R600_S1_X(0x4) |
1003189499Srnoland							R600_S1_Y(0xc) |
1004189499Srnoland							R600_S2_X(0x1) |
1005189499Srnoland							R600_S2_Y(0x6) |
1006189499Srnoland							R600_S3_X(0xa) |
1007189499Srnoland							R600_S3_Y(0xe)));
1008189499Srnoland	RADEON_WRITE(R600_PA_SC_AA_SAMPLE_LOCS_8S_WD1, (R600_S4_X(0x6) |
1009189499Srnoland							R600_S4_Y(0x1) |
1010189499Srnoland							R600_S5_X(0x0) |
1011189499Srnoland							R600_S5_Y(0x0) |
1012189499Srnoland							R600_S6_X(0xb) |
1013189499Srnoland							R600_S6_Y(0x4) |
1014189499Srnoland							R600_S7_X(0x7) |
1015189499Srnoland							R600_S7_Y(0x8)));
1016189499Srnoland
1017189499Srnoland
1018189499Srnoland	switch (dev_priv->flags & RADEON_FAMILY_MASK) {
1019189499Srnoland	case CHIP_R600:
1020189499Srnoland	case CHIP_RV630:
1021189499Srnoland	case CHIP_RV635:
1022189499Srnoland		gs_prim_buffer_depth = 0;
1023189499Srnoland		break;
1024189499Srnoland	case CHIP_RV610:
1025189499Srnoland	case CHIP_RS780:
1026196142Srnoland	case CHIP_RS880:
1027189499Srnoland	case CHIP_RV620:
1028189499Srnoland		gs_prim_buffer_depth = 32;
1029189499Srnoland		break;
1030189499Srnoland	case CHIP_RV670:
1031189499Srnoland		gs_prim_buffer_depth = 128;
1032189499Srnoland		break;
1033189499Srnoland	default:
1034189499Srnoland		break;
1035189499Srnoland	}
1036189499Srnoland
1037189499Srnoland	num_gs_verts_per_thread = dev_priv->r600_max_pipes * 16;
1038189499Srnoland	vgt_gs_per_es = gs_prim_buffer_depth + num_gs_verts_per_thread;
1039189499Srnoland	/* Max value for this is 256 */
1040189499Srnoland	if (vgt_gs_per_es > 256)
1041189499Srnoland		vgt_gs_per_es = 256;
1042189499Srnoland
1043189499Srnoland	RADEON_WRITE(R600_VGT_ES_PER_GS, 128);
1044189499Srnoland	RADEON_WRITE(R600_VGT_GS_PER_ES, vgt_gs_per_es);
1045189499Srnoland	RADEON_WRITE(R600_VGT_GS_PER_VS, 2);
1046189499Srnoland	RADEON_WRITE(R600_VGT_GS_VERTEX_REUSE, 16);
1047189499Srnoland
1048189499Srnoland	/* more default values. 2D/3D driver should adjust as needed */
1049189499Srnoland	RADEON_WRITE(R600_PA_SC_LINE_STIPPLE_STATE, 0);
1050189499Srnoland	RADEON_WRITE(R600_VGT_STRMOUT_EN, 0);
1051189499Srnoland	RADEON_WRITE(R600_SX_MISC, 0);
1052189499Srnoland	RADEON_WRITE(R600_PA_SC_MODE_CNTL, 0);
1053189499Srnoland	RADEON_WRITE(R600_PA_SC_AA_CONFIG, 0);
1054189499Srnoland	RADEON_WRITE(R600_PA_SC_LINE_STIPPLE, 0);
1055189499Srnoland	RADEON_WRITE(R600_SPI_INPUT_Z, 0);
1056189499Srnoland	RADEON_WRITE(R600_SPI_PS_IN_CONTROL_0, R600_NUM_INTERP(2));
1057189499Srnoland	RADEON_WRITE(R600_CB_COLOR7_FRAG, 0);
1058189499Srnoland
1059189499Srnoland	/* clear render buffer base addresses */
1060189499Srnoland	RADEON_WRITE(R600_CB_COLOR0_BASE, 0);
1061189499Srnoland	RADEON_WRITE(R600_CB_COLOR1_BASE, 0);
1062189499Srnoland	RADEON_WRITE(R600_CB_COLOR2_BASE, 0);
1063189499Srnoland	RADEON_WRITE(R600_CB_COLOR3_BASE, 0);
1064189499Srnoland	RADEON_WRITE(R600_CB_COLOR4_BASE, 0);
1065189499Srnoland	RADEON_WRITE(R600_CB_COLOR5_BASE, 0);
1066189499Srnoland	RADEON_WRITE(R600_CB_COLOR6_BASE, 0);
1067189499Srnoland	RADEON_WRITE(R600_CB_COLOR7_BASE, 0);
1068189499Srnoland
1069189499Srnoland	switch (dev_priv->flags & RADEON_FAMILY_MASK) {
1070189499Srnoland	case CHIP_RV610:
1071189499Srnoland	case CHIP_RS780:
1072196142Srnoland	case CHIP_RS880:
1073189499Srnoland	case CHIP_RV620:
1074189499Srnoland		tc_cntl = R600_TC_L2_SIZE(8);
1075189499Srnoland		break;
1076189499Srnoland	case CHIP_RV630:
1077189499Srnoland	case CHIP_RV635:
1078189499Srnoland		tc_cntl = R600_TC_L2_SIZE(4);
1079189499Srnoland		break;
1080189499Srnoland	case CHIP_R600:
1081189499Srnoland		tc_cntl = R600_TC_L2_SIZE(0) | R600_L2_DISABLE_LATE_HIT;
1082189499Srnoland		break;
1083189499Srnoland	default:
1084189499Srnoland		tc_cntl = R600_TC_L2_SIZE(0);
1085189499Srnoland		break;
1086189499Srnoland	}
1087189499Srnoland
1088189499Srnoland	RADEON_WRITE(R600_TC_CNTL, tc_cntl);
1089189499Srnoland
1090189499Srnoland	hdp_host_path_cntl = RADEON_READ(R600_HDP_HOST_PATH_CNTL);
1091189499Srnoland	RADEON_WRITE(R600_HDP_HOST_PATH_CNTL, hdp_host_path_cntl);
1092189499Srnoland
1093189499Srnoland	arb_pop = RADEON_READ(R600_ARB_POP);
1094189499Srnoland	arb_pop |= R600_ENABLE_TC128;
1095189499Srnoland	RADEON_WRITE(R600_ARB_POP, arb_pop);
1096189499Srnoland
1097189499Srnoland	RADEON_WRITE(R600_PA_SC_MULTI_CHIP_CNTL, 0);
1098189499Srnoland	RADEON_WRITE(R600_PA_CL_ENHANCE, (R600_CLIP_VTX_REORDER_ENA |
1099189499Srnoland					  R600_NUM_CLIP_SEQ(3)));
1100189499Srnoland	RADEON_WRITE(R600_PA_SC_ENHANCE, R600_FORCE_EOV_MAX_CLK_CNT(4095));
1101189499Srnoland
1102189499Srnoland}
1103189499Srnoland
1104189499Srnolandstatic u32 r700_get_tile_pipe_to_backend_map(u32 num_tile_pipes,
1105189499Srnoland					     u32 num_backends,
1106189499Srnoland					     u32 backend_disable_mask)
1107189499Srnoland{
1108189499Srnoland	u32 backend_map = 0;
1109189499Srnoland	u32 enabled_backends_mask;
1110189499Srnoland	u32 enabled_backends_count;
1111189499Srnoland	u32 cur_pipe;
1112189499Srnoland	u32 swizzle_pipe[R7XX_MAX_PIPES];
1113189499Srnoland	u32 cur_backend;
1114189499Srnoland	u32 i;
1115189499Srnoland
1116189499Srnoland	if (num_tile_pipes > R7XX_MAX_PIPES)
1117189499Srnoland		num_tile_pipes = R7XX_MAX_PIPES;
1118189499Srnoland	if (num_tile_pipes < 1)
1119189499Srnoland		num_tile_pipes = 1;
1120189499Srnoland	if (num_backends > R7XX_MAX_BACKENDS)
1121189499Srnoland		num_backends = R7XX_MAX_BACKENDS;
1122189499Srnoland	if (num_backends < 1)
1123189499Srnoland		num_backends = 1;
1124189499Srnoland
1125189499Srnoland	enabled_backends_mask = 0;
1126189499Srnoland	enabled_backends_count = 0;
1127189499Srnoland	for (i = 0; i < R7XX_MAX_BACKENDS; ++i) {
1128189499Srnoland		if (((backend_disable_mask >> i) & 1) == 0) {
1129189499Srnoland			enabled_backends_mask |= (1 << i);
1130189499Srnoland			++enabled_backends_count;
1131189499Srnoland		}
1132189499Srnoland		if (enabled_backends_count == num_backends)
1133189499Srnoland			break;
1134189499Srnoland	}
1135189499Srnoland
1136189499Srnoland	if (enabled_backends_count == 0) {
1137189499Srnoland		enabled_backends_mask = 1;
1138189499Srnoland		enabled_backends_count = 1;
1139189499Srnoland	}
1140189499Srnoland
1141189499Srnoland	if (enabled_backends_count != num_backends)
1142189499Srnoland		num_backends = enabled_backends_count;
1143189499Srnoland
1144189499Srnoland	memset((uint8_t *)&swizzle_pipe[0], 0, sizeof(u32) * R7XX_MAX_PIPES);
1145189499Srnoland	switch (num_tile_pipes) {
1146189499Srnoland	case 1:
1147189499Srnoland		swizzle_pipe[0] = 0;
1148189499Srnoland		break;
1149189499Srnoland	case 2:
1150189499Srnoland		swizzle_pipe[0] = 0;
1151189499Srnoland		swizzle_pipe[1] = 1;
1152189499Srnoland		break;
1153189499Srnoland	case 3:
1154189499Srnoland		swizzle_pipe[0] = 0;
1155189499Srnoland		swizzle_pipe[1] = 2;
1156189499Srnoland		swizzle_pipe[2] = 1;
1157189499Srnoland		break;
1158189499Srnoland	case 4:
1159189499Srnoland		swizzle_pipe[0] = 0;
1160189499Srnoland		swizzle_pipe[1] = 2;
1161189499Srnoland		swizzle_pipe[2] = 3;
1162189499Srnoland		swizzle_pipe[3] = 1;
1163189499Srnoland		break;
1164189499Srnoland	case 5:
1165189499Srnoland		swizzle_pipe[0] = 0;
1166189499Srnoland		swizzle_pipe[1] = 2;
1167189499Srnoland		swizzle_pipe[2] = 4;
1168189499Srnoland		swizzle_pipe[3] = 1;
1169189499Srnoland		swizzle_pipe[4] = 3;
1170189499Srnoland		break;
1171189499Srnoland	case 6:
1172189499Srnoland		swizzle_pipe[0] = 0;
1173189499Srnoland		swizzle_pipe[1] = 2;
1174189499Srnoland		swizzle_pipe[2] = 4;
1175189499Srnoland		swizzle_pipe[3] = 5;
1176189499Srnoland		swizzle_pipe[4] = 3;
1177189499Srnoland		swizzle_pipe[5] = 1;
1178189499Srnoland		break;
1179189499Srnoland	case 7:
1180189499Srnoland		swizzle_pipe[0] = 0;
1181189499Srnoland		swizzle_pipe[1] = 2;
1182189499Srnoland		swizzle_pipe[2] = 4;
1183189499Srnoland		swizzle_pipe[3] = 6;
1184189499Srnoland		swizzle_pipe[4] = 3;
1185189499Srnoland		swizzle_pipe[5] = 1;
1186189499Srnoland		swizzle_pipe[6] = 5;
1187189499Srnoland		break;
1188189499Srnoland	case 8:
1189189499Srnoland		swizzle_pipe[0] = 0;
1190189499Srnoland		swizzle_pipe[1] = 2;
1191189499Srnoland		swizzle_pipe[2] = 4;
1192189499Srnoland		swizzle_pipe[3] = 6;
1193189499Srnoland		swizzle_pipe[4] = 3;
1194189499Srnoland		swizzle_pipe[5] = 1;
1195189499Srnoland		swizzle_pipe[6] = 7;
1196189499Srnoland		swizzle_pipe[7] = 5;
1197189499Srnoland		break;
1198189499Srnoland	}
1199189499Srnoland
1200189499Srnoland	cur_backend = 0;
1201189499Srnoland	for (cur_pipe = 0; cur_pipe < num_tile_pipes; ++cur_pipe) {
1202189499Srnoland		while (((1 << cur_backend) & enabled_backends_mask) == 0)
1203189499Srnoland			cur_backend = (cur_backend + 1) % R7XX_MAX_BACKENDS;
1204189499Srnoland
1205189499Srnoland		backend_map |= (u32)(((cur_backend & 3) << (swizzle_pipe[cur_pipe] * 2)));
1206189499Srnoland
1207189499Srnoland		cur_backend = (cur_backend + 1) % R7XX_MAX_BACKENDS;
1208189499Srnoland	}
1209189499Srnoland
1210189499Srnoland	return backend_map;
1211189499Srnoland}
1212189499Srnoland
1213189499Srnolandstatic void r700_gfx_init(struct drm_device *dev,
1214189499Srnoland			  drm_radeon_private_t *dev_priv)
1215189499Srnoland{
1216189499Srnoland	int i, j, num_qd_pipes;
1217189499Srnoland	u32 sx_debug_1;
1218189499Srnoland	u32 smx_dc_ctl0;
1219189499Srnoland	u32 num_gs_verts_per_thread;
1220189499Srnoland	u32 vgt_gs_per_es;
1221189499Srnoland	u32 gs_prim_buffer_depth = 0;
1222189499Srnoland	u32 sq_ms_fifo_sizes;
1223189499Srnoland	u32 sq_config;
1224189499Srnoland	u32 sq_thread_resource_mgmt;
1225189499Srnoland	u32 hdp_host_path_cntl;
1226189499Srnoland	u32 sq_dyn_gpr_size_simd_ab_0;
1227189499Srnoland	u32 backend_map;
1228189499Srnoland	u32 gb_tiling_config = 0;
1229189499Srnoland	u32 cc_rb_backend_disable = 0;
1230189499Srnoland	u32 cc_gc_shader_pipe_config = 0;
1231189499Srnoland	u32 mc_arb_ramcfg;
1232189499Srnoland	u32 db_debug4;
1233189499Srnoland
1234189499Srnoland	/* setup chip specs */
1235189499Srnoland	switch (dev_priv->flags & RADEON_FAMILY_MASK) {
1236189499Srnoland	case CHIP_RV770:
1237189499Srnoland		dev_priv->r600_max_pipes = 4;
1238189499Srnoland		dev_priv->r600_max_tile_pipes = 8;
1239189499Srnoland		dev_priv->r600_max_simds = 10;
1240189499Srnoland		dev_priv->r600_max_backends = 4;
1241189499Srnoland		dev_priv->r600_max_gprs = 256;
1242189499Srnoland		dev_priv->r600_max_threads = 248;
1243189499Srnoland		dev_priv->r600_max_stack_entries = 512;
1244189499Srnoland		dev_priv->r600_max_hw_contexts = 8;
1245189499Srnoland		dev_priv->r600_max_gs_threads = 16 * 2;
1246189499Srnoland		dev_priv->r600_sx_max_export_size = 128;
1247189499Srnoland		dev_priv->r600_sx_max_export_pos_size = 16;
1248189499Srnoland		dev_priv->r600_sx_max_export_smx_size = 112;
1249189499Srnoland		dev_priv->r600_sq_num_cf_insts = 2;
1250189499Srnoland
1251189499Srnoland		dev_priv->r700_sx_num_of_sets = 7;
1252189499Srnoland		dev_priv->r700_sc_prim_fifo_size = 0xF9;
1253189499Srnoland		dev_priv->r700_sc_hiz_tile_fifo_size = 0x30;
1254189499Srnoland		dev_priv->r700_sc_earlyz_tile_fifo_fize = 0x130;
1255189499Srnoland		break;
1256195501Srnoland	case CHIP_RV740:
1257195501Srnoland		dev_priv->r600_max_pipes = 4;
1258195501Srnoland		dev_priv->r600_max_tile_pipes = 4;
1259195501Srnoland		dev_priv->r600_max_simds = 8;
1260195501Srnoland		dev_priv->r600_max_backends = 4;
1261195501Srnoland		dev_priv->r600_max_gprs = 256;
1262195501Srnoland		dev_priv->r600_max_threads = 248;
1263195501Srnoland		dev_priv->r600_max_stack_entries = 512;
1264195501Srnoland		dev_priv->r600_max_hw_contexts = 8;
1265195501Srnoland		dev_priv->r600_max_gs_threads = 16 * 2;
1266195501Srnoland		dev_priv->r600_sx_max_export_size = 256;
1267195501Srnoland		dev_priv->r600_sx_max_export_pos_size = 32;
1268195501Srnoland		dev_priv->r600_sx_max_export_smx_size = 224;
1269195501Srnoland		dev_priv->r600_sq_num_cf_insts = 2;
1270195501Srnoland
1271195501Srnoland		dev_priv->r700_sx_num_of_sets = 7;
1272195501Srnoland		dev_priv->r700_sc_prim_fifo_size = 0x100;
1273195501Srnoland		dev_priv->r700_sc_hiz_tile_fifo_size = 0x30;
1274195501Srnoland		dev_priv->r700_sc_earlyz_tile_fifo_fize = 0x130;
1275195501Srnoland
1276195501Srnoland		if (dev_priv->r600_sx_max_export_pos_size > 16) {
1277195501Srnoland			dev_priv->r600_sx_max_export_pos_size -= 16;
1278195501Srnoland			dev_priv->r600_sx_max_export_smx_size += 16;
1279195501Srnoland		}
1280195501Srnoland		break;
1281189499Srnoland	case CHIP_RV730:
1282189499Srnoland		dev_priv->r600_max_pipes = 2;
1283189499Srnoland		dev_priv->r600_max_tile_pipes = 4;
1284189499Srnoland		dev_priv->r600_max_simds = 8;
1285189499Srnoland		dev_priv->r600_max_backends = 2;
1286189499Srnoland		dev_priv->r600_max_gprs = 128;
1287189499Srnoland		dev_priv->r600_max_threads = 248;
1288189499Srnoland		dev_priv->r600_max_stack_entries = 256;
1289189499Srnoland		dev_priv->r600_max_hw_contexts = 8;
1290189499Srnoland		dev_priv->r600_max_gs_threads = 16 * 2;
1291189499Srnoland		dev_priv->r600_sx_max_export_size = 256;
1292189499Srnoland		dev_priv->r600_sx_max_export_pos_size = 32;
1293189499Srnoland		dev_priv->r600_sx_max_export_smx_size = 224;
1294189499Srnoland		dev_priv->r600_sq_num_cf_insts = 2;
1295189499Srnoland
1296189499Srnoland		dev_priv->r700_sx_num_of_sets = 7;
1297189499Srnoland		dev_priv->r700_sc_prim_fifo_size = 0xf9;
1298189499Srnoland		dev_priv->r700_sc_hiz_tile_fifo_size = 0x30;
1299189499Srnoland		dev_priv->r700_sc_earlyz_tile_fifo_fize = 0x130;
1300195501Srnoland
1301195501Srnoland		if (dev_priv->r600_sx_max_export_pos_size > 16) {
1302195501Srnoland			dev_priv->r600_sx_max_export_pos_size -= 16;
1303195501Srnoland			dev_priv->r600_sx_max_export_smx_size += 16;
1304195501Srnoland		}
1305189499Srnoland		break;
1306189499Srnoland	case CHIP_RV710:
1307189499Srnoland		dev_priv->r600_max_pipes = 2;
1308189499Srnoland		dev_priv->r600_max_tile_pipes = 2;
1309189499Srnoland		dev_priv->r600_max_simds = 2;
1310189499Srnoland		dev_priv->r600_max_backends = 1;
1311189499Srnoland		dev_priv->r600_max_gprs = 256;
1312189499Srnoland		dev_priv->r600_max_threads = 192;
1313189499Srnoland		dev_priv->r600_max_stack_entries = 256;
1314189499Srnoland		dev_priv->r600_max_hw_contexts = 4;
1315189499Srnoland		dev_priv->r600_max_gs_threads = 8 * 2;
1316189499Srnoland		dev_priv->r600_sx_max_export_size = 128;
1317189499Srnoland		dev_priv->r600_sx_max_export_pos_size = 16;
1318189499Srnoland		dev_priv->r600_sx_max_export_smx_size = 112;
1319189499Srnoland		dev_priv->r600_sq_num_cf_insts = 1;
1320189499Srnoland
1321189499Srnoland		dev_priv->r700_sx_num_of_sets = 7;
1322189499Srnoland		dev_priv->r700_sc_prim_fifo_size = 0x40;
1323189499Srnoland		dev_priv->r700_sc_hiz_tile_fifo_size = 0x30;
1324189499Srnoland		dev_priv->r700_sc_earlyz_tile_fifo_fize = 0x130;
1325189499Srnoland		break;
1326189499Srnoland	default:
1327189499Srnoland		break;
1328189499Srnoland	}
1329189499Srnoland
1330189499Srnoland	/* Initialize HDP */
1331189499Srnoland	j = 0;
1332189499Srnoland	for (i = 0; i < 32; i++) {
1333189499Srnoland		RADEON_WRITE((0x2c14 + j), 0x00000000);
1334189499Srnoland		RADEON_WRITE((0x2c18 + j), 0x00000000);
1335189499Srnoland		RADEON_WRITE((0x2c1c + j), 0x00000000);
1336189499Srnoland		RADEON_WRITE((0x2c20 + j), 0x00000000);
1337189499Srnoland		RADEON_WRITE((0x2c24 + j), 0x00000000);
1338189499Srnoland		j += 0x18;
1339189499Srnoland	}
1340189499Srnoland
1341189499Srnoland	RADEON_WRITE(R600_GRBM_CNTL, R600_GRBM_READ_TIMEOUT(0xff));
1342189499Srnoland
1343189499Srnoland	/* setup tiling, simd, pipe config */
1344189499Srnoland	mc_arb_ramcfg = RADEON_READ(R700_MC_ARB_RAMCFG);
1345189499Srnoland
1346189499Srnoland	switch (dev_priv->r600_max_tile_pipes) {
1347189499Srnoland	case 1:
1348189499Srnoland		gb_tiling_config |= R600_PIPE_TILING(0);
1349189499Srnoland		break;
1350189499Srnoland	case 2:
1351189499Srnoland		gb_tiling_config |= R600_PIPE_TILING(1);
1352189499Srnoland		break;
1353189499Srnoland	case 4:
1354189499Srnoland		gb_tiling_config |= R600_PIPE_TILING(2);
1355189499Srnoland		break;
1356189499Srnoland	case 8:
1357189499Srnoland		gb_tiling_config |= R600_PIPE_TILING(3);
1358189499Srnoland		break;
1359189499Srnoland	default:
1360189499Srnoland		break;
1361189499Srnoland	}
1362189499Srnoland
1363189499Srnoland	if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV770)
1364189499Srnoland		gb_tiling_config |= R600_BANK_TILING(1);
1365189499Srnoland	else
1366189499Srnoland		gb_tiling_config |= R600_BANK_TILING((mc_arb_ramcfg >> R700_NOOFBANK_SHIFT) & R700_NOOFBANK_MASK);
1367189499Srnoland
1368189499Srnoland	gb_tiling_config |= R600_GROUP_SIZE(0);
1369189499Srnoland
1370189499Srnoland	if (((mc_arb_ramcfg >> R700_NOOFROWS_SHIFT) & R700_NOOFROWS_MASK) > 3) {
1371189499Srnoland		gb_tiling_config |= R600_ROW_TILING(3);
1372189499Srnoland		gb_tiling_config |= R600_SAMPLE_SPLIT(3);
1373189499Srnoland	} else {
1374189499Srnoland		gb_tiling_config |=
1375189499Srnoland			R600_ROW_TILING(((mc_arb_ramcfg >> R700_NOOFROWS_SHIFT) & R700_NOOFROWS_MASK));
1376189499Srnoland		gb_tiling_config |=
1377189499Srnoland			R600_SAMPLE_SPLIT(((mc_arb_ramcfg >> R700_NOOFROWS_SHIFT) & R700_NOOFROWS_MASK));
1378189499Srnoland	}
1379189499Srnoland
1380189499Srnoland	gb_tiling_config |= R600_BANK_SWAPS(1);
1381189499Srnoland
1382189499Srnoland	backend_map = r700_get_tile_pipe_to_backend_map(dev_priv->r600_max_tile_pipes,
1383189499Srnoland							dev_priv->r600_max_backends,
1384189499Srnoland							(0xff << dev_priv->r600_max_backends) & 0xff);
1385189499Srnoland	gb_tiling_config |= R600_BACKEND_MAP(backend_map);
1386189499Srnoland
1387189499Srnoland	cc_gc_shader_pipe_config =
1388189499Srnoland		R600_INACTIVE_QD_PIPES((R7XX_MAX_PIPES_MASK << dev_priv->r600_max_pipes) & R7XX_MAX_PIPES_MASK);
1389189499Srnoland	cc_gc_shader_pipe_config |=
1390189499Srnoland		R600_INACTIVE_SIMDS((R7XX_MAX_SIMDS_MASK << dev_priv->r600_max_simds) & R7XX_MAX_SIMDS_MASK);
1391189499Srnoland
1392189499Srnoland	cc_rb_backend_disable =
1393189499Srnoland		R600_BACKEND_DISABLE((R7XX_MAX_BACKENDS_MASK << dev_priv->r600_max_backends) & R7XX_MAX_BACKENDS_MASK);
1394189499Srnoland
1395189499Srnoland	RADEON_WRITE(R600_GB_TILING_CONFIG,      gb_tiling_config);
1396189499Srnoland	RADEON_WRITE(R600_DCP_TILING_CONFIG,    (gb_tiling_config & 0xffff));
1397189499Srnoland	RADEON_WRITE(R600_HDP_TILING_CONFIG,    (gb_tiling_config & 0xffff));
1398189499Srnoland
1399189499Srnoland	RADEON_WRITE(R600_CC_RB_BACKEND_DISABLE,      cc_rb_backend_disable);
1400189499Srnoland	RADEON_WRITE(R600_CC_GC_SHADER_PIPE_CONFIG,   cc_gc_shader_pipe_config);
1401189499Srnoland	RADEON_WRITE(R600_GC_USER_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config);
1402189499Srnoland
1403189499Srnoland	RADEON_WRITE(R700_CC_SYS_RB_BACKEND_DISABLE, cc_rb_backend_disable);
1404189499Srnoland	RADEON_WRITE(R700_CGTS_SYS_TCC_DISABLE, 0);
1405189499Srnoland	RADEON_WRITE(R700_CGTS_TCC_DISABLE, 0);
1406189499Srnoland	RADEON_WRITE(R700_CGTS_USER_SYS_TCC_DISABLE, 0);
1407189499Srnoland	RADEON_WRITE(R700_CGTS_USER_TCC_DISABLE, 0);
1408189499Srnoland
1409189499Srnoland	num_qd_pipes =
1410189499Srnoland		R7XX_MAX_BACKENDS - r600_count_pipe_bits(cc_gc_shader_pipe_config & R600_INACTIVE_QD_PIPES_MASK);
1411189499Srnoland	RADEON_WRITE(R600_VGT_OUT_DEALLOC_CNTL, (num_qd_pipes * 4) & R600_DEALLOC_DIST_MASK);
1412189499Srnoland	RADEON_WRITE(R600_VGT_VERTEX_REUSE_BLOCK_CNTL, ((num_qd_pipes * 4) - 2) & R600_VTX_REUSE_DEPTH_MASK);
1413189499Srnoland
1414189499Srnoland	/* set HW defaults for 3D engine */
1415189499Srnoland	RADEON_WRITE(R600_CP_QUEUE_THRESHOLDS, (R600_ROQ_IB1_START(0x16) |
1416189499Srnoland						R600_ROQ_IB2_START(0x2b)));
1417189499Srnoland
1418189499Srnoland	RADEON_WRITE(R600_CP_MEQ_THRESHOLDS, R700_STQ_SPLIT(0x30));
1419189499Srnoland
1420189499Srnoland	RADEON_WRITE(R600_TA_CNTL_AUX, (R600_DISABLE_CUBE_ANISO |
1421189499Srnoland					R600_SYNC_GRADIENT |
1422189499Srnoland					R600_SYNC_WALKER |
1423189499Srnoland					R600_SYNC_ALIGNER));
1424189499Srnoland
1425189499Srnoland	sx_debug_1 = RADEON_READ(R700_SX_DEBUG_1);
1426189499Srnoland	sx_debug_1 |= R700_ENABLE_NEW_SMX_ADDRESS;
1427189499Srnoland	RADEON_WRITE(R700_SX_DEBUG_1, sx_debug_1);
1428189499Srnoland
1429189499Srnoland	smx_dc_ctl0 = RADEON_READ(R600_SMX_DC_CTL0);
1430189499Srnoland	smx_dc_ctl0 &= ~R700_CACHE_DEPTH(0x1ff);
1431189499Srnoland	smx_dc_ctl0 |= R700_CACHE_DEPTH((dev_priv->r700_sx_num_of_sets * 64) - 1);
1432189499Srnoland	RADEON_WRITE(R600_SMX_DC_CTL0, smx_dc_ctl0);
1433189499Srnoland
1434189499Srnoland	RADEON_WRITE(R700_SMX_EVENT_CTL, (R700_ES_FLUSH_CTL(4) |
1435189499Srnoland					  R700_GS_FLUSH_CTL(4) |
1436189499Srnoland					  R700_ACK_FLUSH_CTL(3) |
1437189499Srnoland					  R700_SYNC_FLUSH_CTL));
1438189499Srnoland
1439189499Srnoland	if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV770)
1440189499Srnoland		RADEON_WRITE(R700_DB_DEBUG3, R700_DB_CLK_OFF_DELAY(0x1f));
1441189499Srnoland	else {
1442189499Srnoland		db_debug4 = RADEON_READ(RV700_DB_DEBUG4);
1443189499Srnoland		db_debug4 |= RV700_DISABLE_TILE_COVERED_FOR_PS_ITER;
1444189499Srnoland		RADEON_WRITE(RV700_DB_DEBUG4, db_debug4);
1445189499Srnoland	}
1446189499Srnoland
1447189499Srnoland	RADEON_WRITE(R600_SX_EXPORT_BUFFER_SIZES, (R600_COLOR_BUFFER_SIZE((dev_priv->r600_sx_max_export_size / 4) - 1) |
1448189499Srnoland						   R600_POSITION_BUFFER_SIZE((dev_priv->r600_sx_max_export_pos_size / 4) - 1) |
1449189499Srnoland						   R600_SMX_BUFFER_SIZE((dev_priv->r600_sx_max_export_smx_size / 4) - 1)));
1450189499Srnoland
1451189499Srnoland	RADEON_WRITE(R700_PA_SC_FIFO_SIZE_R7XX, (R700_SC_PRIM_FIFO_SIZE(dev_priv->r700_sc_prim_fifo_size) |
1452189499Srnoland						 R700_SC_HIZ_TILE_FIFO_SIZE(dev_priv->r700_sc_hiz_tile_fifo_size) |
1453189499Srnoland						 R700_SC_EARLYZ_TILE_FIFO_SIZE(dev_priv->r700_sc_earlyz_tile_fifo_fize)));
1454189499Srnoland
1455189499Srnoland	RADEON_WRITE(R600_PA_SC_MULTI_CHIP_CNTL, 0);
1456189499Srnoland
1457189499Srnoland	RADEON_WRITE(R600_VGT_NUM_INSTANCES, 1);
1458189499Srnoland
1459189499Srnoland	RADEON_WRITE(R600_SPI_CONFIG_CNTL, R600_GPR_WRITE_PRIORITY(0));
1460189499Srnoland
1461189499Srnoland	RADEON_WRITE(R600_SPI_CONFIG_CNTL_1, R600_VTX_DONE_DELAY(4));
1462189499Srnoland
1463189499Srnoland	RADEON_WRITE(R600_CP_PERFMON_CNTL, 0);
1464189499Srnoland
1465189499Srnoland	sq_ms_fifo_sizes = (R600_CACHE_FIFO_SIZE(16 * dev_priv->r600_sq_num_cf_insts) |
1466189499Srnoland			    R600_DONE_FIFO_HIWATER(0xe0) |
1467189499Srnoland			    R600_ALU_UPDATE_FIFO_HIWATER(0x8));
1468189499Srnoland	switch (dev_priv->flags & RADEON_FAMILY_MASK) {
1469189499Srnoland	case CHIP_RV770:
1470189499Srnoland		sq_ms_fifo_sizes |= R600_FETCH_FIFO_HIWATER(0x1);
1471189499Srnoland		break;
1472195501Srnoland	case CHIP_RV740:
1473189499Srnoland	case CHIP_RV730:
1474189499Srnoland	case CHIP_RV710:
1475189499Srnoland	default:
1476189499Srnoland		sq_ms_fifo_sizes |= R600_FETCH_FIFO_HIWATER(0x4);
1477189499Srnoland		break;
1478189499Srnoland	}
1479189499Srnoland	RADEON_WRITE(R600_SQ_MS_FIFO_SIZES, sq_ms_fifo_sizes);
1480189499Srnoland
1481189499Srnoland	/* SQ_CONFIG, SQ_GPR_RESOURCE_MGMT, SQ_THREAD_RESOURCE_MGMT, SQ_STACK_RESOURCE_MGMT
1482189499Srnoland	 * should be adjusted as needed by the 2D/3D drivers.  This just sets default values
1483189499Srnoland	 */
1484189499Srnoland	sq_config = RADEON_READ(R600_SQ_CONFIG);
1485189499Srnoland	sq_config &= ~(R600_PS_PRIO(3) |
1486189499Srnoland		       R600_VS_PRIO(3) |
1487189499Srnoland		       R600_GS_PRIO(3) |
1488189499Srnoland		       R600_ES_PRIO(3));
1489189499Srnoland	sq_config |= (R600_DX9_CONSTS |
1490189499Srnoland		      R600_VC_ENABLE |
1491189499Srnoland		      R600_EXPORT_SRC_C |
1492189499Srnoland		      R600_PS_PRIO(0) |
1493189499Srnoland		      R600_VS_PRIO(1) |
1494189499Srnoland		      R600_GS_PRIO(2) |
1495189499Srnoland		      R600_ES_PRIO(3));
1496189499Srnoland	if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV710)
1497189499Srnoland		/* no vertex cache */
1498189499Srnoland		sq_config &= ~R600_VC_ENABLE;
1499189499Srnoland
1500189499Srnoland	RADEON_WRITE(R600_SQ_CONFIG, sq_config);
1501189499Srnoland
1502189499Srnoland	RADEON_WRITE(R600_SQ_GPR_RESOURCE_MGMT_1,  (R600_NUM_PS_GPRS((dev_priv->r600_max_gprs * 24)/64) |
1503189499Srnoland						    R600_NUM_VS_GPRS((dev_priv->r600_max_gprs * 24)/64) |
1504189499Srnoland						    R600_NUM_CLAUSE_TEMP_GPRS(((dev_priv->r600_max_gprs * 24)/64)/2)));
1505189499Srnoland
1506189499Srnoland	RADEON_WRITE(R600_SQ_GPR_RESOURCE_MGMT_2,  (R600_NUM_GS_GPRS((dev_priv->r600_max_gprs * 7)/64) |
1507189499Srnoland						    R600_NUM_ES_GPRS((dev_priv->r600_max_gprs * 7)/64)));
1508189499Srnoland
1509189499Srnoland	sq_thread_resource_mgmt = (R600_NUM_PS_THREADS((dev_priv->r600_max_threads * 4)/8) |
1510189499Srnoland				   R600_NUM_VS_THREADS((dev_priv->r600_max_threads * 2)/8) |
1511189499Srnoland				   R600_NUM_ES_THREADS((dev_priv->r600_max_threads * 1)/8));
1512189499Srnoland	if (((dev_priv->r600_max_threads * 1) / 8) > dev_priv->r600_max_gs_threads)
1513189499Srnoland		sq_thread_resource_mgmt |= R600_NUM_GS_THREADS(dev_priv->r600_max_gs_threads);
1514189499Srnoland	else
1515189499Srnoland		sq_thread_resource_mgmt |= R600_NUM_GS_THREADS((dev_priv->r600_max_gs_threads * 1)/8);
1516189499Srnoland	RADEON_WRITE(R600_SQ_THREAD_RESOURCE_MGMT, sq_thread_resource_mgmt);
1517189499Srnoland
1518189499Srnoland	RADEON_WRITE(R600_SQ_STACK_RESOURCE_MGMT_1, (R600_NUM_PS_STACK_ENTRIES((dev_priv->r600_max_stack_entries * 1)/4) |
1519189499Srnoland						     R600_NUM_VS_STACK_ENTRIES((dev_priv->r600_max_stack_entries * 1)/4)));
1520189499Srnoland
1521189499Srnoland	RADEON_WRITE(R600_SQ_STACK_RESOURCE_MGMT_2, (R600_NUM_GS_STACK_ENTRIES((dev_priv->r600_max_stack_entries * 1)/4) |
1522189499Srnoland						     R600_NUM_ES_STACK_ENTRIES((dev_priv->r600_max_stack_entries * 1)/4)));
1523189499Srnoland
1524189499Srnoland	sq_dyn_gpr_size_simd_ab_0 = (R700_SIMDA_RING0((dev_priv->r600_max_gprs * 38)/64) |
1525189499Srnoland				     R700_SIMDA_RING1((dev_priv->r600_max_gprs * 38)/64) |
1526189499Srnoland				     R700_SIMDB_RING0((dev_priv->r600_max_gprs * 38)/64) |
1527189499Srnoland				     R700_SIMDB_RING1((dev_priv->r600_max_gprs * 38)/64));
1528189499Srnoland
1529189499Srnoland	RADEON_WRITE(R700_SQ_DYN_GPR_SIZE_SIMD_AB_0, sq_dyn_gpr_size_simd_ab_0);
1530189499Srnoland	RADEON_WRITE(R700_SQ_DYN_GPR_SIZE_SIMD_AB_1, sq_dyn_gpr_size_simd_ab_0);
1531189499Srnoland	RADEON_WRITE(R700_SQ_DYN_GPR_SIZE_SIMD_AB_2, sq_dyn_gpr_size_simd_ab_0);
1532189499Srnoland	RADEON_WRITE(R700_SQ_DYN_GPR_SIZE_SIMD_AB_3, sq_dyn_gpr_size_simd_ab_0);
1533189499Srnoland	RADEON_WRITE(R700_SQ_DYN_GPR_SIZE_SIMD_AB_4, sq_dyn_gpr_size_simd_ab_0);
1534189499Srnoland	RADEON_WRITE(R700_SQ_DYN_GPR_SIZE_SIMD_AB_5, sq_dyn_gpr_size_simd_ab_0);
1535189499Srnoland	RADEON_WRITE(R700_SQ_DYN_GPR_SIZE_SIMD_AB_6, sq_dyn_gpr_size_simd_ab_0);
1536189499Srnoland	RADEON_WRITE(R700_SQ_DYN_GPR_SIZE_SIMD_AB_7, sq_dyn_gpr_size_simd_ab_0);
1537189499Srnoland
1538189499Srnoland	RADEON_WRITE(R700_PA_SC_FORCE_EOV_MAX_CNTS, (R700_FORCE_EOV_MAX_CLK_CNT(4095) |
1539189499Srnoland						     R700_FORCE_EOV_MAX_REZ_CNT(255)));
1540189499Srnoland
1541189499Srnoland	if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV710)
1542189499Srnoland		RADEON_WRITE(R600_VGT_CACHE_INVALIDATION, (R600_CACHE_INVALIDATION(R600_TC_ONLY) |
1543189499Srnoland							   R700_AUTO_INVLD_EN(R700_ES_AND_GS_AUTO)));
1544189499Srnoland	else
1545189499Srnoland		RADEON_WRITE(R600_VGT_CACHE_INVALIDATION, (R600_CACHE_INVALIDATION(R600_VC_AND_TC) |
1546189499Srnoland							   R700_AUTO_INVLD_EN(R700_ES_AND_GS_AUTO)));
1547189499Srnoland
1548189499Srnoland	switch (dev_priv->flags & RADEON_FAMILY_MASK) {
1549189499Srnoland	case CHIP_RV770:
1550195501Srnoland	case CHIP_RV740:
1551189499Srnoland	case CHIP_RV730:
1552189499Srnoland		gs_prim_buffer_depth = 384;
1553189499Srnoland		break;
1554189499Srnoland	case CHIP_RV710:
1555189499Srnoland		gs_prim_buffer_depth = 128;
1556189499Srnoland		break;
1557189499Srnoland	default:
1558189499Srnoland		break;
1559189499Srnoland	}
1560189499Srnoland
1561189499Srnoland	num_gs_verts_per_thread = dev_priv->r600_max_pipes * 16;
1562189499Srnoland	vgt_gs_per_es = gs_prim_buffer_depth + num_gs_verts_per_thread;
1563189499Srnoland	/* Max value for this is 256 */
1564189499Srnoland	if (vgt_gs_per_es > 256)
1565189499Srnoland		vgt_gs_per_es = 256;
1566189499Srnoland
1567189499Srnoland	RADEON_WRITE(R600_VGT_ES_PER_GS, 128);
1568189499Srnoland	RADEON_WRITE(R600_VGT_GS_PER_ES, vgt_gs_per_es);
1569189499Srnoland	RADEON_WRITE(R600_VGT_GS_PER_VS, 2);
1570189499Srnoland
1571189499Srnoland	/* more default values. 2D/3D driver should adjust as needed */
1572189499Srnoland	RADEON_WRITE(R600_VGT_GS_VERTEX_REUSE, 16);
1573189499Srnoland	RADEON_WRITE(R600_PA_SC_LINE_STIPPLE_STATE, 0);
1574189499Srnoland	RADEON_WRITE(R600_VGT_STRMOUT_EN, 0);
1575189499Srnoland	RADEON_WRITE(R600_SX_MISC, 0);
1576189499Srnoland	RADEON_WRITE(R600_PA_SC_MODE_CNTL, 0);
1577189499Srnoland	RADEON_WRITE(R700_PA_SC_EDGERULE, 0xaaaaaaaa);
1578189499Srnoland	RADEON_WRITE(R600_PA_SC_AA_CONFIG, 0);
1579189499Srnoland	RADEON_WRITE(R600_PA_SC_CLIPRECT_RULE, 0xffff);
1580189499Srnoland	RADEON_WRITE(R600_PA_SC_LINE_STIPPLE, 0);
1581189499Srnoland	RADEON_WRITE(R600_SPI_INPUT_Z, 0);
1582189499Srnoland	RADEON_WRITE(R600_SPI_PS_IN_CONTROL_0, R600_NUM_INTERP(2));
1583189499Srnoland	RADEON_WRITE(R600_CB_COLOR7_FRAG, 0);
1584189499Srnoland
1585189499Srnoland	/* clear render buffer base addresses */
1586189499Srnoland	RADEON_WRITE(R600_CB_COLOR0_BASE, 0);
1587189499Srnoland	RADEON_WRITE(R600_CB_COLOR1_BASE, 0);
1588189499Srnoland	RADEON_WRITE(R600_CB_COLOR2_BASE, 0);
1589189499Srnoland	RADEON_WRITE(R600_CB_COLOR3_BASE, 0);
1590189499Srnoland	RADEON_WRITE(R600_CB_COLOR4_BASE, 0);
1591189499Srnoland	RADEON_WRITE(R600_CB_COLOR5_BASE, 0);
1592189499Srnoland	RADEON_WRITE(R600_CB_COLOR6_BASE, 0);
1593189499Srnoland	RADEON_WRITE(R600_CB_COLOR7_BASE, 0);
1594189499Srnoland
1595189499Srnoland	RADEON_WRITE(R700_TCP_CNTL, 0);
1596189499Srnoland
1597189499Srnoland	hdp_host_path_cntl = RADEON_READ(R600_HDP_HOST_PATH_CNTL);
1598189499Srnoland	RADEON_WRITE(R600_HDP_HOST_PATH_CNTL, hdp_host_path_cntl);
1599189499Srnoland
1600189499Srnoland	RADEON_WRITE(R600_PA_SC_MULTI_CHIP_CNTL, 0);
1601189499Srnoland
1602189499Srnoland	RADEON_WRITE(R600_PA_CL_ENHANCE, (R600_CLIP_VTX_REORDER_ENA |
1603189499Srnoland					  R600_NUM_CLIP_SEQ(3)));
1604189499Srnoland
1605189499Srnoland}
1606189499Srnoland
1607189499Srnolandstatic void r600_cp_init_ring_buffer(struct drm_device *dev,
1608189499Srnoland				       drm_radeon_private_t *dev_priv,
1609189499Srnoland				       struct drm_file *file_priv)
1610189499Srnoland{
1611189499Srnoland	u32 ring_start;
1612189558Srnoland	u64 rptr_addr;
1613189499Srnoland
1614189499Srnoland	if (((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770))
1615189499Srnoland		r700_gfx_init(dev, dev_priv);
1616189499Srnoland	else
1617189499Srnoland		r600_gfx_init(dev, dev_priv);
1618189499Srnoland
1619189499Srnoland	RADEON_WRITE(R600_GRBM_SOFT_RESET, R600_SOFT_RESET_CP);
1620189499Srnoland	RADEON_READ(R600_GRBM_SOFT_RESET);
1621189499Srnoland	DRM_UDELAY(15000);
1622189499Srnoland	RADEON_WRITE(R600_GRBM_SOFT_RESET, 0);
1623189499Srnoland
1624189499Srnoland
1625189499Srnoland	/* Set ring buffer size */
1626189499Srnoland#ifdef __BIG_ENDIAN
1627189499Srnoland	RADEON_WRITE(R600_CP_RB_CNTL,
1628189499Srnoland		     RADEON_BUF_SWAP_32BIT |
1629189499Srnoland		     RADEON_RB_NO_UPDATE |
1630189499Srnoland		     (dev_priv->ring.rptr_update_l2qw << 8) |
1631189499Srnoland		     dev_priv->ring.size_l2qw);
1632189499Srnoland#else
1633189499Srnoland	RADEON_WRITE(R600_CP_RB_CNTL,
1634189499Srnoland		     RADEON_RB_NO_UPDATE |
1635189499Srnoland		     (dev_priv->ring.rptr_update_l2qw << 8) |
1636189499Srnoland		     dev_priv->ring.size_l2qw);
1637189499Srnoland#endif
1638189499Srnoland
1639189499Srnoland	RADEON_WRITE(R600_CP_SEM_WAIT_TIMER, 0x4);
1640189499Srnoland
1641189499Srnoland	/* Set the write pointer delay */
1642189499Srnoland	RADEON_WRITE(R600_CP_RB_WPTR_DELAY, 0);
1643189499Srnoland
1644189499Srnoland#ifdef __BIG_ENDIAN
1645189499Srnoland	RADEON_WRITE(R600_CP_RB_CNTL,
1646189499Srnoland		     RADEON_BUF_SWAP_32BIT |
1647189499Srnoland		     RADEON_RB_NO_UPDATE |
1648189499Srnoland		     RADEON_RB_RPTR_WR_ENA |
1649189499Srnoland		     (dev_priv->ring.rptr_update_l2qw << 8) |
1650189499Srnoland		     dev_priv->ring.size_l2qw);
1651189499Srnoland#else
1652189499Srnoland	RADEON_WRITE(R600_CP_RB_CNTL,
1653189499Srnoland		     RADEON_RB_NO_UPDATE |
1654189499Srnoland		     RADEON_RB_RPTR_WR_ENA |
1655189499Srnoland		     (dev_priv->ring.rptr_update_l2qw << 8) |
1656189499Srnoland		     dev_priv->ring.size_l2qw);
1657189499Srnoland#endif
1658189499Srnoland
1659189499Srnoland	/* Initialize the ring buffer's read and write pointers */
1660189499Srnoland	RADEON_WRITE(R600_CP_RB_RPTR_WR, 0);
1661189499Srnoland	RADEON_WRITE(R600_CP_RB_WPTR, 0);
1662189499Srnoland	SET_RING_HEAD(dev_priv, 0);
1663189499Srnoland	dev_priv->ring.tail = 0;
1664189499Srnoland
1665189499Srnoland#if __OS_HAS_AGP
1666189499Srnoland	if (dev_priv->flags & RADEON_IS_AGP) {
1667189558Srnoland		rptr_addr = dev_priv->ring_rptr->offset
1668189558Srnoland			- dev->agp->base +
1669189558Srnoland			dev_priv->gart_vm_start;
1670189499Srnoland	} else
1671189499Srnoland#endif
1672189499Srnoland	{
1673207067Srnoland		rptr_addr = dev_priv->ring_rptr->offset - dev->sg->vaddr +
1674207067Srnoland		    dev_priv->gart_vm_start;
1675189499Srnoland	}
1676189558Srnoland	RADEON_WRITE(R600_CP_RB_RPTR_ADDR,
1677189558Srnoland		     rptr_addr & 0xffffffff);
1678189558Srnoland	RADEON_WRITE(R600_CP_RB_RPTR_ADDR_HI,
1679189558Srnoland		     upper_32_bits(rptr_addr));
1680189499Srnoland
1681189499Srnoland#ifdef __BIG_ENDIAN
1682189499Srnoland	RADEON_WRITE(R600_CP_RB_CNTL,
1683189499Srnoland		     RADEON_BUF_SWAP_32BIT |
1684189499Srnoland		     (dev_priv->ring.rptr_update_l2qw << 8) |
1685189499Srnoland		     dev_priv->ring.size_l2qw);
1686189499Srnoland#else
1687189499Srnoland	RADEON_WRITE(R600_CP_RB_CNTL,
1688189499Srnoland		     (dev_priv->ring.rptr_update_l2qw << 8) |
1689189499Srnoland		     dev_priv->ring.size_l2qw);
1690189499Srnoland#endif
1691189499Srnoland
1692189499Srnoland#if __OS_HAS_AGP
1693189499Srnoland	if (dev_priv->flags & RADEON_IS_AGP) {
1694189499Srnoland		/* XXX */
1695189499Srnoland		radeon_write_agp_base(dev_priv, dev->agp->base);
1696189499Srnoland
1697189499Srnoland		/* XXX */
1698189499Srnoland		radeon_write_agp_location(dev_priv,
1699189499Srnoland			     (((dev_priv->gart_vm_start - 1 +
1700189499Srnoland				dev_priv->gart_size) & 0xffff0000) |
1701189499Srnoland			      (dev_priv->gart_vm_start >> 16)));
1702189499Srnoland
1703189499Srnoland		ring_start = (dev_priv->cp_ring->offset
1704189499Srnoland			      - dev->agp->base
1705189499Srnoland			      + dev_priv->gart_vm_start);
1706189499Srnoland	} else
1707189499Srnoland#endif
1708207067Srnoland		ring_start = dev_priv->cp_ring->offset - dev->sg->vaddr +
1709207067Srnoland		    dev_priv->gart_vm_start;
1710189499Srnoland
1711189499Srnoland	RADEON_WRITE(R600_CP_RB_BASE, ring_start >> 8);
1712189499Srnoland
1713189499Srnoland	RADEON_WRITE(R600_CP_ME_CNTL, 0xff);
1714189499Srnoland
1715189499Srnoland	RADEON_WRITE(R600_CP_DEBUG, (1 << 27) | (1 << 28));
1716189499Srnoland
1717189499Srnoland	/* Initialize the scratch register pointer.  This will cause
1718189499Srnoland	 * the scratch register values to be written out to memory
1719189499Srnoland	 * whenever they are updated.
1720189499Srnoland	 *
1721189499Srnoland	 * We simply put this behind the ring read pointer, this works
1722189499Srnoland	 * with PCI GART as well as (whatever kind of) AGP GART
1723189499Srnoland	 */
1724189558Srnoland	{
1725189558Srnoland		u64 scratch_addr;
1726189499Srnoland
1727189558Srnoland		scratch_addr = RADEON_READ(R600_CP_RB_RPTR_ADDR);
1728189558Srnoland		scratch_addr |= ((u64)RADEON_READ(R600_CP_RB_RPTR_ADDR_HI)) << 32;
1729189558Srnoland		scratch_addr += R600_SCRATCH_REG_OFFSET;
1730189558Srnoland		scratch_addr >>= 8;
1731189558Srnoland		scratch_addr &= 0xffffffff;
1732189558Srnoland
1733189558Srnoland		RADEON_WRITE(R600_SCRATCH_ADDR, (uint32_t)scratch_addr);
1734189558Srnoland	}
1735189558Srnoland
1736189499Srnoland	RADEON_WRITE(R600_SCRATCH_UMSK, 0x7);
1737189499Srnoland
1738189499Srnoland	/* Turn on bus mastering */
1739189499Srnoland	radeon_enable_bm(dev_priv);
1740189499Srnoland
1741189499Srnoland	radeon_write_ring_rptr(dev_priv, R600_SCRATCHOFF(0), 0);
1742189499Srnoland	RADEON_WRITE(R600_LAST_FRAME_REG, 0);
1743189499Srnoland
1744189499Srnoland	radeon_write_ring_rptr(dev_priv, R600_SCRATCHOFF(1), 0);
1745189499Srnoland	RADEON_WRITE(R600_LAST_DISPATCH_REG, 0);
1746189499Srnoland
1747189499Srnoland	radeon_write_ring_rptr(dev_priv, R600_SCRATCHOFF(2), 0);
1748189499Srnoland	RADEON_WRITE(R600_LAST_CLEAR_REG, 0);
1749189499Srnoland
1750189499Srnoland	/* reset sarea copies of these */
1751189499Srnoland	if (dev_priv->sarea_priv) {
1752189499Srnoland		dev_priv->sarea_priv->last_frame = 0;
1753189499Srnoland		dev_priv->sarea_priv->last_dispatch = 0;
1754189499Srnoland		dev_priv->sarea_priv->last_clear = 0;
1755189499Srnoland	}
1756189499Srnoland
1757189499Srnoland	r600_do_wait_for_idle(dev_priv);
1758189499Srnoland
1759189499Srnoland}
1760189499Srnoland
1761189499Srnolandint r600_do_cleanup_cp(struct drm_device *dev)
1762189499Srnoland{
1763189499Srnoland	drm_radeon_private_t *dev_priv = dev->dev_private;
1764189499Srnoland	DRM_DEBUG("\n");
1765189499Srnoland
1766189499Srnoland	/* Make sure interrupts are disabled here because the uninstall ioctl
1767189499Srnoland	 * may not have been called from userspace and after dev_private
1768189499Srnoland	 * is freed, it's too late.
1769189499Srnoland	 */
1770189499Srnoland	if (dev->irq_enabled)
1771189499Srnoland		drm_irq_uninstall(dev);
1772189499Srnoland
1773189499Srnoland#if __OS_HAS_AGP
1774189499Srnoland	if (dev_priv->flags & RADEON_IS_AGP) {
1775189499Srnoland		if (dev_priv->cp_ring != NULL) {
1776189499Srnoland			drm_core_ioremapfree(dev_priv->cp_ring, dev);
1777189499Srnoland			dev_priv->cp_ring = NULL;
1778189499Srnoland		}
1779189499Srnoland		if (dev_priv->ring_rptr != NULL) {
1780189499Srnoland			drm_core_ioremapfree(dev_priv->ring_rptr, dev);
1781189499Srnoland			dev_priv->ring_rptr = NULL;
1782189499Srnoland		}
1783189499Srnoland		if (dev->agp_buffer_map != NULL) {
1784189499Srnoland			drm_core_ioremapfree(dev->agp_buffer_map, dev);
1785189499Srnoland			dev->agp_buffer_map = NULL;
1786189499Srnoland		}
1787189499Srnoland	} else
1788189499Srnoland#endif
1789189499Srnoland	{
1790189499Srnoland
1791189499Srnoland		if (dev_priv->gart_info.bus_addr)
1792189499Srnoland			r600_page_table_cleanup(dev, &dev_priv->gart_info);
1793189499Srnoland
1794189499Srnoland		if (dev_priv->gart_info.gart_table_location == DRM_ATI_GART_FB) {
1795189499Srnoland			drm_core_ioremapfree(&dev_priv->gart_info.mapping, dev);
1796189499Srnoland			dev_priv->gart_info.addr = 0;
1797189499Srnoland		}
1798189499Srnoland	}
1799189499Srnoland	/* only clear to the start of flags */
1800189499Srnoland	memset(dev_priv, 0, offsetof(drm_radeon_private_t, flags));
1801189499Srnoland
1802189499Srnoland	return 0;
1803189499Srnoland}
1804189499Srnoland
1805189499Srnolandint r600_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init,
1806189499Srnoland		    struct drm_file *file_priv)
1807189499Srnoland{
1808189499Srnoland	drm_radeon_private_t *dev_priv = dev->dev_private;
1809189499Srnoland
1810189499Srnoland	DRM_DEBUG("\n");
1811189499Srnoland
1812189499Srnoland	/* if we require new memory map but we don't have it fail */
1813189499Srnoland	if ((dev_priv->flags & RADEON_NEW_MEMMAP) && !dev_priv->new_memmap) {
1814189499Srnoland		DRM_ERROR("Cannot initialise DRM on this card\nThis card requires a new X.org DDX for 3D\n");
1815189499Srnoland		r600_do_cleanup_cp(dev);
1816189499Srnoland		return -EINVAL;
1817189499Srnoland	}
1818189499Srnoland
1819189499Srnoland	if (init->is_pci && (dev_priv->flags & RADEON_IS_AGP)) {
1820189499Srnoland		DRM_DEBUG("Forcing AGP card to PCI mode\n");
1821189499Srnoland		dev_priv->flags &= ~RADEON_IS_AGP;
1822189499Srnoland		/* The writeback test succeeds, but when writeback is enabled,
1823189499Srnoland		 * the ring buffer read ptr update fails after first 128 bytes.
1824189499Srnoland		 */
1825189499Srnoland		radeon_no_wb = 1;
1826189499Srnoland	} else if (!(dev_priv->flags & (RADEON_IS_AGP | RADEON_IS_PCI | RADEON_IS_PCIE))
1827189499Srnoland		 && !init->is_pci) {
1828189499Srnoland		DRM_DEBUG("Restoring AGP flag\n");
1829189499Srnoland		dev_priv->flags |= RADEON_IS_AGP;
1830189499Srnoland	}
1831189499Srnoland
1832189499Srnoland	dev_priv->usec_timeout = init->usec_timeout;
1833189499Srnoland	if (dev_priv->usec_timeout < 1 ||
1834189499Srnoland	    dev_priv->usec_timeout > RADEON_MAX_USEC_TIMEOUT) {
1835189499Srnoland		DRM_DEBUG("TIMEOUT problem!\n");
1836189499Srnoland		r600_do_cleanup_cp(dev);
1837189499Srnoland		return -EINVAL;
1838189499Srnoland	}
1839189499Srnoland
1840189499Srnoland	/* Enable vblank on CRTC1 for older X servers
1841189499Srnoland	 */
1842189499Srnoland	dev_priv->vblank_crtc = DRM_RADEON_VBLANK_CRTC1;
1843189499Srnoland
1844196470Srnoland	dev_priv->do_boxes = 0;
1845189499Srnoland	dev_priv->cp_mode = init->cp_mode;
1846189499Srnoland
1847189499Srnoland	/* We don't support anything other than bus-mastering ring mode,
1848189499Srnoland	 * but the ring can be in either AGP or PCI space for the ring
1849189499Srnoland	 * read pointer.
1850189499Srnoland	 */
1851189499Srnoland	if ((init->cp_mode != RADEON_CSQ_PRIBM_INDDIS) &&
1852189499Srnoland	    (init->cp_mode != RADEON_CSQ_PRIBM_INDBM)) {
1853189499Srnoland		DRM_DEBUG("BAD cp_mode (%x)!\n", init->cp_mode);
1854189499Srnoland		r600_do_cleanup_cp(dev);
1855189499Srnoland		return -EINVAL;
1856189499Srnoland	}
1857189499Srnoland
1858189499Srnoland	switch (init->fb_bpp) {
1859189499Srnoland	case 16:
1860189499Srnoland		dev_priv->color_fmt = RADEON_COLOR_FORMAT_RGB565;
1861189499Srnoland		break;
1862189499Srnoland	case 32:
1863189499Srnoland	default:
1864189499Srnoland		dev_priv->color_fmt = RADEON_COLOR_FORMAT_ARGB8888;
1865189499Srnoland		break;
1866189499Srnoland	}
1867189499Srnoland	dev_priv->front_offset = init->front_offset;
1868189499Srnoland	dev_priv->front_pitch = init->front_pitch;
1869189499Srnoland	dev_priv->back_offset = init->back_offset;
1870189499Srnoland	dev_priv->back_pitch = init->back_pitch;
1871189499Srnoland
1872189499Srnoland	dev_priv->ring_offset = init->ring_offset;
1873189499Srnoland	dev_priv->ring_rptr_offset = init->ring_rptr_offset;
1874189499Srnoland	dev_priv->buffers_offset = init->buffers_offset;
1875189499Srnoland	dev_priv->gart_textures_offset = init->gart_textures_offset;
1876189499Srnoland
1877189499Srnoland	dev_priv->sarea = drm_getsarea(dev);
1878189499Srnoland	if (!dev_priv->sarea) {
1879189499Srnoland		DRM_ERROR("could not find sarea!\n");
1880189499Srnoland		r600_do_cleanup_cp(dev);
1881189499Srnoland		return -EINVAL;
1882189499Srnoland	}
1883189499Srnoland
1884189499Srnoland	dev_priv->cp_ring = drm_core_findmap(dev, init->ring_offset);
1885189499Srnoland	if (!dev_priv->cp_ring) {
1886189499Srnoland		DRM_ERROR("could not find cp ring region!\n");
1887189499Srnoland		r600_do_cleanup_cp(dev);
1888189499Srnoland		return -EINVAL;
1889189499Srnoland	}
1890189499Srnoland	dev_priv->ring_rptr = drm_core_findmap(dev, init->ring_rptr_offset);
1891189499Srnoland	if (!dev_priv->ring_rptr) {
1892189499Srnoland		DRM_ERROR("could not find ring read pointer!\n");
1893189499Srnoland		r600_do_cleanup_cp(dev);
1894189499Srnoland		return -EINVAL;
1895189499Srnoland	}
1896189499Srnoland	dev->agp_buffer_token = init->buffers_offset;
1897189499Srnoland	dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
1898189499Srnoland	if (!dev->agp_buffer_map) {
1899189499Srnoland		DRM_ERROR("could not find dma buffer region!\n");
1900189499Srnoland		r600_do_cleanup_cp(dev);
1901189499Srnoland		return -EINVAL;
1902189499Srnoland	}
1903189499Srnoland
1904189499Srnoland	if (init->gart_textures_offset) {
1905189499Srnoland		dev_priv->gart_textures =
1906189499Srnoland		    drm_core_findmap(dev, init->gart_textures_offset);
1907189499Srnoland		if (!dev_priv->gart_textures) {
1908189499Srnoland			DRM_ERROR("could not find GART texture region!\n");
1909189499Srnoland			r600_do_cleanup_cp(dev);
1910189499Srnoland			return -EINVAL;
1911189499Srnoland		}
1912189499Srnoland	}
1913189499Srnoland
1914189499Srnoland	dev_priv->sarea_priv =
1915207066Srnoland	    (drm_radeon_sarea_t *) ((u8 *) dev_priv->sarea->virtual +
1916189499Srnoland				    init->sarea_priv_offset);
1917189499Srnoland
1918189499Srnoland#if __OS_HAS_AGP
1919189499Srnoland	/* XXX */
1920189499Srnoland	if (dev_priv->flags & RADEON_IS_AGP) {
1921189499Srnoland		drm_core_ioremap_wc(dev_priv->cp_ring, dev);
1922189499Srnoland		drm_core_ioremap_wc(dev_priv->ring_rptr, dev);
1923189499Srnoland		drm_core_ioremap_wc(dev->agp_buffer_map, dev);
1924207066Srnoland		if (!dev_priv->cp_ring->virtual ||
1925207066Srnoland		    !dev_priv->ring_rptr->virtual ||
1926207066Srnoland		    !dev->agp_buffer_map->virtual) {
1927189499Srnoland			DRM_ERROR("could not find ioremap agp regions!\n");
1928189499Srnoland			r600_do_cleanup_cp(dev);
1929189499Srnoland			return -EINVAL;
1930189499Srnoland		}
1931189499Srnoland	} else
1932189499Srnoland#endif
1933189499Srnoland	{
1934207066Srnoland		dev_priv->cp_ring->virtual =
1935207066Srnoland		    (void *)dev_priv->cp_ring->offset;
1936207066Srnoland		dev_priv->ring_rptr->virtual =
1937189499Srnoland		    (void *)dev_priv->ring_rptr->offset;
1938207066Srnoland		dev->agp_buffer_map->virtual =
1939189499Srnoland		    (void *)dev->agp_buffer_map->offset;
1940189499Srnoland
1941207066Srnoland		DRM_DEBUG("dev_priv->cp_ring->virtual %p\n",
1942207066Srnoland			  dev_priv->cp_ring->virtual);
1943207066Srnoland		DRM_DEBUG("dev_priv->ring_rptr->virtual %p\n",
1944207066Srnoland			  dev_priv->ring_rptr->virtual);
1945207066Srnoland		DRM_DEBUG("dev->agp_buffer_map->virtual %p\n",
1946207066Srnoland			  dev->agp_buffer_map->virtual);
1947189499Srnoland	}
1948189499Srnoland
1949189499Srnoland	dev_priv->fb_location = (radeon_read_fb_location(dev_priv) & 0xffff) << 24;
1950189499Srnoland	dev_priv->fb_size =
1951189499Srnoland		(((radeon_read_fb_location(dev_priv) & 0xffff0000u) << 8) + 0x1000000)
1952189499Srnoland		- dev_priv->fb_location;
1953189499Srnoland
1954189499Srnoland	dev_priv->front_pitch_offset = (((dev_priv->front_pitch / 64) << 22) |
1955189499Srnoland					((dev_priv->front_offset
1956189499Srnoland					  + dev_priv->fb_location) >> 10));
1957189499Srnoland
1958189499Srnoland	dev_priv->back_pitch_offset = (((dev_priv->back_pitch / 64) << 22) |
1959189499Srnoland				       ((dev_priv->back_offset
1960189499Srnoland					 + dev_priv->fb_location) >> 10));
1961189499Srnoland
1962189499Srnoland	dev_priv->depth_pitch_offset = (((dev_priv->depth_pitch / 64) << 22) |
1963189499Srnoland					((dev_priv->depth_offset
1964189499Srnoland					  + dev_priv->fb_location) >> 10));
1965189499Srnoland
1966189499Srnoland	dev_priv->gart_size = init->gart_size;
1967189499Srnoland
1968189499Srnoland	/* New let's set the memory map ... */
1969189499Srnoland	if (dev_priv->new_memmap) {
1970189499Srnoland		u32 base = 0;
1971189499Srnoland
1972189499Srnoland		DRM_INFO("Setting GART location based on new memory map\n");
1973189499Srnoland
1974189499Srnoland		/* If using AGP, try to locate the AGP aperture at the same
1975189499Srnoland		 * location in the card and on the bus, though we have to
1976189499Srnoland		 * align it down.
1977189499Srnoland		 */
1978189499Srnoland#if __OS_HAS_AGP
1979189499Srnoland		/* XXX */
1980189499Srnoland		if (dev_priv->flags & RADEON_IS_AGP) {
1981189499Srnoland			base = dev->agp->base;
1982189499Srnoland			/* Check if valid */
1983189499Srnoland			if ((base + dev_priv->gart_size - 1) >= dev_priv->fb_location &&
1984189499Srnoland			    base < (dev_priv->fb_location + dev_priv->fb_size - 1)) {
1985189499Srnoland				DRM_INFO("Can't use AGP base @0x%08lx, won't fit\n",
1986189499Srnoland					 dev->agp->base);
1987189499Srnoland				base = 0;
1988189499Srnoland			}
1989189499Srnoland		}
1990189499Srnoland#endif
1991189499Srnoland		/* If not or if AGP is at 0 (Macs), try to put it elsewhere */
1992189499Srnoland		if (base == 0) {
1993189499Srnoland			base = dev_priv->fb_location + dev_priv->fb_size;
1994189499Srnoland			if (base < dev_priv->fb_location ||
1995189499Srnoland			    ((base + dev_priv->gart_size) & 0xfffffffful) < base)
1996189499Srnoland				base = dev_priv->fb_location
1997189499Srnoland					- dev_priv->gart_size;
1998189499Srnoland		}
1999189499Srnoland		dev_priv->gart_vm_start = base & 0xffc00000u;
2000189499Srnoland		if (dev_priv->gart_vm_start != base)
2001189499Srnoland			DRM_INFO("GART aligned down from 0x%08x to 0x%08x\n",
2002189499Srnoland				 base, dev_priv->gart_vm_start);
2003189499Srnoland	}
2004189499Srnoland
2005189499Srnoland#if __OS_HAS_AGP
2006189499Srnoland	/* XXX */
2007189499Srnoland	if (dev_priv->flags & RADEON_IS_AGP)
2008189499Srnoland		dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset
2009189499Srnoland						 - dev->agp->base
2010189499Srnoland						 + dev_priv->gart_vm_start);
2011189499Srnoland	else
2012189499Srnoland#endif
2013207067Srnoland		dev_priv->gart_buffers_offset = dev->agp_buffer_map->offset -
2014207067Srnoland		    dev->sg->vaddr + dev_priv->gart_vm_start;
2015189499Srnoland
2016189499Srnoland	DRM_DEBUG("fb 0x%08x size %d\n",
2017189499Srnoland		  (unsigned int) dev_priv->fb_location,
2018189499Srnoland		  (unsigned int) dev_priv->fb_size);
2019189499Srnoland	DRM_DEBUG("dev_priv->gart_size %d\n", dev_priv->gart_size);
2020189499Srnoland	DRM_DEBUG("dev_priv->gart_vm_start 0x%08x\n",
2021189499Srnoland		  (unsigned int) dev_priv->gart_vm_start);
2022189499Srnoland	DRM_DEBUG("dev_priv->gart_buffers_offset 0x%08lx\n",
2023189499Srnoland		  dev_priv->gart_buffers_offset);
2024189499Srnoland
2025207066Srnoland	dev_priv->ring.start = (u32 *) dev_priv->cp_ring->virtual;
2026207066Srnoland	dev_priv->ring.end = ((u32 *) dev_priv->cp_ring->virtual
2027189499Srnoland			      + init->ring_size / sizeof(u32));
2028189499Srnoland	dev_priv->ring.size = init->ring_size;
2029189499Srnoland	dev_priv->ring.size_l2qw = drm_order(init->ring_size / 8);
2030189499Srnoland
2031189499Srnoland	dev_priv->ring.rptr_update = /* init->rptr_update */ 4096;
2032189499Srnoland	dev_priv->ring.rptr_update_l2qw = drm_order(/* init->rptr_update */ 4096 / 8);
2033189499Srnoland
2034189499Srnoland	dev_priv->ring.fetch_size = /* init->fetch_size */ 32;
2035189499Srnoland	dev_priv->ring.fetch_size_l2ow = drm_order(/* init->fetch_size */ 32 / 16);
2036189499Srnoland
2037189499Srnoland	dev_priv->ring.tail_mask = (dev_priv->ring.size / sizeof(u32)) - 1;
2038189499Srnoland
2039189499Srnoland	dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK;
2040189499Srnoland
2041189499Srnoland#if __OS_HAS_AGP
2042189499Srnoland	if (dev_priv->flags & RADEON_IS_AGP) {
2043189499Srnoland		/* XXX turn off pcie gart */
2044189499Srnoland	} else
2045189499Srnoland#endif
2046189499Srnoland	{
2047189499Srnoland		dev_priv->gart_info.table_mask = DMA_BIT_MASK(32);
2048189499Srnoland		/* if we have an offset set from userspace */
2049189499Srnoland		if (!dev_priv->pcigart_offset_set) {
2050189499Srnoland			DRM_ERROR("Need gart offset from userspace\n");
2051189499Srnoland			r600_do_cleanup_cp(dev);
2052189499Srnoland			return -EINVAL;
2053189499Srnoland		}
2054189499Srnoland
2055189499Srnoland		DRM_DEBUG("Using gart offset 0x%08lx\n", dev_priv->pcigart_offset);
2056189499Srnoland
2057189499Srnoland		dev_priv->gart_info.bus_addr =
2058189499Srnoland			dev_priv->pcigart_offset + dev_priv->fb_location;
2059189499Srnoland		dev_priv->gart_info.mapping.offset =
2060189499Srnoland			dev_priv->pcigart_offset + dev_priv->fb_aper_offset;
2061189499Srnoland		dev_priv->gart_info.mapping.size =
2062189499Srnoland			dev_priv->gart_info.table_size;
2063189499Srnoland
2064189499Srnoland		drm_core_ioremap_wc(&dev_priv->gart_info.mapping, dev);
2065207066Srnoland		if (!dev_priv->gart_info.mapping.virtual) {
2066189499Srnoland			DRM_ERROR("ioremap failed.\n");
2067189499Srnoland			r600_do_cleanup_cp(dev);
2068189499Srnoland			return -EINVAL;
2069189499Srnoland		}
2070189499Srnoland
2071189499Srnoland		dev_priv->gart_info.addr =
2072207066Srnoland			dev_priv->gart_info.mapping.virtual;
2073189499Srnoland
2074189499Srnoland		DRM_DEBUG("Setting phys_pci_gart to %p %08lX\n",
2075189499Srnoland			  dev_priv->gart_info.addr,
2076189499Srnoland			  dev_priv->pcigart_offset);
2077189499Srnoland
2078189909Srnoland		if (!r600_page_table_init(dev)) {
2079189499Srnoland			DRM_ERROR("Failed to init GART table\n");
2080189499Srnoland			r600_do_cleanup_cp(dev);
2081189499Srnoland			return -EINVAL;
2082189499Srnoland		}
2083189499Srnoland
2084189499Srnoland		if (((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770))
2085189499Srnoland			r700_vm_init(dev);
2086189499Srnoland		else
2087189499Srnoland			r600_vm_init(dev);
2088189499Srnoland	}
2089189499Srnoland
2090189499Srnoland	if (((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770))
2091189499Srnoland		r700_cp_load_microcode(dev_priv);
2092189499Srnoland	else
2093189499Srnoland		r600_cp_load_microcode(dev_priv);
2094189499Srnoland
2095189499Srnoland	r600_cp_init_ring_buffer(dev, dev_priv, file_priv);
2096189499Srnoland
2097189499Srnoland	dev_priv->last_buf = 0;
2098189499Srnoland
2099189499Srnoland	r600_do_engine_reset(dev);
2100189499Srnoland	r600_test_writeback(dev_priv);
2101189499Srnoland
2102196470Srnoland	r600_cs_init(dev);
2103196470Srnoland
2104189499Srnoland	return 0;
2105189499Srnoland}
2106189499Srnoland
2107189499Srnolandint r600_do_resume_cp(struct drm_device *dev, struct drm_file *file_priv)
2108189499Srnoland{
2109189499Srnoland	drm_radeon_private_t *dev_priv = dev->dev_private;
2110189499Srnoland
2111189499Srnoland	DRM_DEBUG("\n");
2112189499Srnoland	if (((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770)) {
2113189499Srnoland		r700_vm_init(dev);
2114189499Srnoland		r700_cp_load_microcode(dev_priv);
2115189499Srnoland	} else {
2116189499Srnoland		r600_vm_init(dev);
2117189499Srnoland		r600_cp_load_microcode(dev_priv);
2118189499Srnoland	}
2119189499Srnoland	r600_cp_init_ring_buffer(dev, dev_priv, file_priv);
2120189499Srnoland	r600_do_engine_reset(dev);
2121189499Srnoland
2122189499Srnoland	return 0;
2123189499Srnoland}
2124189499Srnoland
2125189499Srnoland/* Wait for the CP to go idle.
2126189499Srnoland */
2127189499Srnolandint r600_do_cp_idle(drm_radeon_private_t *dev_priv)
2128189499Srnoland{
2129189499Srnoland	RING_LOCALS;
2130189499Srnoland	DRM_DEBUG("\n");
2131189499Srnoland
2132189499Srnoland	BEGIN_RING(5);
2133189499Srnoland	OUT_RING(CP_PACKET3(R600_IT_EVENT_WRITE, 0));
2134189499Srnoland	OUT_RING(R600_CACHE_FLUSH_AND_INV_EVENT);
2135189499Srnoland	/* wait for 3D idle clean */
2136189499Srnoland	OUT_RING(CP_PACKET3(R600_IT_SET_CONFIG_REG, 1));
2137189499Srnoland	OUT_RING((R600_WAIT_UNTIL - R600_SET_CONFIG_REG_OFFSET) >> 2);
2138189499Srnoland	OUT_RING(RADEON_WAIT_3D_IDLE | RADEON_WAIT_3D_IDLECLEAN);
2139189499Srnoland
2140189499Srnoland	ADVANCE_RING();
2141189499Srnoland	COMMIT_RING();
2142189499Srnoland
2143189499Srnoland	return r600_do_wait_for_idle(dev_priv);
2144189499Srnoland}
2145189499Srnoland
2146189499Srnoland/* Start the Command Processor.
2147189499Srnoland */
2148189499Srnolandvoid r600_do_cp_start(drm_radeon_private_t *dev_priv)
2149189499Srnoland{
2150189499Srnoland	u32 cp_me;
2151189499Srnoland	RING_LOCALS;
2152189499Srnoland	DRM_DEBUG("\n");
2153189499Srnoland
2154189499Srnoland	BEGIN_RING(7);
2155189499Srnoland	OUT_RING(CP_PACKET3(R600_IT_ME_INITIALIZE, 5));
2156189499Srnoland	OUT_RING(0x00000001);
2157189499Srnoland	if (((dev_priv->flags & RADEON_FAMILY_MASK) < CHIP_RV770))
2158189499Srnoland		OUT_RING(0x00000003);
2159189499Srnoland	else
2160189499Srnoland		OUT_RING(0x00000000);
2161189499Srnoland	OUT_RING((dev_priv->r600_max_hw_contexts - 1));
2162189499Srnoland	OUT_RING(R600_ME_INITIALIZE_DEVICE_ID(1));
2163189499Srnoland	OUT_RING(0x00000000);
2164189499Srnoland	OUT_RING(0x00000000);
2165189499Srnoland	ADVANCE_RING();
2166189499Srnoland	COMMIT_RING();
2167189499Srnoland
2168189499Srnoland	/* set the mux and reset the halt bit */
2169189499Srnoland	cp_me = 0xff;
2170189499Srnoland	RADEON_WRITE(R600_CP_ME_CNTL, cp_me);
2171189499Srnoland
2172189499Srnoland	dev_priv->cp_running = 1;
2173189499Srnoland
2174189499Srnoland}
2175189499Srnoland
2176189499Srnolandvoid r600_do_cp_reset(drm_radeon_private_t *dev_priv)
2177189499Srnoland{
2178189499Srnoland	u32 cur_read_ptr;
2179189499Srnoland	DRM_DEBUG("\n");
2180189499Srnoland
2181189499Srnoland	cur_read_ptr = RADEON_READ(R600_CP_RB_RPTR);
2182189499Srnoland	RADEON_WRITE(R600_CP_RB_WPTR, cur_read_ptr);
2183189499Srnoland	SET_RING_HEAD(dev_priv, cur_read_ptr);
2184189499Srnoland	dev_priv->ring.tail = cur_read_ptr;
2185189499Srnoland}
2186189499Srnoland
2187189499Srnolandvoid r600_do_cp_stop(drm_radeon_private_t *dev_priv)
2188189499Srnoland{
2189189499Srnoland	uint32_t cp_me;
2190189499Srnoland
2191189499Srnoland	DRM_DEBUG("\n");
2192189499Srnoland
2193189499Srnoland	cp_me = 0xff | R600_CP_ME_HALT;
2194189499Srnoland
2195189499Srnoland	RADEON_WRITE(R600_CP_ME_CNTL, cp_me);
2196189499Srnoland
2197189499Srnoland	dev_priv->cp_running = 0;
2198189499Srnoland}
2199189499Srnoland
2200189499Srnolandint r600_cp_dispatch_indirect(struct drm_device *dev,
2201189499Srnoland			      struct drm_buf *buf, int start, int end)
2202189499Srnoland{
2203189499Srnoland	drm_radeon_private_t *dev_priv = dev->dev_private;
2204189499Srnoland	RING_LOCALS;
2205189499Srnoland
2206189499Srnoland	if (start != end) {
2207189499Srnoland		unsigned long offset = (dev_priv->gart_buffers_offset
2208189499Srnoland					+ buf->offset + start);
2209189499Srnoland		int dwords = (end - start + 3) / sizeof(u32);
2210189499Srnoland
2211189499Srnoland		DRM_DEBUG("dwords:%d\n", dwords);
2212189499Srnoland		DRM_DEBUG("offset 0x%lx\n", offset);
2213189499Srnoland
2214189499Srnoland
2215189499Srnoland		/* Indirect buffer data must be a multiple of 16 dwords.
2216189499Srnoland		 * pad the data with a Type-2 CP packet.
2217189499Srnoland		 */
2218189499Srnoland		while (dwords & 0xf) {
2219189499Srnoland			u32 *data = (u32 *)
2220207066Srnoland			    ((char *)dev->agp_buffer_map->virtual
2221189499Srnoland			     + buf->offset + start);
2222189499Srnoland			data[dwords++] = RADEON_CP_PACKET2;
2223189499Srnoland		}
2224189499Srnoland
2225189499Srnoland		/* Fire off the indirect buffer */
2226189499Srnoland		BEGIN_RING(4);
2227189499Srnoland		OUT_RING(CP_PACKET3(R600_IT_INDIRECT_BUFFER, 2));
2228189499Srnoland		OUT_RING((offset & 0xfffffffc));
2229189499Srnoland		OUT_RING((upper_32_bits(offset) & 0xff));
2230189499Srnoland		OUT_RING(dwords);
2231189499Srnoland		ADVANCE_RING();
2232189499Srnoland	}
2233189499Srnoland
2234189499Srnoland	return 0;
2235189499Srnoland}
2236196470Srnoland
2237196470Srnolandvoid r600_cp_dispatch_swap(struct drm_device * dev)
2238196470Srnoland{
2239196470Srnoland	drm_radeon_private_t *dev_priv = dev->dev_private;
2240196470Srnoland	drm_radeon_sarea_t *sarea_priv = dev_priv->sarea_priv;
2241196470Srnoland	int nbox = sarea_priv->nbox;
2242196470Srnoland	struct drm_clip_rect *pbox = sarea_priv->boxes;
2243196470Srnoland	int i, cpp, src_pitch, dst_pitch;
2244196470Srnoland	uint64_t src, dst;
2245196470Srnoland	RING_LOCALS;
2246196470Srnoland	DRM_DEBUG("\n");
2247196470Srnoland
2248196470Srnoland	if (dev_priv->color_fmt == RADEON_COLOR_FORMAT_ARGB8888)
2249196470Srnoland		cpp = 4;
2250196470Srnoland	else
2251196470Srnoland		cpp = 2;
2252196470Srnoland
2253196470Srnoland	if (dev_priv->sarea_priv->pfCurrentPage == 0) {
2254196470Srnoland		src_pitch = dev_priv->back_pitch;
2255196470Srnoland		dst_pitch = dev_priv->front_pitch;
2256196470Srnoland		src = dev_priv->back_offset + dev_priv->fb_location;
2257196470Srnoland		dst = dev_priv->front_offset + dev_priv->fb_location;
2258196470Srnoland	} else {
2259196470Srnoland		src_pitch = dev_priv->front_pitch;
2260196470Srnoland		dst_pitch = dev_priv->back_pitch;
2261196470Srnoland		src = dev_priv->front_offset + dev_priv->fb_location;
2262196470Srnoland		dst = dev_priv->back_offset + dev_priv->fb_location;
2263196470Srnoland	}
2264196470Srnoland
2265196470Srnoland	if (r600_prepare_blit_copy(dev)) {
2266196470Srnoland		DRM_ERROR("unable to allocate vertex buffer for swap buffer\n");
2267196470Srnoland		return;
2268196470Srnoland	}
2269196470Srnoland	for (i = 0; i < nbox; i++) {
2270196470Srnoland		int x = pbox[i].x1;
2271196470Srnoland		int y = pbox[i].y1;
2272196470Srnoland		int w = pbox[i].x2 - x;
2273196470Srnoland		int h = pbox[i].y2 - y;
2274196470Srnoland
2275196470Srnoland		DRM_DEBUG("%d,%d-%d,%d\n", x, y, w, h);
2276196470Srnoland
2277196470Srnoland		r600_blit_swap(dev,
2278196470Srnoland			       src, dst,
2279196470Srnoland			       x, y, x, y, w, h,
2280196470Srnoland			       src_pitch, dst_pitch, cpp);
2281196470Srnoland	}
2282196470Srnoland	r600_done_blit_copy(dev);
2283196470Srnoland
2284196470Srnoland	/* Increment the frame counter.  The client-side 3D driver must
2285196470Srnoland	 * throttle the framerate by waiting for this value before
2286196470Srnoland	 * performing the swapbuffer ioctl.
2287196470Srnoland	 */
2288196470Srnoland	dev_priv->sarea_priv->last_frame++;
2289196470Srnoland
2290196470Srnoland	BEGIN_RING(3);
2291196470Srnoland	R600_FRAME_AGE(dev_priv->sarea_priv->last_frame);
2292196470Srnoland	ADVANCE_RING();
2293196470Srnoland}
2294196470Srnoland
2295196470Srnolandint r600_cp_dispatch_texture(struct drm_device * dev,
2296196470Srnoland			     struct drm_file *file_priv,
2297196470Srnoland			     drm_radeon_texture_t * tex,
2298196470Srnoland			     drm_radeon_tex_image_t * image)
2299196470Srnoland{
2300196470Srnoland	drm_radeon_private_t *dev_priv = dev->dev_private;
2301196470Srnoland	struct drm_buf *buf;
2302196470Srnoland	u32 *buffer;
2303196470Srnoland	const u8 __user *data;
2304196470Srnoland	int size, pass_size;
2305196470Srnoland	u64 src_offset, dst_offset;
2306196470Srnoland
2307196470Srnoland	if (!radeon_check_offset(dev_priv, tex->offset)) {
2308196470Srnoland		DRM_ERROR("Invalid destination offset\n");
2309196470Srnoland		return -EINVAL;
2310196470Srnoland	}
2311196470Srnoland
2312196470Srnoland	/* this might fail for zero-sized uploads - are those illegal? */
2313196470Srnoland	if (!radeon_check_offset(dev_priv, tex->offset + tex->height * tex->pitch - 1)) {
2314196470Srnoland		DRM_ERROR("Invalid final destination offset\n");
2315196470Srnoland		return -EINVAL;
2316196470Srnoland	}
2317196470Srnoland
2318196470Srnoland	size = tex->height * tex->pitch;
2319196470Srnoland
2320196470Srnoland	if (size == 0)
2321196470Srnoland		return 0;
2322196470Srnoland
2323196470Srnoland	dst_offset = tex->offset;
2324196470Srnoland
2325196470Srnoland	r600_prepare_blit_copy(dev);
2326196470Srnoland	do {
2327196470Srnoland		data = (const u8 __user *)image->data;
2328196470Srnoland		pass_size = size;
2329196470Srnoland
2330196470Srnoland		buf = radeon_freelist_get(dev);
2331196470Srnoland		if (!buf) {
2332196470Srnoland			DRM_DEBUG("EAGAIN\n");
2333196470Srnoland			if (DRM_COPY_TO_USER(tex->image, image, sizeof(*image)))
2334196470Srnoland				return -EFAULT;
2335196470Srnoland			return -EAGAIN;
2336196470Srnoland		}
2337196470Srnoland
2338196470Srnoland		if (pass_size > buf->total)
2339196470Srnoland			pass_size = buf->total;
2340196470Srnoland
2341196470Srnoland		/* Dispatch the indirect buffer.
2342196470Srnoland		 */
2343196470Srnoland		buffer =
2344207066Srnoland		    (u32 *) ((char *)dev->agp_buffer_map->virtual +
2345207066Srnoland		    buf->offset);
2346196470Srnoland
2347196470Srnoland		if (DRM_COPY_FROM_USER(buffer, data, pass_size)) {
2348196470Srnoland			DRM_ERROR("EFAULT on pad, %d bytes\n", pass_size);
2349196470Srnoland			return -EFAULT;
2350196470Srnoland		}
2351196470Srnoland
2352196470Srnoland		buf->file_priv = file_priv;
2353196470Srnoland		buf->used = pass_size;
2354196470Srnoland		src_offset = dev_priv->gart_buffers_offset + buf->offset;
2355196470Srnoland
2356196470Srnoland		r600_blit_copy(dev, src_offset, dst_offset, pass_size);
2357196470Srnoland
2358196470Srnoland		radeon_cp_discard_buffer(dev, buf);
2359196470Srnoland
2360196470Srnoland		/* Update the input parameters for next time */
2361196470Srnoland		image->data = (const u8 __user *)image->data + pass_size;
2362196470Srnoland		dst_offset += pass_size;
2363196470Srnoland		size -= pass_size;
2364196470Srnoland	} while (size > 0);
2365196470Srnoland	r600_done_blit_copy(dev);
2366196470Srnoland
2367196470Srnoland	return 0;
2368196470Srnoland}
2369