r200.c revision 256281
1228692Sdes/*
2141098Sdes * Copyright 2008 Advanced Micro Devices, Inc.
3117610Sdes * Copyright 2008 Red Hat Inc.
4141098Sdes * Copyright 2009 Jerome Glisse.
5228692Sdes *
6228692Sdes * Permission is hereby granted, free of charge, to any person obtaining a
7117610Sdes * copy of this software and associated documentation files (the "Software"),
8117610Sdes * to deal in the Software without restriction, including without limitation
9117610Sdes * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10117610Sdes * and/or sell copies of the Software, and to permit persons to whom the
11117610Sdes * Software is furnished to do so, subject to the following conditions:
12117610Sdes *
13117610Sdes * The above copyright notice and this permission notice shall be included in
14117610Sdes * all copies or substantial portions of the Software.
15117610Sdes *
16117610Sdes * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17147455Sdes * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18174832Sdes * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19117610Sdes * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
20117610Sdes * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21228692Sdes * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22117610Sdes * OTHER DEALINGS IN THE SOFTWARE.
23228692Sdes *
24141098Sdes * Authors: Dave Airlie
25141098Sdes *          Alex Deucher
26141098Sdes *          Jerome Glisse
27141098Sdes */
28117610Sdes
29141098Sdes#include <sys/cdefs.h>
30117610Sdes__FBSDID("$FreeBSD: stable/10/sys/dev/drm2/radeon/r200.c 254885 2013-08-25 19:37:15Z dumbbell $");
31117610Sdes
32117610Sdes#include <dev/drm2/drmP.h>
33117610Sdes#include <dev/drm2/radeon/radeon_drm.h>
34117610Sdes#include "radeon_reg.h"
35117610Sdes#include "radeon.h"
36117610Sdes#include "radeon_asic.h"
37117610Sdes
38141098Sdes#include "r100d.h"
39141098Sdes#include "r200_reg_safe.h"
40141098Sdes
41141098Sdes#include "r100_track.h"
42141098Sdes
43141098Sdesstatic int r200_get_vtx_size_0(uint32_t vtx_fmt_0)
44174832Sdes{
45141098Sdes	int vtx_size, i;
46141098Sdes	vtx_size = 2;
47228692Sdes
48141098Sdes	if (vtx_fmt_0 & R200_VTX_Z0)
49141098Sdes		vtx_size++;
50141098Sdes	if (vtx_fmt_0 & R200_VTX_W0)
51141098Sdes		vtx_size++;
52228692Sdes	/* blend weight */
53228692Sdes	if (vtx_fmt_0 & (0x7 << R200_VTX_WEIGHT_COUNT_SHIFT))
54228692Sdes		vtx_size += (vtx_fmt_0 >> R200_VTX_WEIGHT_COUNT_SHIFT) & 0x7;
55228692Sdes	if (vtx_fmt_0 & R200_VTX_PV_MATRIX_SEL)
56228692Sdes		vtx_size++;
57228692Sdes	if (vtx_fmt_0 & R200_VTX_N0)
58228692Sdes		vtx_size += 3;
59228692Sdes	if (vtx_fmt_0 & R200_VTX_POINT_SIZE)
60228692Sdes		vtx_size++;
61228692Sdes	if (vtx_fmt_0 & R200_VTX_DISCRETE_FOG)
62141098Sdes		vtx_size++;
63141098Sdes	if (vtx_fmt_0 & R200_VTX_SHININESS_0)
64141098Sdes		vtx_size++;
65141098Sdes	if (vtx_fmt_0 & R200_VTX_SHININESS_1)
66228692Sdes		vtx_size++;
67228692Sdes	for (i = 0; i < 8; i++) {
68228692Sdes		int color_size = (vtx_fmt_0 >> (11 + 2*i)) & 0x3;
69228692Sdes		switch (color_size) {
70228692Sdes		case 0: break;
71228692Sdes		case 1: vtx_size++; break;
72228692Sdes		case 2: vtx_size += 3; break;
73228692Sdes		case 3: vtx_size += 4; break;
74228692Sdes		}
75228692Sdes	}
76228692Sdes	if (vtx_fmt_0 & R200_VTX_XY1)
77228692Sdes		vtx_size += 2;
78228692Sdes	if (vtx_fmt_0 & R200_VTX_Z1)
79228692Sdes		vtx_size++;
80228692Sdes	if (vtx_fmt_0 & R200_VTX_W1)
81228692Sdes		vtx_size++;
82228692Sdes	if (vtx_fmt_0 & R200_VTX_N1)
83228692Sdes		vtx_size += 3;
84228692Sdes	return vtx_size;
85228692Sdes}
86228692Sdes
87228692Sdesint r200_copy_dma(struct radeon_device *rdev,
88228692Sdes		  uint64_t src_offset,
89228692Sdes		  uint64_t dst_offset,
90228692Sdes		  unsigned num_gpu_pages,
91141098Sdes		  struct radeon_fence **fence)
92117610Sdes{
93141098Sdes	struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
94141098Sdes	uint32_t size;
95141098Sdes	uint32_t cur_size;
96141098Sdes	int i, num_loops;
97117610Sdes	int r = 0;
98117610Sdes
99141098Sdes	/* radeon pitch is /64 */
100117610Sdes	size = num_gpu_pages << RADEON_GPU_PAGE_SHIFT;
101141098Sdes	num_loops = DIV_ROUND_UP(size, 0x1FFFFF);
102117610Sdes	r = radeon_ring_lock(rdev, ring, num_loops * 4 + 64);
103117610Sdes	if (r) {
104141098Sdes		DRM_ERROR("radeon: moving bo (%d).\n", r);
105141098Sdes		return r;
106117610Sdes	}
107228692Sdes	/* Must wait for 2D idle & clean before DMA or hangs might happen */
108117610Sdes	radeon_ring_write(ring, PACKET0(RADEON_WAIT_UNTIL, 0));
109228692Sdes	radeon_ring_write(ring, (1 << 16));
110228692Sdes	for (i = 0; i < num_loops; i++) {
111141098Sdes		cur_size = size;
112141098Sdes		if (cur_size > 0x1FFFFF) {
113141098Sdes			cur_size = 0x1FFFFF;
114141098Sdes		}
115117610Sdes		size -= cur_size;
116228692Sdes		radeon_ring_write(ring, PACKET0(0x720, 2));
117174832Sdes		radeon_ring_write(ring, src_offset);
118228692Sdes		radeon_ring_write(ring, dst_offset);
119141098Sdes		radeon_ring_write(ring, cur_size | (1 << 31) | (1 << 30));
120141098Sdes		src_offset += cur_size;
121141098Sdes		dst_offset += cur_size;
122117610Sdes	}
123228692Sdes	radeon_ring_write(ring, PACKET0(RADEON_WAIT_UNTIL, 0));
124141098Sdes	radeon_ring_write(ring, RADEON_WAIT_DMA_GUI_IDLE);
125141098Sdes	if (fence) {
126141098Sdes		r = radeon_fence_emit(rdev, fence, RADEON_RING_TYPE_GFX_INDEX);
127117610Sdes	}
128117610Sdes	radeon_ring_unlock_commit(rdev, ring);
129228692Sdes	return r;
130117610Sdes}
131141098Sdes
132141098Sdes
133228692Sdesstatic int r200_get_vtx_size_1(uint32_t vtx_fmt_1)
134228692Sdes{
135228692Sdes	int vtx_size, i, tex_size;
136228692Sdes	vtx_size = 0;
137228692Sdes	for (i = 0; i < 6; i++) {
138117610Sdes		tex_size = (vtx_fmt_1 >> (i * 3)) & 0x7;
139117610Sdes		if (tex_size > 4)
140228692Sdes			continue;
141228692Sdes		vtx_size += tex_size;
142117610Sdes	}
143141098Sdes	return vtx_size;
144141098Sdes}
145141098Sdes
146141098Sdesint r200_packet0_check(struct radeon_cs_parser *p,
147228692Sdes		       struct radeon_cs_packet *pkt,
148141098Sdes		       unsigned idx, unsigned reg)
149141098Sdes{
150117610Sdes	struct radeon_cs_reloc *reloc;
151174832Sdes	struct r100_cs_track *track;
152141098Sdes	volatile uint32_t *ib;
153141098Sdes	uint32_t tmp;
154141098Sdes	int r;
155117610Sdes	int i;
156228692Sdes	int face;
157228692Sdes	u32 tile_flags = 0;
158228692Sdes	u32 idx_value;
159228692Sdes
160228692Sdes	ib = p->ib.ptr;
161141098Sdes	track = (struct r100_cs_track *)p->track;
162228692Sdes	idx_value = radeon_get_ib_value(p, idx);
163117610Sdes	switch (reg) {
164141098Sdes	case RADEON_CRTC_GUI_TRIG_VLINE:
165117610Sdes		r = r100_cs_packet_parse_vline(p);
166174832Sdes		if (r) {
167174832Sdes			DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
168141098Sdes				  idx, reg);
169141098Sdes			r100_cs_dump_packet(p, pkt);
170141098Sdes			return r;
171141098Sdes		}
172141098Sdes		break;
173141098Sdes		/* FIXME: only allow PACKET3 blit? easier to check for out of
174228692Sdes		 * range access */
175141098Sdes	case RADEON_DST_PITCH_OFFSET:
176174832Sdes	case RADEON_SRC_PITCH_OFFSET:
177174832Sdes		r = r100_reloc_pitch_offset(p, pkt, idx, reg);
178174832Sdes		if (r)
179141098Sdes			return r;
180141098Sdes		break;
181141098Sdes	case RADEON_RB3D_DEPTHOFFSET:
182141098Sdes		r = r100_cs_packet_next_reloc(p, &reloc);
183141098Sdes		if (r) {
184141098Sdes			DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
185174832Sdes				  idx, reg);
186141098Sdes			r100_cs_dump_packet(p, pkt);
187141098Sdes			return r;
188117610Sdes		}
189141098Sdes		track->zb.robj = reloc->robj;
190141098Sdes		track->zb.offset = idx_value;
191174832Sdes		track->zb_dirty = true;
192141098Sdes		ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
193141098Sdes		break;
194141098Sdes	case RADEON_RB3D_COLOROFFSET:
195141098Sdes		r = r100_cs_packet_next_reloc(p, &reloc);
196174832Sdes		if (r) {
197141098Sdes			DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
198141098Sdes				  idx, reg);
199174832Sdes			r100_cs_dump_packet(p, pkt);
200141098Sdes			return r;
201141098Sdes		}
202228692Sdes		track->cb[0].robj = reloc->robj;
203141098Sdes		track->cb[0].offset = idx_value;
204141098Sdes		track->cb_dirty = true;
205228692Sdes		ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
206228692Sdes		break;
207228692Sdes	case R200_PP_TXOFFSET_0:
208117610Sdes	case R200_PP_TXOFFSET_1:
209117610Sdes	case R200_PP_TXOFFSET_2:
210117610Sdes	case R200_PP_TXOFFSET_3:
211117610Sdes	case R200_PP_TXOFFSET_4:
212141098Sdes	case R200_PP_TXOFFSET_5:
213141098Sdes		i = (reg - R200_PP_TXOFFSET_0) / 24;
214141098Sdes		r = r100_cs_packet_next_reloc(p, &reloc);
215141098Sdes		if (r) {
216228692Sdes			DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
217228692Sdes				  idx, reg);
218141098Sdes			r100_cs_dump_packet(p, pkt);
219141098Sdes			return r;
220141098Sdes		}
221228692Sdes		if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
222228692Sdes			if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
223228692Sdes				tile_flags |= R200_TXO_MACRO_TILE;
224141098Sdes			if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
225141098Sdes				tile_flags |= R200_TXO_MICRO_TILE;
226141098Sdes
227141098Sdes			tmp = idx_value & ~(0x7 << 2);
228141098Sdes			tmp |= tile_flags;
229141098Sdes			ib[idx] = tmp + ((u32)reloc->lobj.gpu_offset);
230141098Sdes		} else
231141098Sdes			ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
232141098Sdes		track->textures[i].robj = reloc->robj;
233117610Sdes		track->tex_dirty = true;
234141098Sdes		break;
235141098Sdes	case R200_PP_CUBIC_OFFSET_F1_0:
236141098Sdes	case R200_PP_CUBIC_OFFSET_F2_0:
237141098Sdes	case R200_PP_CUBIC_OFFSET_F3_0:
238141098Sdes	case R200_PP_CUBIC_OFFSET_F4_0:
239141098Sdes	case R200_PP_CUBIC_OFFSET_F5_0:
240141098Sdes	case R200_PP_CUBIC_OFFSET_F1_1:
241228692Sdes	case R200_PP_CUBIC_OFFSET_F2_1:
242141098Sdes	case R200_PP_CUBIC_OFFSET_F3_1:
243117610Sdes	case R200_PP_CUBIC_OFFSET_F4_1:
244117610Sdes	case R200_PP_CUBIC_OFFSET_F5_1:
245117610Sdes	case R200_PP_CUBIC_OFFSET_F1_2:
246117610Sdes	case R200_PP_CUBIC_OFFSET_F2_2:
247117610Sdes	case R200_PP_CUBIC_OFFSET_F3_2:
248117610Sdes	case R200_PP_CUBIC_OFFSET_F4_2:
249117610Sdes	case R200_PP_CUBIC_OFFSET_F5_2:
250117610Sdes	case R200_PP_CUBIC_OFFSET_F1_3:
251117610Sdes	case R200_PP_CUBIC_OFFSET_F2_3:
252117610Sdes	case R200_PP_CUBIC_OFFSET_F3_3:
253117610Sdes	case R200_PP_CUBIC_OFFSET_F4_3:
254117610Sdes	case R200_PP_CUBIC_OFFSET_F5_3:
255117610Sdes	case R200_PP_CUBIC_OFFSET_F1_4:
256228692Sdes	case R200_PP_CUBIC_OFFSET_F2_4:
257174832Sdes	case R200_PP_CUBIC_OFFSET_F3_4:
258174832Sdes	case R200_PP_CUBIC_OFFSET_F4_4:
259174832Sdes	case R200_PP_CUBIC_OFFSET_F5_4:
260174832Sdes	case R200_PP_CUBIC_OFFSET_F1_5:
261174832Sdes	case R200_PP_CUBIC_OFFSET_F2_5:
262174832Sdes	case R200_PP_CUBIC_OFFSET_F3_5:
263117610Sdes	case R200_PP_CUBIC_OFFSET_F4_5:
264117610Sdes	case R200_PP_CUBIC_OFFSET_F5_5:
265117610Sdes		i = (reg - R200_PP_TXOFFSET_0) / 24;
266117610Sdes		face = (reg - ((i * 24) + R200_PP_TXOFFSET_0)) / 4;
267117610Sdes		r = r100_cs_packet_next_reloc(p, &reloc);
268117610Sdes		if (r) {
269117610Sdes			DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
270117610Sdes				  idx, reg);
271117610Sdes			r100_cs_dump_packet(p, pkt);
272117610Sdes			return r;
273228692Sdes		}
274174832Sdes		track->textures[i].cube_info[face - 1].offset = idx_value;
275117610Sdes		ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
276117610Sdes		track->textures[i].cube_info[face - 1].robj = reloc->robj;
277117610Sdes		track->tex_dirty = true;
278117610Sdes		break;
279117610Sdes	case RADEON_RE_WIDTH_HEIGHT:
280228692Sdes		track->maxy = ((idx_value >> 16) & 0x7FF);
281228692Sdes		track->cb_dirty = true;
282174832Sdes		track->zb_dirty = true;
283174832Sdes		break;
284174832Sdes	case RADEON_RB3D_COLORPITCH:
285174832Sdes		r = r100_cs_packet_next_reloc(p, &reloc);
286174832Sdes		if (r) {
287174832Sdes			DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
288117610Sdes				  idx, reg);
289117610Sdes			r100_cs_dump_packet(p, pkt);
290117610Sdes			return r;
291117610Sdes		}
292117610Sdes
293117610Sdes		if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
294117610Sdes			if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
295117610Sdes				tile_flags |= RADEON_COLOR_TILE_ENABLE;
296117610Sdes			if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
297117610Sdes				tile_flags |= RADEON_COLOR_MICROTILE_ENABLE;
298117610Sdes
299117610Sdes			tmp = idx_value & ~(0x7 << 16);
300117610Sdes			tmp |= tile_flags;
301117610Sdes			ib[idx] = tmp;
302117610Sdes		} else
303117610Sdes			ib[idx] = idx_value;
304117610Sdes
305117610Sdes		track->cb[0].pitch = idx_value & RADEON_COLORPITCH_MASK;
306117610Sdes		track->cb_dirty = true;
307228692Sdes		break;
308174832Sdes	case RADEON_RB3D_DEPTHPITCH:
309117610Sdes		track->zb.pitch = idx_value & RADEON_DEPTHPITCH_MASK;
310117610Sdes		track->zb_dirty = true;
311117610Sdes		break;
312228692Sdes	case RADEON_RB3D_CNTL:
313117610Sdes		switch ((idx_value >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f) {
314141098Sdes		case 7:
315141098Sdes		case 8:
316228692Sdes		case 9:
317141098Sdes		case 11:
318117610Sdes		case 12:
319117610Sdes			track->cb[0].cpp = 1;
320141098Sdes			break;
321117610Sdes		case 3:
322117610Sdes		case 4:
323117610Sdes		case 15:
324228692Sdes			track->cb[0].cpp = 2;
325228692Sdes			break;
326141098Sdes		case 6:
327141098Sdes			track->cb[0].cpp = 4;
328117610Sdes			break;
329117610Sdes		default:
330117610Sdes			DRM_ERROR("Invalid color buffer format (%d) !\n",
331228692Sdes				  ((idx_value >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f));
332117610Sdes			return -EINVAL;
333141098Sdes		}
334141098Sdes		if (idx_value & RADEON_DEPTHXY_OFFSET_ENABLE) {
335141098Sdes			DRM_ERROR("No support for depth xy offset in kms\n");
336141098Sdes			return -EINVAL;
337141098Sdes		}
338141098Sdes
339141098Sdes		track->z_enabled = !!(idx_value & RADEON_Z_ENABLE);
340117610Sdes		track->cb_dirty = true;
341117610Sdes		track->zb_dirty = true;
342141098Sdes		break;
343228692Sdes	case RADEON_RB3D_ZSTENCILCNTL:
344117610Sdes		switch (idx_value & 0xf) {
345117610Sdes		case 0:
346141098Sdes			track->zb.cpp = 2;
347117610Sdes			break;
348117610Sdes		case 2:
349117610Sdes		case 3:
350228692Sdes		case 4:
351228692Sdes		case 5:
352228692Sdes		case 9:
353228692Sdes		case 11:
354141098Sdes			track->zb.cpp = 4;
355228692Sdes			break;
356228692Sdes		default:
357228692Sdes			break;
358228692Sdes		}
359228692Sdes		track->zb_dirty = true;
360228692Sdes		break;
361228692Sdes	case RADEON_RB3D_ZPASS_ADDR:
362141098Sdes		r = r100_cs_packet_next_reloc(p, &reloc);
363141098Sdes		if (r) {
364141098Sdes			DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
365141098Sdes				  idx, reg);
366141098Sdes			r100_cs_dump_packet(p, pkt);
367141098Sdes			return r;
368141098Sdes		}
369141098Sdes		ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
370228692Sdes		break;
371228692Sdes	case RADEON_PP_CNTL:
372228692Sdes		{
373141098Sdes			uint32_t temp = idx_value >> 4;
374228692Sdes			for (i = 0; i < track->num_texture; i++)
375117610Sdes				track->textures[i].enabled = !!(temp & (1 << i));
376117610Sdes			track->tex_dirty = true;
377141098Sdes		}
378228692Sdes		break;
379228692Sdes	case RADEON_SE_VF_CNTL:
380117610Sdes		track->vap_vf_cntl = idx_value;
381117610Sdes		break;
382141098Sdes	case 0x210c:
383117610Sdes		/* VAP_VF_MAX_VTX_INDX */
384117610Sdes		track->max_indx = idx_value & 0x00FFFFFFUL;
385228692Sdes		break;
386228692Sdes	case R200_SE_VTX_FMT_0:
387228692Sdes		track->vtx_size = r200_get_vtx_size_0(idx_value);
388228692Sdes		break;
389228692Sdes	case R200_SE_VTX_FMT_1:
390228692Sdes		track->vtx_size += r200_get_vtx_size_1(idx_value);
391228692Sdes		break;
392228692Sdes	case R200_PP_TXSIZE_0:
393228692Sdes	case R200_PP_TXSIZE_1:
394228692Sdes	case R200_PP_TXSIZE_2:
395228692Sdes	case R200_PP_TXSIZE_3:
396228692Sdes	case R200_PP_TXSIZE_4:
397141098Sdes	case R200_PP_TXSIZE_5:
398117610Sdes		i = (reg - R200_PP_TXSIZE_0) / 32;
399228692Sdes		track->textures[i].width = (idx_value & RADEON_TEX_USIZE_MASK) + 1;
400228692Sdes		track->textures[i].height = ((idx_value & RADEON_TEX_VSIZE_MASK) >> RADEON_TEX_VSIZE_SHIFT) + 1;
401228692Sdes		track->tex_dirty = true;
402228692Sdes		break;
403141098Sdes	case R200_PP_TXPITCH_0:
404228692Sdes	case R200_PP_TXPITCH_1:
405228692Sdes	case R200_PP_TXPITCH_2:
406141098Sdes	case R200_PP_TXPITCH_3:
407228692Sdes	case R200_PP_TXPITCH_4:
408117610Sdes	case R200_PP_TXPITCH_5:
409228692Sdes		i = (reg - R200_PP_TXPITCH_0) / 32;
410228692Sdes		track->textures[i].pitch = idx_value + 32;
411117610Sdes		track->tex_dirty = true;
412117610Sdes		break;
413117610Sdes	case R200_PP_TXFILTER_0:
414228692Sdes	case R200_PP_TXFILTER_1:
415117610Sdes	case R200_PP_TXFILTER_2:
416141098Sdes	case R200_PP_TXFILTER_3:
417228692Sdes	case R200_PP_TXFILTER_4:
418117610Sdes	case R200_PP_TXFILTER_5:
419228692Sdes		i = (reg - R200_PP_TXFILTER_0) / 32;
420228692Sdes		track->textures[i].num_levels = ((idx_value & R200_MAX_MIP_LEVEL_MASK)
421228692Sdes						 >> R200_MAX_MIP_LEVEL_SHIFT);
422228692Sdes		tmp = (idx_value >> 23) & 0x7;
423228692Sdes		if (tmp == 2 || tmp == 6)
424228692Sdes			track->textures[i].roundup_w = false;
425228692Sdes		tmp = (idx_value >> 27) & 0x7;
426228692Sdes		if (tmp == 2 || tmp == 6)
427228692Sdes			track->textures[i].roundup_h = false;
428228692Sdes		track->tex_dirty = true;
429228692Sdes		break;
430228692Sdes	case R200_PP_TXMULTI_CTL_0:
431228692Sdes	case R200_PP_TXMULTI_CTL_1:
432117610Sdes	case R200_PP_TXMULTI_CTL_2:
433228692Sdes	case R200_PP_TXMULTI_CTL_3:
434228692Sdes	case R200_PP_TXMULTI_CTL_4:
435228692Sdes	case R200_PP_TXMULTI_CTL_5:
436228692Sdes		i = (reg - R200_PP_TXMULTI_CTL_0) / 32;
437228692Sdes		break;
438117610Sdes	case R200_PP_TXFORMAT_X_0:
439117610Sdes	case R200_PP_TXFORMAT_X_1:
440117610Sdes	case R200_PP_TXFORMAT_X_2:
441117610Sdes	case R200_PP_TXFORMAT_X_3:
442117610Sdes	case R200_PP_TXFORMAT_X_4:
443117610Sdes	case R200_PP_TXFORMAT_X_5:
444117610Sdes		i = (reg - R200_PP_TXFORMAT_X_0) / 32;
445117610Sdes		track->textures[i].txdepth = idx_value & 0x7;
446117610Sdes		tmp = (idx_value >> 16) & 0x3;
447117610Sdes		/* 2D, 3D, CUBE */
448117610Sdes		switch (tmp) {
449117610Sdes		case 0:
450117610Sdes		case 3:
451117610Sdes		case 4:
452117610Sdes		case 5:
453117610Sdes		case 6:
454117610Sdes		case 7:
455117610Sdes			/* 1D/2D */
456117610Sdes			track->textures[i].tex_coord_type = 0;
457117610Sdes			break;
458141098Sdes		case 1:
459117610Sdes			/* CUBE */
460117610Sdes			track->textures[i].tex_coord_type = 2;
461117610Sdes			break;
462117610Sdes		case 2:
463117610Sdes			/* 3D */
464117610Sdes			track->textures[i].tex_coord_type = 1;
465117610Sdes			break;
466174832Sdes		}
467228692Sdes		track->tex_dirty = true;
468117610Sdes		break;
469117610Sdes	case R200_PP_TXFORMAT_0:
470117610Sdes	case R200_PP_TXFORMAT_1:
471117610Sdes	case R200_PP_TXFORMAT_2:
472117610Sdes	case R200_PP_TXFORMAT_3:
473117610Sdes	case R200_PP_TXFORMAT_4:
474117610Sdes	case R200_PP_TXFORMAT_5:
475117610Sdes		i = (reg - R200_PP_TXFORMAT_0) / 32;
476117610Sdes		if (idx_value & R200_TXFORMAT_NON_POWER2) {
477141098Sdes			track->textures[i].use_pitch = 1;
478228692Sdes		} else {
479117610Sdes			track->textures[i].use_pitch = 0;
480117610Sdes			track->textures[i].width = 1 << ((idx_value >> RADEON_TXFORMAT_WIDTH_SHIFT) & RADEON_TXFORMAT_WIDTH_MASK);
481117610Sdes			track->textures[i].height = 1 << ((idx_value >> RADEON_TXFORMAT_HEIGHT_SHIFT) & RADEON_TXFORMAT_HEIGHT_MASK);
482117610Sdes		}
483117610Sdes		if (idx_value & R200_TXFORMAT_LOOKUP_DISABLE)
484141098Sdes			track->textures[i].lookup_disable = true;
485141098Sdes		switch ((idx_value & RADEON_TXFORMAT_FORMAT_MASK)) {
486228692Sdes		case R200_TXFORMAT_I8:
487228692Sdes		case R200_TXFORMAT_RGB332:
488117610Sdes		case R200_TXFORMAT_Y8:
489117610Sdes			track->textures[i].cpp = 1;
490117610Sdes			track->textures[i].compress_format = R100_TRACK_COMP_NONE;
491117610Sdes			break;
492117610Sdes		case R200_TXFORMAT_AI88:
493117610Sdes		case R200_TXFORMAT_ARGB1555:
494228692Sdes		case R200_TXFORMAT_RGB565:
495228692Sdes		case R200_TXFORMAT_ARGB4444:
496228692Sdes		case R200_TXFORMAT_VYUY422:
497228692Sdes		case R200_TXFORMAT_YVYU422:
498117610Sdes		case R200_TXFORMAT_LDVDU655:
499117610Sdes		case R200_TXFORMAT_DVDU88:
500228692Sdes		case R200_TXFORMAT_AVYU4444:
501228692Sdes			track->textures[i].cpp = 2;
502228692Sdes			track->textures[i].compress_format = R100_TRACK_COMP_NONE;
503228692Sdes			break;
504117610Sdes		case R200_TXFORMAT_ARGB8888:
505117610Sdes		case R200_TXFORMAT_RGBA8888:
506228692Sdes		case R200_TXFORMAT_ABGR8888:
507228692Sdes		case R200_TXFORMAT_BGR111110:
508117610Sdes		case R200_TXFORMAT_LDVDU8888:
509117610Sdes			track->textures[i].cpp = 4;
510228692Sdes			track->textures[i].compress_format = R100_TRACK_COMP_NONE;
511228692Sdes			break;
512228692Sdes		case R200_TXFORMAT_DXT1:
513228692Sdes			track->textures[i].cpp = 1;
514228692Sdes			track->textures[i].compress_format = R100_TRACK_COMP_DXT1;
515228692Sdes			break;
516228692Sdes		case R200_TXFORMAT_DXT23:
517228692Sdes		case R200_TXFORMAT_DXT45:
518117610Sdes			track->textures[i].cpp = 1;
519117610Sdes			track->textures[i].compress_format = R100_TRACK_COMP_DXT1;
520117610Sdes			break;
521141098Sdes		}
522117610Sdes		track->textures[i].cube_info[4].width = 1 << ((idx_value >> 16) & 0xf);
523117610Sdes		track->textures[i].cube_info[4].height = 1 << ((idx_value >> 20) & 0xf);
524117610Sdes		track->tex_dirty = true;
525117610Sdes		break;
526117610Sdes	case R200_PP_CUBIC_FACES_0:
527117610Sdes	case R200_PP_CUBIC_FACES_1:
528141098Sdes	case R200_PP_CUBIC_FACES_2:
529141098Sdes	case R200_PP_CUBIC_FACES_3:
530141098Sdes	case R200_PP_CUBIC_FACES_4:
531141098Sdes	case R200_PP_CUBIC_FACES_5:
532141098Sdes		tmp = idx_value;
533141098Sdes		i = (reg - R200_PP_CUBIC_FACES_0) / 32;
534141098Sdes		for (face = 0; face < 4; face++) {
535141098Sdes			track->textures[i].cube_info[face].width = 1 << ((tmp >> (face * 8)) & 0xf);
536228692Sdes			track->textures[i].cube_info[face].height = 1 << ((tmp >> ((face * 8) + 4)) & 0xf);
537117610Sdes		}
538228692Sdes		track->tex_dirty = true;
539228692Sdes		break;
540117610Sdes	default:
541228692Sdes		DRM_ERROR("Forbidden register 0x%04X in cs at %d\n",
542228692Sdes		       reg, idx);
543228692Sdes		return -EINVAL;
544228692Sdes	}
545141098Sdes	return 0;
546228692Sdes}
547228692Sdes
548228692Sdesvoid r200_set_safe_registers(struct radeon_device *rdev)
549228692Sdes{
550141098Sdes	rdev->config.r100.reg_safe_bm = r200_reg_safe_bm;
551228692Sdes	rdev->config.r100.reg_safe_bm_size = DRM_ARRAY_SIZE(r200_reg_safe_bm);
552228692Sdes}
553228692Sdes