r200.c 15.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
/*
 * Copyright 2008 Advanced Micro Devices, Inc.
 * Copyright 2008 Red Hat Inc.
 * Copyright 2009 Jerome Glisse.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a
 * copy of this software and associated documentation files (the "Software"),
 * to deal in the Software without restriction, including without limitation
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 * and/or sell copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 *
 * Authors: Dave Airlie
 *          Alex Deucher
 *          Jerome Glisse
 */
28 29
#include <drm/drmP.h>
#include <drm/radeon_drm.h>
30 31
#include "radeon_reg.h"
#include "radeon.h"
32
#include "radeon_asic.h"
33

34
#include "r100d.h"
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82
#include "r200_reg_safe.h"

#include "r100_track.h"

static int r200_get_vtx_size_0(uint32_t vtx_fmt_0)
{
	int vtx_size, i;
	vtx_size = 2;

	if (vtx_fmt_0 & R200_VTX_Z0)
		vtx_size++;
	if (vtx_fmt_0 & R200_VTX_W0)
		vtx_size++;
	/* blend weight */
	if (vtx_fmt_0 & (0x7 << R200_VTX_WEIGHT_COUNT_SHIFT))
		vtx_size += (vtx_fmt_0 >> R200_VTX_WEIGHT_COUNT_SHIFT) & 0x7;
	if (vtx_fmt_0 & R200_VTX_PV_MATRIX_SEL)
		vtx_size++;
	if (vtx_fmt_0 & R200_VTX_N0)
		vtx_size += 3;
	if (vtx_fmt_0 & R200_VTX_POINT_SIZE)
		vtx_size++;
	if (vtx_fmt_0 & R200_VTX_DISCRETE_FOG)
		vtx_size++;
	if (vtx_fmt_0 & R200_VTX_SHININESS_0)
		vtx_size++;
	if (vtx_fmt_0 & R200_VTX_SHININESS_1)
		vtx_size++;
	for (i = 0; i < 8; i++) {
		int color_size = (vtx_fmt_0 >> (11 + 2*i)) & 0x3;
		switch (color_size) {
		case 0: break;
		case 1: vtx_size++; break;
		case 2: vtx_size += 3; break;
		case 3: vtx_size += 4; break;
		}
	}
	if (vtx_fmt_0 & R200_VTX_XY1)
		vtx_size += 2;
	if (vtx_fmt_0 & R200_VTX_Z1)
		vtx_size++;
	if (vtx_fmt_0 & R200_VTX_W1)
		vtx_size++;
	if (vtx_fmt_0 & R200_VTX_N1)
		vtx_size += 3;
	return vtx_size;
}

83 84 85
int r200_copy_dma(struct radeon_device *rdev,
		  uint64_t src_offset,
		  uint64_t dst_offset,
86
		  unsigned num_gpu_pages,
87
		  struct radeon_fence **fence)
88
{
89
	struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
90 91 92 93 94 95
	uint32_t size;
	uint32_t cur_size;
	int i, num_loops;
	int r = 0;

	/* radeon pitch is /64 */
96
	size = num_gpu_pages << RADEON_GPU_PAGE_SHIFT;
97
	num_loops = DIV_ROUND_UP(size, 0x1FFFFF);
98
	r = radeon_ring_lock(rdev, ring, num_loops * 4 + 64);
99 100 101 102 103
	if (r) {
		DRM_ERROR("radeon: moving bo (%d).\n", r);
		return r;
	}
	/* Must wait for 2D idle & clean before DMA or hangs might happen */
104 105
	radeon_ring_write(ring, PACKET0(RADEON_WAIT_UNTIL, 0));
	radeon_ring_write(ring, (1 << 16));
106 107 108 109 110 111
	for (i = 0; i < num_loops; i++) {
		cur_size = size;
		if (cur_size > 0x1FFFFF) {
			cur_size = 0x1FFFFF;
		}
		size -= cur_size;
112 113 114 115
		radeon_ring_write(ring, PACKET0(0x720, 2));
		radeon_ring_write(ring, src_offset);
		radeon_ring_write(ring, dst_offset);
		radeon_ring_write(ring, cur_size | (1 << 31) | (1 << 30));
116 117 118
		src_offset += cur_size;
		dst_offset += cur_size;
	}
119 120
	radeon_ring_write(ring, PACKET0(RADEON_WAIT_UNTIL, 0));
	radeon_ring_write(ring, RADEON_WAIT_DMA_GUI_IDLE);
121
	if (fence) {
122
		r = radeon_fence_emit(rdev, fence, RADEON_RING_TYPE_GFX_INDEX);
123
	}
124
	radeon_ring_unlock_commit(rdev, ring);
125 126 127 128
	return r;
}


