1254885Sdumbbell/*
2254885Sdumbbell * Copyright 2008 Advanced Micro Devices, Inc.
3254885Sdumbbell * Copyright 2008 Red Hat Inc.
4254885Sdumbbell * Copyright 2009 Jerome Glisse.
5254885Sdumbbell *
6254885Sdumbbell * Permission is hereby granted, free of charge, to any person obtaining a
7254885Sdumbbell * copy of this software and associated documentation files (the "Software"),
8254885Sdumbbell * to deal in the Software without restriction, including without limitation
9254885Sdumbbell * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10254885Sdumbbell * and/or sell copies of the Software, and to permit persons to whom the
11254885Sdumbbell * Software is furnished to do so, subject to the following conditions:
12254885Sdumbbell *
13254885Sdumbbell * The above copyright notice and this permission notice shall be included in
14254885Sdumbbell * all copies or substantial portions of the Software.
15254885Sdumbbell *
16254885Sdumbbell * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17254885Sdumbbell * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18254885Sdumbbell * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19254885Sdumbbell * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20254885Sdumbbell * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21254885Sdumbbell * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22254885Sdumbbell * OTHER DEALINGS IN THE SOFTWARE.
23254885Sdumbbell *
24254885Sdumbbell * Authors: Dave Airlie
25254885Sdumbbell *          Alex Deucher
26254885Sdumbbell *          Jerome Glisse
27254885Sdumbbell */
28254885Sdumbbell
29254885Sdumbbell#include <sys/cdefs.h>
30254885Sdumbbell__FBSDID("$FreeBSD$");
31254885Sdumbbell
32254885Sdumbbell#include <dev/drm2/drmP.h>
33254885Sdumbbell#include <dev/drm2/radeon/radeon_drm.h>
34254885Sdumbbell#include "radeon_reg.h"
35254885Sdumbbell#include "radeon.h"
36254885Sdumbbell#include "radeon_asic.h"
37254885Sdumbbell
38254885Sdumbbell#include "r100d.h"
39254885Sdumbbell#include "r200_reg_safe.h"
40254885Sdumbbell
41254885Sdumbbell#include "r100_track.h"
42254885Sdumbbell
43254885Sdumbbellstatic int r200_get_vtx_size_0(uint32_t vtx_fmt_0)
44254885Sdumbbell{
45254885Sdumbbell	int vtx_size, i;
46254885Sdumbbell	vtx_size = 2;
47254885Sdumbbell
48254885Sdumbbell	if (vtx_fmt_0 & R200_VTX_Z0)
49254885Sdumbbell		vtx_size++;
50254885Sdumbbell	if (vtx_fmt_0 & R200_VTX_W0)
51254885Sdumbbell		vtx_size++;
52254885Sdumbbell	/* blend weight */
53254885Sdumbbell	if (vtx_fmt_0 & (0x7 << R200_VTX_WEIGHT_COUNT_SHIFT))
54254885Sdumbbell		vtx_size += (vtx_fmt_0 >> R200_VTX_WEIGHT_COUNT_SHIFT) & 0x7;
55254885Sdumbbell	if (vtx_fmt_0 & R200_VTX_PV_MATRIX_SEL)
56254885Sdumbbell		vtx_size++;
57254885Sdumbbell	if (vtx_fmt_0 & R200_VTX_N0)
58254885Sdumbbell		vtx_size += 3;
59254885Sdumbbell	if (vtx_fmt_0 & R200_VTX_POINT_SIZE)
60254885Sdumbbell		vtx_size++;
61254885Sdumbbell	if (vtx_fmt_0 & R200_VTX_DISCRETE_FOG)
62254885Sdumbbell		vtx_size++;
63254885Sdumbbell	if (vtx_fmt_0 & R200_VTX_SHININESS_0)
64254885Sdumbbell		vtx_size++;
65254885Sdumbbell	if (vtx_fmt_0 & R200_VTX_SHININESS_1)
66254885Sdumbbell		vtx_size++;
67254885Sdumbbell	for (i = 0; i < 8; i++) {
68254885Sdumbbell		int color_size = (vtx_fmt_0 >> (11 + 2*i)) & 0x3;
69254885Sdumbbell		switch (color_size) {
70254885Sdumbbell		case 0: break;
71254885Sdumbbell		case 1: vtx_size++; break;
72254885Sdumbbell		case 2: vtx_size += 3; break;
73254885Sdumbbell		case 3: vtx_size += 4; break;
74254885Sdumbbell		}
75254885Sdumbbell	}
76254885Sdumbbell	if (vtx_fmt_0 & R200_VTX_XY1)
77254885Sdumbbell		vtx_size += 2;
78254885Sdumbbell	if (vtx_fmt_0 & R200_VTX_Z1)
79254885Sdumbbell		vtx_size++;
80254885Sdumbbell	if (vtx_fmt_0 & R200_VTX_W1)
81254885Sdumbbell		vtx_size++;
82254885Sdumbbell	if (vtx_fmt_0 & R200_VTX_N1)
83254885Sdumbbell		vtx_size += 3;
84254885Sdumbbell	return vtx_size;
85254885Sdumbbell}
86254885Sdumbbell
87254885Sdumbbellint r200_copy_dma(struct radeon_device *rdev,
88254885Sdumbbell		  uint64_t src_offset,
89254885Sdumbbell		  uint64_t dst_offset,
90254885Sdumbbell		  unsigned num_gpu_pages,
91254885Sdumbbell		  struct radeon_fence **fence)
92254885Sdumbbell{
93254885Sdumbbell	struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
94254885Sdumbbell	uint32_t size;
95254885Sdumbbell	uint32_t cur_size;
96254885Sdumbbell	int i, num_loops;
97254885Sdumbbell	int r = 0;
98254885Sdumbbell
99254885Sdumbbell	/* radeon pitch is /64 */
100254885Sdumbbell	size = num_gpu_pages << RADEON_GPU_PAGE_SHIFT;
101254885Sdumbbell	num_loops = DIV_ROUND_UP(size, 0x1FFFFF);
102254885Sdumbbell	r = radeon_ring_lock(rdev, ring, num_loops * 4 + 64);
103254885Sdumbbell	if (r) {
104254885Sdumbbell		DRM_ERROR("radeon: moving bo (%d).\n", r);
105254885Sdumbbell		return r;
106254885Sdumbbell	}
107254885Sdumbbell	/* Must wait for 2D idle & clean before DMA or hangs might happen */
108254885Sdumbbell	radeon_ring_write(ring, PACKET0(RADEON_WAIT_UNTIL, 0));
109254885Sdumbbell	radeon_ring_write(ring, (1 << 16));
110254885Sdumbbell	for (i = 0; i < num_loops; i++) {
111254885Sdumbbell		cur_size = size;
112254885Sdumbbell		if (cur_size > 0x1FFFFF) {
113254885Sdumbbell			cur_size = 0x1FFFFF;
114254885Sdumbbell		}
115254885Sdumbbell		size -= cur_size;
116254885Sdumbbell		radeon_ring_write(ring, PACKET0(0x720, 2));
117254885Sdumbbell		radeon_ring_write(ring, src_offset);
118254885Sdumbbell		radeon_ring_write(ring, dst_offset);
119258780Seadler		radeon_ring_write(ring, cur_size | (1U << 31) | (1 << 30));
120254885Sdumbbell		src_offset += cur_size;
121254885Sdumbbell		dst_offset += cur_size;
122254885Sdumbbell	}
123254885Sdumbbell	radeon_ring_write(ring, PACKET0(RADEON_WAIT_UNTIL, 0));
124254885Sdumbbell	radeon_ring_write(ring, RADEON_WAIT_DMA_GUI_IDLE);
125254885Sdumbbell	if (fence) {
126254885Sdumbbell		r = radeon_fence_emit(rdev, fence, RADEON_RING_TYPE_GFX_INDEX);
127254885Sdumbbell	}
128254885Sdumbbell	radeon_ring_unlock_commit(rdev, ring);
129254885Sdumbbell	return r;
130254885Sdumbbell}
131254885Sdumbbell
132254885Sdumbbell
133254885Sdumbbellstatic int r200_get_vtx_size_1(uint32_t vtx_fmt_1)
134254885Sdumbbell{
135254885Sdumbbell	int vtx_size, i, tex_size;
136254885Sdumbbell	vtx_size = 0;
137254885Sdumbbell	for (i = 0; i < 6; i++) {
138254885Sdumbbell		tex_size = (vtx_fmt_1 >> (i * 3)) & 0x7;
139254885Sdumbbell		if (tex_size > 4)
140254885Sdumbbell			continue;
141254885Sdumbbell		vtx_size += tex_size;
142254885Sdumbbell	}
143254885Sdumbbell	return vtx_size;
144254885Sdumbbell}
145254885Sdumbbell
146254885Sdumbbellint r200_packet0_check(struct radeon_cs_parser *p,
147254885Sdumbbell		       struct radeon_cs_packet *pkt,
148254885Sdumbbell		       unsigned idx, unsigned reg)
149254885Sdumbbell{
150254885Sdumbbell	struct radeon_cs_reloc *reloc;
151254885Sdumbbell	struct r100_cs_track *track;
152254885Sdumbbell	volatile uint32_t *ib;
153254885Sdumbbell	uint32_t tmp;
154254885Sdumbbell	int r;
155254885Sdumbbell	int i;
156254885Sdumbbell	int face;
157254885Sdumbbell	u32 tile_flags = 0;
158254885Sdumbbell	u32 idx_value;
159254885Sdumbbell
160254885Sdumbbell	ib = p->ib.ptr;
161254885Sdumbbell	track = (struct r100_cs_track *)p->track;
162254885Sdumbbell	idx_value = radeon_get_ib_value(p, idx);
163254885Sdumbbell	switch (reg) {
164254885Sdumbbell	case RADEON_CRTC_GUI_TRIG_VLINE:
165254885Sdumbbell		r = r100_cs_packet_parse_vline(p);
166254885Sdumbbell		if (r) {
167254885Sdumbbell			DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
168254885Sdumbbell				  idx, reg);
169254885Sdumbbell			r100_cs_dump_packet(p, pkt);
170254885Sdumbbell			return r;
171254885Sdumbbell		}
172254885Sdumbbell		break;
173254885Sdumbbell		/* FIXME: only allow PACKET3 blit? easier to check for out of
174254885Sdumbbell		 * range access */
175254885Sdumbbell	case RADEON_DST_PITCH_OFFSET:
176254885Sdumbbell	case RADEON_SRC_PITCH_OFFSET:
177254885Sdumbbell		r = r100_reloc_pitch_offset(p, pkt, idx, reg);
178254885Sdumbbell		if (r)
179254885Sdumbbell			return r;
180254885Sdumbbell		break;
181254885Sdumbbell	case RADEON_RB3D_DEPTHOFFSET:
182254885Sdumbbell		r = r100_cs_packet_next_reloc(p, &reloc);
183254885Sdumbbell		if (r) {
184254885Sdumbbell			DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
185254885Sdumbbell				  idx, reg);
186254885Sdumbbell			r100_cs_dump_packet(p, pkt);
187254885Sdumbbell			return r;
188254885Sdumbbell		}
189254885Sdumbbell		track->zb.robj = reloc->robj;
190254885Sdumbbell		track->zb.offset = idx_value;
191254885Sdumbbell		track->zb_dirty = true;
192254885Sdumbbell		ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
193254885Sdumbbell		break;
194254885Sdumbbell	case RADEON_RB3D_COLOROFFSET:
195254885Sdumbbell		r = r100_cs_packet_next_reloc(p, &reloc);
196254885Sdumbbell		if (r) {
197254885Sdumbbell			DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
198254885Sdumbbell				  idx, reg);
199254885Sdumbbell			r100_cs_dump_packet(p, pkt);
200254885Sdumbbell			return r;
201254885Sdumbbell		}
202254885Sdumbbell		track->cb[0].robj = reloc->robj;
203254885Sdumbbell		track->cb[0].offset = idx_value;
204254885Sdumbbell		track->cb_dirty = true;
205254885Sdumbbell		ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
206254885Sdumbbell		break;
207254885Sdumbbell	case R200_PP_TXOFFSET_0:
208254885Sdumbbell	case R200_PP_TXOFFSET_1:
209254885Sdumbbell	case R200_PP_TXOFFSET_2:
210254885Sdumbbell	case R200_PP_TXOFFSET_3:
211254885Sdumbbell	case R200_PP_TXOFFSET_4:
212254885Sdumbbell	case R200_PP_TXOFFSET_5:
213254885Sdumbbell		i = (reg - R200_PP_TXOFFSET_0) / 24;
214254885Sdumbbell		r = r100_cs_packet_next_reloc(p, &reloc);
215254885Sdumbbell		if (r) {
216254885Sdumbbell			DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
217254885Sdumbbell				  idx, reg);
218254885Sdumbbell			r100_cs_dump_packet(p, pkt);
219254885Sdumbbell			return r;
220254885Sdumbbell		}
221254885Sdumbbell		if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
222254885Sdumbbell			if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
223254885Sdumbbell				tile_flags |= R200_TXO_MACRO_TILE;
224254885Sdumbbell			if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
225254885Sdumbbell				tile_flags |= R200_TXO_MICRO_TILE;
226254885Sdumbbell
227254885Sdumbbell			tmp = idx_value & ~(0x7 << 2);
228254885Sdumbbell			tmp |= tile_flags;
229254885Sdumbbell			ib[idx] = tmp + ((u32)reloc->lobj.gpu_offset);
230254885Sdumbbell		} else
231254885Sdumbbell			ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
232254885Sdumbbell		track->textures[i].robj = reloc->robj;
233254885Sdumbbell		track->tex_dirty = true;
234254885Sdumbbell		break;
235254885Sdumbbell	case R200_PP_CUBIC_OFFSET_F1_0:
236254885Sdumbbell	case R200_PP_CUBIC_OFFSET_F2_0:
237254885Sdumbbell	case R200_PP_CUBIC_OFFSET_F3_0:
238254885Sdumbbell	case R200_PP_CUBIC_OFFSET_F4_0:
239254885Sdumbbell	case R200_PP_CUBIC_OFFSET_F5_0:
240254885Sdumbbell	case R200_PP_CUBIC_OFFSET_F1_1:
241254885Sdumbbell	case R200_PP_CUBIC_OFFSET_F2_1:
242254885Sdumbbell	case R200_PP_CUBIC_OFFSET_F3_1:
243254885Sdumbbell	case R200_PP_CUBIC_OFFSET_F4_1:
244254885Sdumbbell	case R200_PP_CUBIC_OFFSET_F5_1:
245254885Sdumbbell	case R200_PP_CUBIC_OFFSET_F1_2:
246254885Sdumbbell	case R200_PP_CUBIC_OFFSET_F2_2:
247254885Sdumbbell	case R200_PP_CUBIC_OFFSET_F3_2:
248254885Sdumbbell	case R200_PP_CUBIC_OFFSET_F4_2:
249254885Sdumbbell	case R200_PP_CUBIC_OFFSET_F5_2:
250254885Sdumbbell	case R200_PP_CUBIC_OFFSET_F1_3:
251254885Sdumbbell	case R200_PP_CUBIC_OFFSET_F2_3:
252254885Sdumbbell	case R200_PP_CUBIC_OFFSET_F3_3:
253254885Sdumbbell	case R200_PP_CUBIC_OFFSET_F4_3:
254254885Sdumbbell	case R200_PP_CUBIC_OFFSET_F5_3:
255254885Sdumbbell	case R200_PP_CUBIC_OFFSET_F1_4:
256254885Sdumbbell	case R200_PP_CUBIC_OFFSET_F2_4:
257254885Sdumbbell	case R200_PP_CUBIC_OFFSET_F3_4:
258254885Sdumbbell	case R200_PP_CUBIC_OFFSET_F4_4:
259254885Sdumbbell	case R200_PP_CUBIC_OFFSET_F5_4:
260254885Sdumbbell	case R200_PP_CUBIC_OFFSET_F1_5:
261254885Sdumbbell	case R200_PP_CUBIC_OFFSET_F2_5:
262254885Sdumbbell	case R200_PP_CUBIC_OFFSET_F3_5:
263254885Sdumbbell	case R200_PP_CUBIC_OFFSET_F4_5:
264254885Sdumbbell	case R200_PP_CUBIC_OFFSET_F5_5:
265254885Sdumbbell		i = (reg - R200_PP_TXOFFSET_0) / 24;
266254885Sdumbbell		face = (reg - ((i * 24) + R200_PP_TXOFFSET_0)) / 4;
267254885Sdumbbell		r = r100_cs_packet_next_reloc(p, &reloc);
268254885Sdumbbell		if (r) {
269254885Sdumbbell			DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
270254885Sdumbbell				  idx, reg);
271254885Sdumbbell			r100_cs_dump_packet(p, pkt);
272254885Sdumbbell			return r;
273254885Sdumbbell		}
274254885Sdumbbell		track->textures[i].cube_info[face - 1].offset = idx_value;
275254885Sdumbbell		ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
276254885Sdumbbell		track->textures[i].cube_info[face - 1].robj = reloc->robj;
277254885Sdumbbell		track->tex_dirty = true;
278254885Sdumbbell		break;
279254885Sdumbbell	case RADEON_RE_WIDTH_HEIGHT:
280254885Sdumbbell		track->maxy = ((idx_value >> 16) & 0x7FF);
281254885Sdumbbell		track->cb_dirty = true;
282254885Sdumbbell		track->zb_dirty = true;
283254885Sdumbbell		break;
284254885Sdumbbell	case RADEON_RB3D_COLORPITCH:
285254885Sdumbbell		r = r100_cs_packet_next_reloc(p, &reloc);
286254885Sdumbbell		if (r) {
287254885Sdumbbell			DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
288254885Sdumbbell				  idx, reg);
289254885Sdumbbell			r100_cs_dump_packet(p, pkt);
290254885Sdumbbell			return r;
291254885Sdumbbell		}
292254885Sdumbbell
293254885Sdumbbell		if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
294254885Sdumbbell			if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
295254885Sdumbbell				tile_flags |= RADEON_COLOR_TILE_ENABLE;
296254885Sdumbbell			if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
297254885Sdumbbell				tile_flags |= RADEON_COLOR_MICROTILE_ENABLE;
298254885Sdumbbell
299254885Sdumbbell			tmp = idx_value & ~(0x7 << 16);
300254885Sdumbbell			tmp |= tile_flags;
301254885Sdumbbell			ib[idx] = tmp;
302254885Sdumbbell		} else
303254885Sdumbbell			ib[idx] = idx_value;
304254885Sdumbbell
305254885Sdumbbell		track->cb[0].pitch = idx_value & RADEON_COLORPITCH_MASK;
306254885Sdumbbell		track->cb_dirty = true;
307254885Sdumbbell		break;
308254885Sdumbbell	case RADEON_RB3D_DEPTHPITCH:
309254885Sdumbbell		track->zb.pitch = idx_value & RADEON_DEPTHPITCH_MASK;
310254885Sdumbbell		track->zb_dirty = true;
311254885Sdumbbell		break;
312254885Sdumbbell	case RADEON_RB3D_CNTL:
313254885Sdumbbell		switch ((idx_value >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f) {
314254885Sdumbbell		case 7:
315254885Sdumbbell		case 8:
316254885Sdumbbell		case 9:
317254885Sdumbbell		case 11:
318254885Sdumbbell		case 12:
319254885Sdumbbell			track->cb[0].cpp = 1;
320254885Sdumbbell			break;
321254885Sdumbbell		case 3:
322254885Sdumbbell		case 4:
323254885Sdumbbell		case 15:
324254885Sdumbbell			track->cb[0].cpp = 2;
325254885Sdumbbell			break;
326254885Sdumbbell		case 6:
327254885Sdumbbell			track->cb[0].cpp = 4;
328254885Sdumbbell			break;
329254885Sdumbbell		default:
330254885Sdumbbell			DRM_ERROR("Invalid color buffer format (%d) !\n",
331254885Sdumbbell				  ((idx_value >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f));
332254885Sdumbbell			return -EINVAL;
333254885Sdumbbell		}
334254885Sdumbbell		if (idx_value & RADEON_DEPTHXY_OFFSET_ENABLE) {
335254885Sdumbbell			DRM_ERROR("No support for depth xy offset in kms\n");
336254885Sdumbbell			return -EINVAL;
337254885Sdumbbell		}
338254885Sdumbbell
339254885Sdumbbell		track->z_enabled = !!(idx_value & RADEON_Z_ENABLE);
340254885Sdumbbell		track->cb_dirty = true;
341254885Sdumbbell		track->zb_dirty = true;
342254885Sdumbbell		break;
343254885Sdumbbell	case RADEON_RB3D_ZSTENCILCNTL:
344254885Sdumbbell		switch (idx_value & 0xf) {
345254885Sdumbbell		case 0:
346254885Sdumbbell			track->zb.cpp = 2;
347254885Sdumbbell			break;
348254885Sdumbbell		case 2:
349254885Sdumbbell		case 3:
350254885Sdumbbell		case 4:
351254885Sdumbbell		case 5:
352254885Sdumbbell		case 9:
353254885Sdumbbell		case 11:
354254885Sdumbbell			track->zb.cpp = 4;
355254885Sdumbbell			break;
356254885Sdumbbell		default:
357254885Sdumbbell			break;
358254885Sdumbbell		}
359254885Sdumbbell		track->zb_dirty = true;
360254885Sdumbbell		break;
361254885Sdumbbell	case RADEON_RB3D_ZPASS_ADDR:
362254885Sdumbbell		r = r100_cs_packet_next_reloc(p, &reloc);
363254885Sdumbbell		if (r) {
364254885Sdumbbell			DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
365254885Sdumbbell				  idx, reg);
366254885Sdumbbell			r100_cs_dump_packet(p, pkt);
367254885Sdumbbell			return r;
368254885Sdumbbell		}
369254885Sdumbbell		ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
370254885Sdumbbell		break;
371254885Sdumbbell	case RADEON_PP_CNTL:
372254885Sdumbbell		{
373254885Sdumbbell			uint32_t temp = idx_value >> 4;
374254885Sdumbbell			for (i = 0; i < track->num_texture; i++)
375254885Sdumbbell				track->textures[i].enabled = !!(temp & (1 << i));
376254885Sdumbbell			track->tex_dirty = true;
377254885Sdumbbell		}
378254885Sdumbbell		break;
379254885Sdumbbell	case RADEON_SE_VF_CNTL:
380254885Sdumbbell		track->vap_vf_cntl = idx_value;
381254885Sdumbbell		break;
382254885Sdumbbell	case 0x210c:
383254885Sdumbbell		/* VAP_VF_MAX_VTX_INDX */
384254885Sdumbbell		track->max_indx = idx_value & 0x00FFFFFFUL;
385254885Sdumbbell		break;
386254885Sdumbbell	case R200_SE_VTX_FMT_0:
387254885Sdumbbell		track->vtx_size = r200_get_vtx_size_0(idx_value);
388254885Sdumbbell		break;
389254885Sdumbbell	case R200_SE_VTX_FMT_1:
390254885Sdumbbell		track->vtx_size += r200_get_vtx_size_1(idx_value);
391254885Sdumbbell		break;
392254885Sdumbbell	case R200_PP_TXSIZE_0:
393254885Sdumbbell	case R200_PP_TXSIZE_1:
394254885Sdumbbell	case R200_PP_TXSIZE_2:
395254885Sdumbbell	case R200_PP_TXSIZE_3:
396254885Sdumbbell	case R200_PP_TXSIZE_4:
397254885Sdumbbell	case R200_PP_TXSIZE_5:
398254885Sdumbbell		i = (reg - R200_PP_TXSIZE_0) / 32;
399254885Sdumbbell		track->textures[i].width = (idx_value & RADEON_TEX_USIZE_MASK) + 1;
400254885Sdumbbell		track->textures[i].height = ((idx_value & RADEON_TEX_VSIZE_MASK) >> RADEON_TEX_VSIZE_SHIFT) + 1;
401254885Sdumbbell		track->tex_dirty = true;
402254885Sdumbbell		break;
403254885Sdumbbell	case R200_PP_TXPITCH_0:
404254885Sdumbbell	case R200_PP_TXPITCH_1:
405254885Sdumbbell	case R200_PP_TXPITCH_2:
406254885Sdumbbell	case R200_PP_TXPITCH_3:
407254885Sdumbbell	case R200_PP_TXPITCH_4:
408254885Sdumbbell	case R200_PP_TXPITCH_5:
409254885Sdumbbell		i = (reg - R200_PP_TXPITCH_0) / 32;
410254885Sdumbbell		track->textures[i].pitch = idx_value + 32;
411254885Sdumbbell		track->tex_dirty = true;
412254885Sdumbbell		break;
413254885Sdumbbell	case R200_PP_TXFILTER_0:
414254885Sdumbbell	case R200_PP_TXFILTER_1:
415254885Sdumbbell	case R200_PP_TXFILTER_2:
416254885Sdumbbell	case R200_PP_TXFILTER_3:
417254885Sdumbbell	case R200_PP_TXFILTER_4:
418254885Sdumbbell	case R200_PP_TXFILTER_5:
419254885Sdumbbell		i = (reg - R200_PP_TXFILTER_0) / 32;
420254885Sdumbbell		track->textures[i].num_levels = ((idx_value & R200_MAX_MIP_LEVEL_MASK)
421254885Sdumbbell						 >> R200_MAX_MIP_LEVEL_SHIFT);
422254885Sdumbbell		tmp = (idx_value >> 23) & 0x7;
423254885Sdumbbell		if (tmp == 2 || tmp == 6)
424254885Sdumbbell			track->textures[i].roundup_w = false;
425254885Sdumbbell		tmp = (idx_value >> 27) & 0x7;
426254885Sdumbbell		if (tmp == 2 || tmp == 6)
427254885Sdumbbell			track->textures[i].roundup_h = false;
428254885Sdumbbell		track->tex_dirty = true;
429254885Sdumbbell		break;
430254885Sdumbbell	case R200_PP_TXMULTI_CTL_0:
431254885Sdumbbell	case R200_PP_TXMULTI_CTL_1:
432254885Sdumbbell	case R200_PP_TXMULTI_CTL_2:
433254885Sdumbbell	case R200_PP_TXMULTI_CTL_3:
434254885Sdumbbell	case R200_PP_TXMULTI_CTL_4:
435254885Sdumbbell	case R200_PP_TXMULTI_CTL_5:
436254885Sdumbbell		i = (reg - R200_PP_TXMULTI_CTL_0) / 32;
437254885Sdumbbell		break;
438254885Sdumbbell	case R200_PP_TXFORMAT_X_0:
439254885Sdumbbell	case R200_PP_TXFORMAT_X_1:
440254885Sdumbbell	case R200_PP_TXFORMAT_X_2:
441254885Sdumbbell	case R200_PP_TXFORMAT_X_3:
442254885Sdumbbell	case R200_PP_TXFORMAT_X_4:
443254885Sdumbbell	case R200_PP_TXFORMAT_X_5:
444254885Sdumbbell		i = (reg - R200_PP_TXFORMAT_X_0) / 32;
445254885Sdumbbell		track->textures[i].txdepth = idx_value & 0x7;
446254885Sdumbbell		tmp = (idx_value >> 16) & 0x3;
447254885Sdumbbell		/* 2D, 3D, CUBE */
448254885Sdumbbell		switch (tmp) {
449254885Sdumbbell		case 0:
450254885Sdumbbell		case 3:
451254885Sdumbbell		case 4:
452254885Sdumbbell		case 5:
453254885Sdumbbell		case 6:
454254885Sdumbbell		case 7:
455254885Sdumbbell			/* 1D/2D */
456254885Sdumbbell			track->textures[i].tex_coord_type = 0;
457254885Sdumbbell			break;
458254885Sdumbbell		case 1:
459254885Sdumbbell			/* CUBE */
460254885Sdumbbell			track->textures[i].tex_coord_type = 2;
461254885Sdumbbell			break;
462254885Sdumbbell		case 2:
463254885Sdumbbell			/* 3D */
464254885Sdumbbell			track->textures[i].tex_coord_type = 1;
465254885Sdumbbell			break;
466254885Sdumbbell		}
467254885Sdumbbell		track->tex_dirty = true;
468254885Sdumbbell		break;
469254885Sdumbbell	case R200_PP_TXFORMAT_0:
470254885Sdumbbell	case R200_PP_TXFORMAT_1:
471254885Sdumbbell	case R200_PP_TXFORMAT_2:
472254885Sdumbbell	case R200_PP_TXFORMAT_3:
473254885Sdumbbell	case R200_PP_TXFORMAT_4:
474254885Sdumbbell	case R200_PP_TXFORMAT_5:
475254885Sdumbbell		i = (reg - R200_PP_TXFORMAT_0) / 32;
476254885Sdumbbell		if (idx_value & R200_TXFORMAT_NON_POWER2) {
477254885Sdumbbell			track->textures[i].use_pitch = 1;
478254885Sdumbbell		} else {
479254885Sdumbbell			track->textures[i].use_pitch = 0;
480254885Sdumbbell			track->textures[i].width = 1 << ((idx_value >> RADEON_TXFORMAT_WIDTH_SHIFT) & RADEON_TXFORMAT_WIDTH_MASK);
481254885Sdumbbell			track->textures[i].height = 1 << ((idx_value >> RADEON_TXFORMAT_HEIGHT_SHIFT) & RADEON_TXFORMAT_HEIGHT_MASK);
482254885Sdumbbell		}
483254885Sdumbbell		if (idx_value & R200_TXFORMAT_LOOKUP_DISABLE)
484254885Sdumbbell			track->textures[i].lookup_disable = true;
485254885Sdumbbell		switch ((idx_value & RADEON_TXFORMAT_FORMAT_MASK)) {
486254885Sdumbbell		case R200_TXFORMAT_I8:
487254885Sdumbbell		case R200_TXFORMAT_RGB332:
488254885Sdumbbell		case R200_TXFORMAT_Y8:
489254885Sdumbbell			track->textures[i].cpp = 1;
490254885Sdumbbell			track->textures[i].compress_format = R100_TRACK_COMP_NONE;
491254885Sdumbbell			break;
492254885Sdumbbell		case R200_TXFORMAT_AI88:
493254885Sdumbbell		case R200_TXFORMAT_ARGB1555:
494254885Sdumbbell		case R200_TXFORMAT_RGB565:
495254885Sdumbbell		case R200_TXFORMAT_ARGB4444:
496254885Sdumbbell		case R200_TXFORMAT_VYUY422:
497254885Sdumbbell		case R200_TXFORMAT_YVYU422:
498254885Sdumbbell		case R200_TXFORMAT_LDVDU655:
499254885Sdumbbell		case R200_TXFORMAT_DVDU88:
500254885Sdumbbell		case R200_TXFORMAT_AVYU4444:
501254885Sdumbbell			track->textures[i].cpp = 2;
502254885Sdumbbell			track->textures[i].compress_format = R100_TRACK_COMP_NONE;
503254885Sdumbbell			break;
504254885Sdumbbell		case R200_TXFORMAT_ARGB8888:
505254885Sdumbbell		case R200_TXFORMAT_RGBA8888:
506254885Sdumbbell		case R200_TXFORMAT_ABGR8888:
507254885Sdumbbell		case R200_TXFORMAT_BGR111110:
508254885Sdumbbell		case R200_TXFORMAT_LDVDU8888:
509254885Sdumbbell			track->textures[i].cpp = 4;
510254885Sdumbbell			track->textures[i].compress_format = R100_TRACK_COMP_NONE;
511254885Sdumbbell			break;
512254885Sdumbbell		case R200_TXFORMAT_DXT1:
513254885Sdumbbell			track->textures[i].cpp = 1;
514254885Sdumbbell			track->textures[i].compress_format = R100_TRACK_COMP_DXT1;
515254885Sdumbbell			break;
516254885Sdumbbell		case R200_TXFORMAT_DXT23:
517254885Sdumbbell		case R200_TXFORMAT_DXT45:
518254885Sdumbbell			track->textures[i].cpp = 1;
519254885Sdumbbell			track->textures[i].compress_format = R100_TRACK_COMP_DXT1;
520254885Sdumbbell			break;
521254885Sdumbbell		}
522254885Sdumbbell		track->textures[i].cube_info[4].width = 1 << ((idx_value >> 16) & 0xf);
523254885Sdumbbell		track->textures[i].cube_info[4].height = 1 << ((idx_value >> 20) & 0xf);
524254885Sdumbbell		track->tex_dirty = true;
525254885Sdumbbell		break;
526254885Sdumbbell	case R200_PP_CUBIC_FACES_0:
527254885Sdumbbell	case R200_PP_CUBIC_FACES_1:
528254885Sdumbbell	case R200_PP_CUBIC_FACES_2:
529254885Sdumbbell	case R200_PP_CUBIC_FACES_3:
530254885Sdumbbell	case R200_PP_CUBIC_FACES_4:
531254885Sdumbbell	case R200_PP_CUBIC_FACES_5:
532254885Sdumbbell		tmp = idx_value;
533254885Sdumbbell		i = (reg - R200_PP_CUBIC_FACES_0) / 32;
534254885Sdumbbell		for (face = 0; face < 4; face++) {
535254885Sdumbbell			track->textures[i].cube_info[face].width = 1 << ((tmp >> (face * 8)) & 0xf);
536254885Sdumbbell			track->textures[i].cube_info[face].height = 1 << ((tmp >> ((face * 8) + 4)) & 0xf);
537254885Sdumbbell		}
538254885Sdumbbell		track->tex_dirty = true;
539254885Sdumbbell		break;
540254885Sdumbbell	default:
541254885Sdumbbell		DRM_ERROR("Forbidden register 0x%04X in cs at %d\n",
542254885Sdumbbell		       reg, idx);
543254885Sdumbbell		return -EINVAL;
544254885Sdumbbell	}
545254885Sdumbbell	return 0;
546254885Sdumbbell}
547254885Sdumbbell
548254885Sdumbbellvoid r200_set_safe_registers(struct radeon_device *rdev)
549254885Sdumbbell{
550254885Sdumbbell	rdev->config.r100.reg_safe_bm = r200_reg_safe_bm;
551280183Sdumbbell	rdev->config.r100.reg_safe_bm_size = ARRAY_SIZE(r200_reg_safe_bm);
552254885Sdumbbell}
553