129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
static int r200_get_vtx_size_1(uint32_t vtx_fmt_1)
{
	int vtx_size, i, tex_size;
	vtx_size = 0;
	for (i = 0; i < 6; i++) {
		tex_size = (vtx_fmt_1 >> (i * 3)) & 0x7;
		if (tex_size > 4)
			continue;
		vtx_size += tex_size;
	}
	return vtx_size;
}

int r200_packet0_check(struct radeon_cs_parser *p,
		       struct radeon_cs_packet *pkt,
		       unsigned idx, unsigned reg)
{
	struct radeon_cs_reloc *reloc;
	struct r100_cs_track *track;
	volatile uint32_t *ib;
	uint32_t tmp;
	int r;
	int i;
	int face;
	u32 tile_flags = 0;
154
	u32 idx_value;
155

156
	ib = p->ib.ptr;
157
	track = (struct r100_cs_track *)p->track;
158
	idx_value = radeon_get_ib_value(p, idx);
159 160 161 162 163 164
	switch (reg) {
	case RADEON_CRTC_GUI_TRIG_VLINE:
		r = r100_cs_packet_parse_vline(p);
		if (r) {
			DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
				  idx, reg);
165
			radeon_cs_dump_packet(p, pkt);
166 167 168 169 170 171 172 173 174 175 176 177
			return r;
		}
		break;
		/* FIXME: only allow PACKET3 blit? easier to check for out of
		 * range access */
	case RADEON_DST_PITCH_OFFSET:
	case RADEON_SRC_PITCH_OFFSET:
		r = r100_reloc_pitch_offset(p, pkt, idx, reg);
		if (r)
			return r;
		break;
	case RADEON_RB3D_DEPTHOFFSET:
178
		r = radeon_cs_packet_next_reloc(p, &reloc, 0);
179 180 181
		if (r) {
			DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
				  idx, reg);
182
			radeon_cs_dump_packet(p, pkt);
183 184 185
			return r;
		}
		track->zb.robj = reloc->robj;
186
		track->zb.offset = idx_value;
187
		track->zb_dirty = true;
188
		ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
189 190
		break;
	case RADEON_RB3D_COLOROFFSET:
191
		r = radeon_cs_packet_next_reloc(p, &reloc, 0);
192 193 194
		if (r) {
			DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
				  idx, reg);
195
			radeon_cs_dump_packet(p, pkt);
196 197 198
			return r;
		}
		track->cb[0].robj = reloc->robj;
199
		track->cb[0].offset = idx_value;
200
		track->cb_dirty = true;
201
		ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
202 203 204 205 206 207 208 209
		break;
	case R200_PP_TXOFFSET_0:
	case R200_PP_TXOFFSET_1:
	case R200_PP_TXOFFSET_2:
	case R200_PP_TXOFFSET_3:
	case R200_PP_TXOFFSET_4:
	case R200_PP_TXOFFSET_5:
		i = (reg - R200_PP_TXOFFSET_0) / 24;
210
		r = radeon_cs_packet_next_reloc(p, &reloc, 0);
211 212 213
		if (r) {
			DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
				  idx, reg);
214
			radeon_cs_dump_packet(p, pkt);
215 216
			return r;
		}
217 218 219 220 221 222 223 224 225 226 227
		if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
			if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
				tile_flags |= R200_TXO_MACRO_TILE;
			if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
				tile_flags |= R200_TXO_MICRO_TILE;

			tmp = idx_value & ~(0x7 << 2);
			tmp |= tile_flags;
			ib[idx] = tmp + ((u32)reloc->lobj.gpu_offset);
		} else
			ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
228
		track->textures[i].robj = reloc->robj;
229
		track->tex_dirty = true;
230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262
		break;
	case R200_PP_CUBIC_OFFSET_F1_0:
	case R200_PP_CUBIC_OFFSET_F2_0:
	case R200_PP_CUBIC_OFFSET_F3_0:
	case R200_PP_CUBIC_OFFSET_F4_0:
	case R200_PP_CUBIC_OFFSET_F5_0:
	case R200_PP_CUBIC_OFFSET_F1_1:
	case R200_PP_CUBIC_OFFSET_F2_1:
	case R200_PP_CUBIC_OFFSET_F3_1:
	case R200_PP_CUBIC_OFFSET_F4_1:
	case R200_PP_CUBIC_OFFSET_F5_1:
	case R200_PP_CUBIC_OFFSET_F1_2:
	case R200_PP_CUBIC_OFFSET_F2_2:
	case R200_PP_CUBIC_OFFSET_F3_2:
	case R200_PP_CUBIC_OFFSET_F4_2:
	case R200_PP_CUBIC_OFFSET_F5_2:
	case R200_PP_CUBIC_OFFSET_F1_3:
	case R200_PP_CUBIC_OFFSET_F2_3:
	case R200_PP_CUBIC_OFFSET_F3_3:
	case R200_PP_CUBIC_OFFSET_F4_3:
	case R200_PP_CUBIC_OFFSET_F5_3:
	case R200_PP_CUBIC_OFFSET_F1_4:
	case R200_PP_CUBIC_OFFSET_F2_4:
	case R200_PP_CUBIC_OFFSET_F3_4:
	case R200_PP_CUBIC_OFFSET_F4_4:
	case R200_PP_CUBIC_OFFSET_F5_4:
	case R200_PP_CUBIC_OFFSET_F1_5:
	case R200_PP_CUBIC_OFFSET_F2_5:
	case R200_PP_CUBIC_OFFSET_F3_5:
	case R200_PP_CUBIC_OFFSET_F4_5:
	case R200_PP_CUBIC_OFFSET_F5_5:
		i = (reg - R200_PP_TXOFFSET_0) / 24;
		face = (reg - ((i * 24) + R200_PP_TXOFFSET_0)) / 4;
263
		r = radeon_cs_packet_next_reloc(p, &reloc, 0);
264 265 266
		if (r) {
			DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
				  idx, reg);
267
			radeon_cs_dump_packet(p, pkt);
268 269
			return r;
		}
270 271
		track->textures[i].cube_info[face - 1].offset = idx_value;
		ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
272
		track->textures[i].cube_info[face - 1].robj = reloc->robj;
273
		track->tex_dirty = true;
274 275
		break;
	case RADEON_RE_WIDTH_HEIGHT:
276
		track->maxy = ((idx_value >> 16) & 0x7FF);
277 278
		track->cb_dirty = true;
		track->zb_dirty = true;
279 280
		break;
	case RADEON_RB3D_COLORPITCH:
281
		r = radeon_cs_packet_next_reloc(p, &reloc, 0);
282 283 284
		if (r) {
			DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
				  idx, reg);
285
			radeon_cs_dump_packet(p, pkt);
286 287 288
			return r;
		}

289 290 291 292 293
		if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
			if (reloc->lobj.tiling_flags & RADEON_TILING_MACRO)
				tile_flags |= RADEON_COLOR_TILE_ENABLE;
			if (reloc->lobj.tiling_flags & RADEON_TILING_MICRO)
				tile_flags |= RADEON_COLOR_MICROTILE_ENABLE;
294

295 296 297 298 299
			tmp = idx_value & ~(0x7 << 16);
			tmp |= tile_flags;
			ib[idx] = tmp;
		} else
			ib[idx] = idx_value;
300

301
		track->cb[0].pitch = idx_value & RADEON_COLORPITCH_MASK;
302
		track->cb_dirty = true;
303 304
		break;
	case RADEON_RB3D_DEPTHPITCH:
305
		track->zb.pitch = idx_value & RADEON_DEPTHPITCH_MASK;
306
		track->zb_dirty = true;
307 308
		break;
	case RADEON_RB3D_CNTL:
309
		switch ((idx_value >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f) {
310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326
		case 7:
		case 8:
		case 9:
		case 11:
		case 12:
			track->cb[0].cpp = 1;
			break;
		case 3:
		case 4:
		case 15:
			track->cb[0].cpp = 2;
			break;
		case 6:
			track->cb[0].cpp = 4;
			break;
		default:
			DRM_ERROR("Invalid color buffer format (%d) !\n",
327
				  ((idx_value >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f));
328 329
			return -EINVAL;
		}
330
		if (idx_value & RADEON_DEPTHXY_OFFSET_ENABLE) {
331 332 333 334
			DRM_ERROR("No support for depth xy offset in kms\n");
			return -EINVAL;
		}

335
		track->z_enabled = !!(idx_value & RADEON_Z_ENABLE);
336 337
		track->cb_dirty = true;
		track->zb_dirty = true;
338 339
		break;
	case RADEON_RB3D_ZSTENCILCNTL:
340
		switch (idx_value & 0xf) {
341 342 343 344 345 346 347 348 349 350 351 352 353 354
		case 0:
			track->zb.cpp = 2;
			break;
		case 2:
		case 3:
		case 4:
		case 5:
		case 9:
		case 11:
			track->zb.cpp = 4;
			break;
		default:
			break;
		}
355
		track->zb_dirty = true;
356 357
		break;
	case RADEON_RB3D_ZPASS_ADDR:
358
		r = radeon_cs_packet_next_reloc(p, &reloc, 0);
359 360 361
		if (r) {
			DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
				  idx, reg);
362
			radeon_cs_dump_packet(p, pkt);
363 364
			return r;
		}
365
		ib[idx] = idx_value + ((u32)reloc->lobj.gpu_offset);
366 367 368
		break;
	case RADEON_PP_CNTL:
		{
369
			uint32_t temp = idx_value >> 4;
370 371
			for (i = 0; i < track->num_texture; i++)
				track->textures[i].enabled = !!(temp & (1 << i));
372
			track->tex_dirty = true;
373 374 375
		}
		break;
	case RADEON_SE_VF_CNTL:
376
		track->vap_vf_cntl = idx_value;
377 378 379
		break;
	case 0x210c:
		/* VAP_VF_MAX_VTX_INDX */
380
		track->max_indx = idx_value & 0x00FFFFFFUL;
381 382
		break;
	case R200_SE_VTX_FMT_0:
383
		track->vtx_size = r200_get_vtx_size_0(idx_value);
384 385
		break;
	case R200_SE_VTX_FMT_1:
386
		track->vtx_size += r200_get_vtx_size_1(idx_value);
387 388 389 390 391 392 393 394
		break;
	case R200_PP_TXSIZE_0:
	case R200_PP_TXSIZE_1:
	case R200_PP_TXSIZE_2:
	case R200_PP_TXSIZE_3:
	case R200_PP_TXSIZE_4:
	case R200_PP_TXSIZE_5:
		i = (reg - R200_PP_TXSIZE_0) / 32;
395 396
		track->textures[i].width = (idx_value & RADEON_TEX_USIZE_MASK) + 1;
		track->textures[i].height = ((idx_value & RADEON_TEX_VSIZE_MASK) >> RADEON_TEX_VSIZE_SHIFT) + 1;
397
		track->tex_dirty = true;
398 399 400 401 402 403 404 405
		break;
	case R200_PP_TXPITCH_0:
	case R200_PP_TXPITCH_1:
	case R200_PP_TXPITCH_2:
	case R200_PP_TXPITCH_3:
	case R200_PP_TXPITCH_4:
	case R200_PP_TXPITCH_5:
		i = (reg - R200_PP_TXPITCH_0) / 32;
406
		track->textures[i].pitch = idx_value + 32;
407
		track->tex_dirty = true;
408 409 410 411 412 413 414 415
		break;
	case R200_PP_TXFILTER_0:
	case R200_PP_TXFILTER_1:
	case R200_PP_TXFILTER_2:
	case R200_PP_TXFILTER_3:
	case R200_PP_TXFILTER_4:
	case R200_PP_TXFILTER_5:
		i = (reg - R200_PP_TXFILTER_0) / 32;
416
		track->textures[i].num_levels = ((idx_value & R200_MAX_MIP_LEVEL_MASK)
417
						 >> R200_MAX_MIP_LEVEL_SHIFT);
418
		tmp = (idx_value >> 23) & 0x7;
419 420
		if (tmp == 2 || tmp == 6)
			track->textures[i].roundup_w = false;
421
		tmp = (idx_value >> 27) & 0x7;
422 423
		if (tmp == 2 || tmp == 6)
			track->textures[i].roundup_h = false;
424
		track->tex_dirty = true;
425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440
		break;
	case R200_PP_TXMULTI_CTL_0:
	case R200_PP_TXMULTI_CTL_1:
	case R200_PP_TXMULTI_CTL_2:
	case R200_PP_TXMULTI_CTL_3:
	case R200_PP_TXMULTI_CTL_4:
	case R200_PP_TXMULTI_CTL_5:
		i = (reg - R200_PP_TXMULTI_CTL_0) / 32;
		break;
	case R200_PP_TXFORMAT_X_0:
	case R200_PP_TXFORMAT_X_1:
	case R200_PP_TXFORMAT_X_2:
	case R200_PP_TXFORMAT_X_3:
	case R200_PP_TXFORMAT_X_4:
	case R200_PP_TXFORMAT_X_5:
		i = (reg - R200_PP_TXFORMAT_X_0) / 32;
441 442
		track->textures[i].txdepth = idx_value & 0x7;
		tmp = (idx_value >> 16) & 0x3;
443 444 445
		/* 2D, 3D, CUBE */
		switch (tmp) {
		case 0:
446 447
		case 3:
		case 4:
448 449 450
		case 5:
		case 6:
		case 7:
451
			/* 1D/2D */
452 453 454
			track->textures[i].tex_coord_type = 0;
			break;
		case 1:
455 456
			/* CUBE */
			track->textures[i].tex_coord_type = 2;
457 458
			break;
		case 2:
459 460
			/* 3D */
			track->textures[i].tex_coord_type = 1;
461 462
			break;
		}
463
		track->tex_dirty = true;
464 465 466 467 468 469 470 471
		break;
	case R200_PP_TXFORMAT_0:
	case R200_PP_TXFORMAT_1:
	case R200_PP_TXFORMAT_2:
	case R200_PP_TXFORMAT_3:
	case R200_PP_TXFORMAT_4:
	case R200_PP_TXFORMAT_5:
		i = (reg - R200_PP_TXFORMAT_0) / 32;
472
		if (idx_value & R200_TXFORMAT_NON_POWER2) {
473 474 475
			track->textures[i].use_pitch = 1;
		} else {
			track->textures[i].use_pitch = 0;
476 477
			track->textures[i].width = 1 << ((idx_value >> RADEON_TXFORMAT_WIDTH_SHIFT) & RADEON_TXFORMAT_WIDTH_MASK);
			track->textures[i].height = 1 << ((idx_value >> RADEON_TXFORMAT_HEIGHT_SHIFT) & RADEON_TXFORMAT_HEIGHT_MASK);
478
		}
479 480
		if (idx_value & R200_TXFORMAT_LOOKUP_DISABLE)
			track->textures[i].lookup_disable = true;
481
		switch ((idx_value & RADEON_TXFORMAT_FORMAT_MASK)) {
482 483 484 485
		case R200_TXFORMAT_I8:
		case R200_TXFORMAT_RGB332:
		case R200_TXFORMAT_Y8:
			track->textures[i].cpp = 1;
486
			track->textures[i].compress_format = R100_TRACK_COMP_NONE;
487 488 489 490 491 492 493 494 495 496 497
			break;
		case R200_TXFORMAT_AI88:
		case R200_TXFORMAT_ARGB1555:
		case R200_TXFORMAT_RGB565:
		case R200_TXFORMAT_ARGB4444:
		case R200_TXFORMAT_VYUY422:
		case R200_TXFORMAT_YVYU422:
		case R200_TXFORMAT_LDVDU655:
		case R200_TXFORMAT_DVDU88:
		case R200_TXFORMAT_AVYU4444:
			track->textures[i].cpp = 2;
498
			track->textures[i].compress_format = R100_TRACK_COMP_NONE;
499 500 501 502 503 504
			break;
		case R200_TXFORMAT_ARGB8888:
		case R200_TXFORMAT_RGBA8888:
		case R200_TXFORMAT_ABGR8888:
		case R200_TXFORMAT_BGR111110:
		case R200_TXFORMAT_LDVDU8888:
505
			track->textures[i].cpp = 4;
506
			track->textures[i].compress_format = R100_TRACK_COMP_NONE;
507 508 509 510 511
			break;
		case R200_TXFORMAT_DXT1:
			track->textures[i].cpp = 1;
			track->textures[i].compress_format = R100_TRACK_COMP_DXT1;
			break;
512 513
		case R200_TXFORMAT_DXT23:
		case R200_TXFORMAT_DXT45:
514 515
			track->textures[i].cpp = 1;
			track->textures[i].compress_format = R100_TRACK_COMP_DXT1;
516 517
			break;
		}
518 519
		track->textures[i].cube_info[4].width = 1 << ((idx_value >> 16) & 0xf);
		track->textures[i].cube_info[4].height = 1 << ((idx_value >> 20) & 0xf);
520
		track->tex_dirty = true;
521 522 523 524 525 526 527
		break;
	case R200_PP_CUBIC_FACES_0:
	case R200_PP_CUBIC_FACES_1:
	case R200_PP_CUBIC_FACES_2:
	case R200_PP_CUBIC_FACES_3:
	case R200_PP_CUBIC_FACES_4:
	case R200_PP_CUBIC_FACES_5:
528
		tmp = idx_value;
529 530 531 532 533
		i = (reg - R200_PP_CUBIC_FACES_0) / 32;
		for (face = 0; face < 4; face++) {
			track->textures[i].cube_info[face].width = 1 << ((tmp >> (face * 8)) & 0xf);
			track->textures[i].cube_info[face].height = 1 << ((tmp >> ((face * 8) + 4)) & 0xf);
		}
534
		track->tex_dirty = true;
535 536 537 538 539 540 541 542 543
		break;
	default:
		printk(KERN_ERR "Forbidden register 0x%04X in cs at %d\n",
		       reg, idx);
		return -EINVAL;
	}
	return 0;
}

544
void r200_set_safe_registers(struct radeon_device *rdev)
545 546 547 548
{
	rdev->config.r100.reg_safe_bm = r200_reg_safe_bm;
	rdev->config.r100.reg_safe_bm_size = ARRAY_SIZE(r200_reg_safe_bm);
}