162306a36Sopenharmony_ci/*
262306a36Sopenharmony_ci * Copyright 2008 Advanced Micro Devices, Inc.
362306a36Sopenharmony_ci * Copyright 2008 Red Hat Inc.
462306a36Sopenharmony_ci * Copyright 2009 Jerome Glisse.
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
762306a36Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
862306a36Sopenharmony_ci * to deal in the Software without restriction, including without limitation
962306a36Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
1062306a36Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
1162306a36Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
1262306a36Sopenharmony_ci *
1362306a36Sopenharmony_ci * The above copyright notice and this permission notice shall be included in
1462306a36Sopenharmony_ci * all copies or substantial portions of the Software.
1562306a36Sopenharmony_ci *
1662306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1762306a36Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1862306a36Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
1962306a36Sopenharmony_ci * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
2062306a36Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
2162306a36Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
2262306a36Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE.
2362306a36Sopenharmony_ci *
2462306a36Sopenharmony_ci * Authors: Dave Airlie
2562306a36Sopenharmony_ci *          Alex Deucher
2662306a36Sopenharmony_ci *          Jerome Glisse
2762306a36Sopenharmony_ci */
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci#include <drm/radeon_drm.h>
3062306a36Sopenharmony_ci#include "radeon_reg.h"
3162306a36Sopenharmony_ci#include "radeon.h"
3262306a36Sopenharmony_ci#include "radeon_asic.h"
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci#include "r100d.h"
3562306a36Sopenharmony_ci#include "r200_reg_safe.h"
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci#include "r100_track.h"
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_cistatic int r200_get_vtx_size_0(uint32_t vtx_fmt_0)
4062306a36Sopenharmony_ci{
4162306a36Sopenharmony_ci	int vtx_size, i;
4262306a36Sopenharmony_ci	vtx_size = 2;
4362306a36Sopenharmony_ci
4462306a36Sopenharmony_ci	if (vtx_fmt_0 & R200_VTX_Z0)
4562306a36Sopenharmony_ci		vtx_size++;
4662306a36Sopenharmony_ci	if (vtx_fmt_0 & R200_VTX_W0)
4762306a36Sopenharmony_ci		vtx_size++;
4862306a36Sopenharmony_ci	/* blend weight */
4962306a36Sopenharmony_ci	if (vtx_fmt_0 & (0x7 << R200_VTX_WEIGHT_COUNT_SHIFT))
5062306a36Sopenharmony_ci		vtx_size += (vtx_fmt_0 >> R200_VTX_WEIGHT_COUNT_SHIFT) & 0x7;
5162306a36Sopenharmony_ci	if (vtx_fmt_0 & R200_VTX_PV_MATRIX_SEL)
5262306a36Sopenharmony_ci		vtx_size++;
5362306a36Sopenharmony_ci	if (vtx_fmt_0 & R200_VTX_N0)
5462306a36Sopenharmony_ci		vtx_size += 3;
5562306a36Sopenharmony_ci	if (vtx_fmt_0 & R200_VTX_POINT_SIZE)
5662306a36Sopenharmony_ci		vtx_size++;
5762306a36Sopenharmony_ci	if (vtx_fmt_0 & R200_VTX_DISCRETE_FOG)
5862306a36Sopenharmony_ci		vtx_size++;
5962306a36Sopenharmony_ci	if (vtx_fmt_0 & R200_VTX_SHININESS_0)
6062306a36Sopenharmony_ci		vtx_size++;
6162306a36Sopenharmony_ci	if (vtx_fmt_0 & R200_VTX_SHININESS_1)
6262306a36Sopenharmony_ci		vtx_size++;
6362306a36Sopenharmony_ci	for (i = 0; i < 8; i++) {
6462306a36Sopenharmony_ci		int color_size = (vtx_fmt_0 >> (11 + 2*i)) & 0x3;
6562306a36Sopenharmony_ci		switch (color_size) {
6662306a36Sopenharmony_ci		case 0: break;
6762306a36Sopenharmony_ci		case 1: vtx_size++; break;
6862306a36Sopenharmony_ci		case 2: vtx_size += 3; break;
6962306a36Sopenharmony_ci		case 3: vtx_size += 4; break;
7062306a36Sopenharmony_ci		}
7162306a36Sopenharmony_ci	}
7262306a36Sopenharmony_ci	if (vtx_fmt_0 & R200_VTX_XY1)
7362306a36Sopenharmony_ci		vtx_size += 2;
7462306a36Sopenharmony_ci	if (vtx_fmt_0 & R200_VTX_Z1)
7562306a36Sopenharmony_ci		vtx_size++;
7662306a36Sopenharmony_ci	if (vtx_fmt_0 & R200_VTX_W1)
7762306a36Sopenharmony_ci		vtx_size++;
7862306a36Sopenharmony_ci	if (vtx_fmt_0 & R200_VTX_N1)
7962306a36Sopenharmony_ci		vtx_size += 3;
8062306a36Sopenharmony_ci	return vtx_size;
8162306a36Sopenharmony_ci}
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_cistruct radeon_fence *r200_copy_dma(struct radeon_device *rdev,
8462306a36Sopenharmony_ci				   uint64_t src_offset,
8562306a36Sopenharmony_ci				   uint64_t dst_offset,
8662306a36Sopenharmony_ci				   unsigned num_gpu_pages,
8762306a36Sopenharmony_ci				   struct dma_resv *resv)
8862306a36Sopenharmony_ci{
8962306a36Sopenharmony_ci	struct radeon_ring *ring = &rdev->ring[RADEON_RING_TYPE_GFX_INDEX];
9062306a36Sopenharmony_ci	struct radeon_fence *fence;
9162306a36Sopenharmony_ci	uint32_t size;
9262306a36Sopenharmony_ci	uint32_t cur_size;
9362306a36Sopenharmony_ci	int i, num_loops;
9462306a36Sopenharmony_ci	int r = 0;
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci	/* radeon pitch is /64 */
9762306a36Sopenharmony_ci	size = num_gpu_pages << RADEON_GPU_PAGE_SHIFT;
9862306a36Sopenharmony_ci	num_loops = DIV_ROUND_UP(size, 0x1FFFFF);
9962306a36Sopenharmony_ci	r = radeon_ring_lock(rdev, ring, num_loops * 4 + 64);
10062306a36Sopenharmony_ci	if (r) {
10162306a36Sopenharmony_ci		DRM_ERROR("radeon: moving bo (%d).\n", r);
10262306a36Sopenharmony_ci		return ERR_PTR(r);
10362306a36Sopenharmony_ci	}
10462306a36Sopenharmony_ci	/* Must wait for 2D idle & clean before DMA or hangs might happen */
10562306a36Sopenharmony_ci	radeon_ring_write(ring, PACKET0(RADEON_WAIT_UNTIL, 0));
10662306a36Sopenharmony_ci	radeon_ring_write(ring, (1 << 16));
10762306a36Sopenharmony_ci	for (i = 0; i < num_loops; i++) {
10862306a36Sopenharmony_ci		cur_size = size;
10962306a36Sopenharmony_ci		if (cur_size > 0x1FFFFF) {
11062306a36Sopenharmony_ci			cur_size = 0x1FFFFF;
11162306a36Sopenharmony_ci		}
11262306a36Sopenharmony_ci		size -= cur_size;
11362306a36Sopenharmony_ci		radeon_ring_write(ring, PACKET0(0x720, 2));
11462306a36Sopenharmony_ci		radeon_ring_write(ring, src_offset);
11562306a36Sopenharmony_ci		radeon_ring_write(ring, dst_offset);
11662306a36Sopenharmony_ci		radeon_ring_write(ring, cur_size | (1 << 31) | (1 << 30));
11762306a36Sopenharmony_ci		src_offset += cur_size;
11862306a36Sopenharmony_ci		dst_offset += cur_size;
11962306a36Sopenharmony_ci	}
12062306a36Sopenharmony_ci	radeon_ring_write(ring, PACKET0(RADEON_WAIT_UNTIL, 0));
12162306a36Sopenharmony_ci	radeon_ring_write(ring, RADEON_WAIT_DMA_GUI_IDLE);
12262306a36Sopenharmony_ci	r = radeon_fence_emit(rdev, &fence, RADEON_RING_TYPE_GFX_INDEX);
12362306a36Sopenharmony_ci	if (r) {
12462306a36Sopenharmony_ci		radeon_ring_unlock_undo(rdev, ring);
12562306a36Sopenharmony_ci		return ERR_PTR(r);
12662306a36Sopenharmony_ci	}
12762306a36Sopenharmony_ci	radeon_ring_unlock_commit(rdev, ring, false);
12862306a36Sopenharmony_ci	return fence;
12962306a36Sopenharmony_ci}
13062306a36Sopenharmony_ci
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_cistatic int r200_get_vtx_size_1(uint32_t vtx_fmt_1)
13362306a36Sopenharmony_ci{
13462306a36Sopenharmony_ci	int vtx_size, i, tex_size;
13562306a36Sopenharmony_ci	vtx_size = 0;
13662306a36Sopenharmony_ci	for (i = 0; i < 6; i++) {
13762306a36Sopenharmony_ci		tex_size = (vtx_fmt_1 >> (i * 3)) & 0x7;
13862306a36Sopenharmony_ci		if (tex_size > 4)
13962306a36Sopenharmony_ci			continue;
14062306a36Sopenharmony_ci		vtx_size += tex_size;
14162306a36Sopenharmony_ci	}
14262306a36Sopenharmony_ci	return vtx_size;
14362306a36Sopenharmony_ci}
14462306a36Sopenharmony_ci
14562306a36Sopenharmony_ciint r200_packet0_check(struct radeon_cs_parser *p,
14662306a36Sopenharmony_ci		       struct radeon_cs_packet *pkt,
14762306a36Sopenharmony_ci		       unsigned idx, unsigned reg)
14862306a36Sopenharmony_ci{
14962306a36Sopenharmony_ci	struct radeon_bo_list *reloc;
15062306a36Sopenharmony_ci	struct r100_cs_track *track;
15162306a36Sopenharmony_ci	volatile uint32_t *ib;
15262306a36Sopenharmony_ci	uint32_t tmp;
15362306a36Sopenharmony_ci	int r;
15462306a36Sopenharmony_ci	int i;
15562306a36Sopenharmony_ci	int face;
15662306a36Sopenharmony_ci	u32 tile_flags = 0;
15762306a36Sopenharmony_ci	u32 idx_value;
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci	ib = p->ib.ptr;
16062306a36Sopenharmony_ci	track = (struct r100_cs_track *)p->track;
16162306a36Sopenharmony_ci	idx_value = radeon_get_ib_value(p, idx);
16262306a36Sopenharmony_ci	switch (reg) {
16362306a36Sopenharmony_ci	case RADEON_CRTC_GUI_TRIG_VLINE:
16462306a36Sopenharmony_ci		r = r100_cs_packet_parse_vline(p);
16562306a36Sopenharmony_ci		if (r) {
16662306a36Sopenharmony_ci			DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
16762306a36Sopenharmony_ci				  idx, reg);
16862306a36Sopenharmony_ci			radeon_cs_dump_packet(p, pkt);
16962306a36Sopenharmony_ci			return r;
17062306a36Sopenharmony_ci		}
17162306a36Sopenharmony_ci		break;
17262306a36Sopenharmony_ci		/* FIXME: only allow PACKET3 blit? easier to check for out of
17362306a36Sopenharmony_ci		 * range access */
17462306a36Sopenharmony_ci	case RADEON_DST_PITCH_OFFSET:
17562306a36Sopenharmony_ci	case RADEON_SRC_PITCH_OFFSET:
17662306a36Sopenharmony_ci		r = r100_reloc_pitch_offset(p, pkt, idx, reg);
17762306a36Sopenharmony_ci		if (r)
17862306a36Sopenharmony_ci			return r;
17962306a36Sopenharmony_ci		break;
18062306a36Sopenharmony_ci	case RADEON_RB3D_DEPTHOFFSET:
18162306a36Sopenharmony_ci		r = radeon_cs_packet_next_reloc(p, &reloc, 0);
18262306a36Sopenharmony_ci		if (r) {
18362306a36Sopenharmony_ci			DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
18462306a36Sopenharmony_ci				  idx, reg);
18562306a36Sopenharmony_ci			radeon_cs_dump_packet(p, pkt);
18662306a36Sopenharmony_ci			return r;
18762306a36Sopenharmony_ci		}
18862306a36Sopenharmony_ci		track->zb.robj = reloc->robj;
18962306a36Sopenharmony_ci		track->zb.offset = idx_value;
19062306a36Sopenharmony_ci		track->zb_dirty = true;
19162306a36Sopenharmony_ci		ib[idx] = idx_value + ((u32)reloc->gpu_offset);
19262306a36Sopenharmony_ci		break;
19362306a36Sopenharmony_ci	case RADEON_RB3D_COLOROFFSET:
19462306a36Sopenharmony_ci		r = radeon_cs_packet_next_reloc(p, &reloc, 0);
19562306a36Sopenharmony_ci		if (r) {
19662306a36Sopenharmony_ci			DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
19762306a36Sopenharmony_ci				  idx, reg);
19862306a36Sopenharmony_ci			radeon_cs_dump_packet(p, pkt);
19962306a36Sopenharmony_ci			return r;
20062306a36Sopenharmony_ci		}
20162306a36Sopenharmony_ci		track->cb[0].robj = reloc->robj;
20262306a36Sopenharmony_ci		track->cb[0].offset = idx_value;
20362306a36Sopenharmony_ci		track->cb_dirty = true;
20462306a36Sopenharmony_ci		ib[idx] = idx_value + ((u32)reloc->gpu_offset);
20562306a36Sopenharmony_ci		break;
20662306a36Sopenharmony_ci	case R200_PP_TXOFFSET_0:
20762306a36Sopenharmony_ci	case R200_PP_TXOFFSET_1:
20862306a36Sopenharmony_ci	case R200_PP_TXOFFSET_2:
20962306a36Sopenharmony_ci	case R200_PP_TXOFFSET_3:
21062306a36Sopenharmony_ci	case R200_PP_TXOFFSET_4:
21162306a36Sopenharmony_ci	case R200_PP_TXOFFSET_5:
21262306a36Sopenharmony_ci		i = (reg - R200_PP_TXOFFSET_0) / 24;
21362306a36Sopenharmony_ci		r = radeon_cs_packet_next_reloc(p, &reloc, 0);
21462306a36Sopenharmony_ci		if (r) {
21562306a36Sopenharmony_ci			DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
21662306a36Sopenharmony_ci				  idx, reg);
21762306a36Sopenharmony_ci			radeon_cs_dump_packet(p, pkt);
21862306a36Sopenharmony_ci			return r;
21962306a36Sopenharmony_ci		}
22062306a36Sopenharmony_ci		if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
22162306a36Sopenharmony_ci			if (reloc->tiling_flags & RADEON_TILING_MACRO)
22262306a36Sopenharmony_ci				tile_flags |= R200_TXO_MACRO_TILE;
22362306a36Sopenharmony_ci			if (reloc->tiling_flags & RADEON_TILING_MICRO)
22462306a36Sopenharmony_ci				tile_flags |= R200_TXO_MICRO_TILE;
22562306a36Sopenharmony_ci
22662306a36Sopenharmony_ci			tmp = idx_value & ~(0x7 << 2);
22762306a36Sopenharmony_ci			tmp |= tile_flags;
22862306a36Sopenharmony_ci			ib[idx] = tmp + ((u32)reloc->gpu_offset);
22962306a36Sopenharmony_ci		} else
23062306a36Sopenharmony_ci			ib[idx] = idx_value + ((u32)reloc->gpu_offset);
23162306a36Sopenharmony_ci		track->textures[i].robj = reloc->robj;
23262306a36Sopenharmony_ci		track->tex_dirty = true;
23362306a36Sopenharmony_ci		break;
23462306a36Sopenharmony_ci	case R200_PP_CUBIC_OFFSET_F1_0:
23562306a36Sopenharmony_ci	case R200_PP_CUBIC_OFFSET_F2_0:
23662306a36Sopenharmony_ci	case R200_PP_CUBIC_OFFSET_F3_0:
23762306a36Sopenharmony_ci	case R200_PP_CUBIC_OFFSET_F4_0:
23862306a36Sopenharmony_ci	case R200_PP_CUBIC_OFFSET_F5_0:
23962306a36Sopenharmony_ci	case R200_PP_CUBIC_OFFSET_F1_1:
24062306a36Sopenharmony_ci	case R200_PP_CUBIC_OFFSET_F2_1:
24162306a36Sopenharmony_ci	case R200_PP_CUBIC_OFFSET_F3_1:
24262306a36Sopenharmony_ci	case R200_PP_CUBIC_OFFSET_F4_1:
24362306a36Sopenharmony_ci	case R200_PP_CUBIC_OFFSET_F5_1:
24462306a36Sopenharmony_ci	case R200_PP_CUBIC_OFFSET_F1_2:
24562306a36Sopenharmony_ci	case R200_PP_CUBIC_OFFSET_F2_2:
24662306a36Sopenharmony_ci	case R200_PP_CUBIC_OFFSET_F3_2:
24762306a36Sopenharmony_ci	case R200_PP_CUBIC_OFFSET_F4_2:
24862306a36Sopenharmony_ci	case R200_PP_CUBIC_OFFSET_F5_2:
24962306a36Sopenharmony_ci	case R200_PP_CUBIC_OFFSET_F1_3:
25062306a36Sopenharmony_ci	case R200_PP_CUBIC_OFFSET_F2_3:
25162306a36Sopenharmony_ci	case R200_PP_CUBIC_OFFSET_F3_3:
25262306a36Sopenharmony_ci	case R200_PP_CUBIC_OFFSET_F4_3:
25362306a36Sopenharmony_ci	case R200_PP_CUBIC_OFFSET_F5_3:
25462306a36Sopenharmony_ci	case R200_PP_CUBIC_OFFSET_F1_4:
25562306a36Sopenharmony_ci	case R200_PP_CUBIC_OFFSET_F2_4:
25662306a36Sopenharmony_ci	case R200_PP_CUBIC_OFFSET_F3_4:
25762306a36Sopenharmony_ci	case R200_PP_CUBIC_OFFSET_F4_4:
25862306a36Sopenharmony_ci	case R200_PP_CUBIC_OFFSET_F5_4:
25962306a36Sopenharmony_ci	case R200_PP_CUBIC_OFFSET_F1_5:
26062306a36Sopenharmony_ci	case R200_PP_CUBIC_OFFSET_F2_5:
26162306a36Sopenharmony_ci	case R200_PP_CUBIC_OFFSET_F3_5:
26262306a36Sopenharmony_ci	case R200_PP_CUBIC_OFFSET_F4_5:
26362306a36Sopenharmony_ci	case R200_PP_CUBIC_OFFSET_F5_5:
26462306a36Sopenharmony_ci		i = (reg - R200_PP_TXOFFSET_0) / 24;
26562306a36Sopenharmony_ci		face = (reg - ((i * 24) + R200_PP_TXOFFSET_0)) / 4;
26662306a36Sopenharmony_ci		r = radeon_cs_packet_next_reloc(p, &reloc, 0);
26762306a36Sopenharmony_ci		if (r) {
26862306a36Sopenharmony_ci			DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
26962306a36Sopenharmony_ci				  idx, reg);
27062306a36Sopenharmony_ci			radeon_cs_dump_packet(p, pkt);
27162306a36Sopenharmony_ci			return r;
27262306a36Sopenharmony_ci		}
27362306a36Sopenharmony_ci		track->textures[i].cube_info[face - 1].offset = idx_value;
27462306a36Sopenharmony_ci		ib[idx] = idx_value + ((u32)reloc->gpu_offset);
27562306a36Sopenharmony_ci		track->textures[i].cube_info[face - 1].robj = reloc->robj;
27662306a36Sopenharmony_ci		track->tex_dirty = true;
27762306a36Sopenharmony_ci		break;
27862306a36Sopenharmony_ci	case RADEON_RE_WIDTH_HEIGHT:
27962306a36Sopenharmony_ci		track->maxy = ((idx_value >> 16) & 0x7FF);
28062306a36Sopenharmony_ci		track->cb_dirty = true;
28162306a36Sopenharmony_ci		track->zb_dirty = true;
28262306a36Sopenharmony_ci		break;
28362306a36Sopenharmony_ci	case RADEON_RB3D_COLORPITCH:
28462306a36Sopenharmony_ci		r = radeon_cs_packet_next_reloc(p, &reloc, 0);
28562306a36Sopenharmony_ci		if (r) {
28662306a36Sopenharmony_ci			DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
28762306a36Sopenharmony_ci				  idx, reg);
28862306a36Sopenharmony_ci			radeon_cs_dump_packet(p, pkt);
28962306a36Sopenharmony_ci			return r;
29062306a36Sopenharmony_ci		}
29162306a36Sopenharmony_ci
29262306a36Sopenharmony_ci		if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
29362306a36Sopenharmony_ci			if (reloc->tiling_flags & RADEON_TILING_MACRO)
29462306a36Sopenharmony_ci				tile_flags |= RADEON_COLOR_TILE_ENABLE;
29562306a36Sopenharmony_ci			if (reloc->tiling_flags & RADEON_TILING_MICRO)
29662306a36Sopenharmony_ci				tile_flags |= RADEON_COLOR_MICROTILE_ENABLE;
29762306a36Sopenharmony_ci
29862306a36Sopenharmony_ci			tmp = idx_value & ~(0x7 << 16);
29962306a36Sopenharmony_ci			tmp |= tile_flags;
30062306a36Sopenharmony_ci			ib[idx] = tmp;
30162306a36Sopenharmony_ci		} else
30262306a36Sopenharmony_ci			ib[idx] = idx_value;
30362306a36Sopenharmony_ci
30462306a36Sopenharmony_ci		track->cb[0].pitch = idx_value & RADEON_COLORPITCH_MASK;
30562306a36Sopenharmony_ci		track->cb_dirty = true;
30662306a36Sopenharmony_ci		break;
30762306a36Sopenharmony_ci	case RADEON_RB3D_DEPTHPITCH:
30862306a36Sopenharmony_ci		track->zb.pitch = idx_value & RADEON_DEPTHPITCH_MASK;
30962306a36Sopenharmony_ci		track->zb_dirty = true;
31062306a36Sopenharmony_ci		break;
31162306a36Sopenharmony_ci	case RADEON_RB3D_CNTL:
31262306a36Sopenharmony_ci		switch ((idx_value >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f) {
31362306a36Sopenharmony_ci		case 7:
31462306a36Sopenharmony_ci		case 8:
31562306a36Sopenharmony_ci		case 9:
31662306a36Sopenharmony_ci		case 11:
31762306a36Sopenharmony_ci		case 12:
31862306a36Sopenharmony_ci			track->cb[0].cpp = 1;
31962306a36Sopenharmony_ci			break;
32062306a36Sopenharmony_ci		case 3:
32162306a36Sopenharmony_ci		case 4:
32262306a36Sopenharmony_ci		case 15:
32362306a36Sopenharmony_ci			track->cb[0].cpp = 2;
32462306a36Sopenharmony_ci			break;
32562306a36Sopenharmony_ci		case 6:
32662306a36Sopenharmony_ci			track->cb[0].cpp = 4;
32762306a36Sopenharmony_ci			break;
32862306a36Sopenharmony_ci		default:
32962306a36Sopenharmony_ci			DRM_ERROR("Invalid color buffer format (%d) !\n",
33062306a36Sopenharmony_ci				  ((idx_value >> RADEON_RB3D_COLOR_FORMAT_SHIFT) & 0x1f));
33162306a36Sopenharmony_ci			return -EINVAL;
33262306a36Sopenharmony_ci		}
33362306a36Sopenharmony_ci		if (idx_value & RADEON_DEPTHXY_OFFSET_ENABLE) {
33462306a36Sopenharmony_ci			DRM_ERROR("No support for depth xy offset in kms\n");
33562306a36Sopenharmony_ci			return -EINVAL;
33662306a36Sopenharmony_ci		}
33762306a36Sopenharmony_ci
33862306a36Sopenharmony_ci		track->z_enabled = !!(idx_value & RADEON_Z_ENABLE);
33962306a36Sopenharmony_ci		track->cb_dirty = true;
34062306a36Sopenharmony_ci		track->zb_dirty = true;
34162306a36Sopenharmony_ci		break;
34262306a36Sopenharmony_ci	case RADEON_RB3D_ZSTENCILCNTL:
34362306a36Sopenharmony_ci		switch (idx_value & 0xf) {
34462306a36Sopenharmony_ci		case 0:
34562306a36Sopenharmony_ci			track->zb.cpp = 2;
34662306a36Sopenharmony_ci			break;
34762306a36Sopenharmony_ci		case 2:
34862306a36Sopenharmony_ci		case 3:
34962306a36Sopenharmony_ci		case 4:
35062306a36Sopenharmony_ci		case 5:
35162306a36Sopenharmony_ci		case 9:
35262306a36Sopenharmony_ci		case 11:
35362306a36Sopenharmony_ci			track->zb.cpp = 4;
35462306a36Sopenharmony_ci			break;
35562306a36Sopenharmony_ci		default:
35662306a36Sopenharmony_ci			break;
35762306a36Sopenharmony_ci		}
35862306a36Sopenharmony_ci		track->zb_dirty = true;
35962306a36Sopenharmony_ci		break;
36062306a36Sopenharmony_ci	case RADEON_RB3D_ZPASS_ADDR:
36162306a36Sopenharmony_ci		r = radeon_cs_packet_next_reloc(p, &reloc, 0);
36262306a36Sopenharmony_ci		if (r) {
36362306a36Sopenharmony_ci			DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
36462306a36Sopenharmony_ci				  idx, reg);
36562306a36Sopenharmony_ci			radeon_cs_dump_packet(p, pkt);
36662306a36Sopenharmony_ci			return r;
36762306a36Sopenharmony_ci		}
36862306a36Sopenharmony_ci		ib[idx] = idx_value + ((u32)reloc->gpu_offset);
36962306a36Sopenharmony_ci		break;
37062306a36Sopenharmony_ci	case RADEON_PP_CNTL:
37162306a36Sopenharmony_ci		{
37262306a36Sopenharmony_ci			uint32_t temp = idx_value >> 4;
37362306a36Sopenharmony_ci			for (i = 0; i < track->num_texture; i++)
37462306a36Sopenharmony_ci				track->textures[i].enabled = !!(temp & (1 << i));
37562306a36Sopenharmony_ci			track->tex_dirty = true;
37662306a36Sopenharmony_ci		}
37762306a36Sopenharmony_ci		break;
37862306a36Sopenharmony_ci	case RADEON_SE_VF_CNTL:
37962306a36Sopenharmony_ci		track->vap_vf_cntl = idx_value;
38062306a36Sopenharmony_ci		break;
38162306a36Sopenharmony_ci	case 0x210c:
38262306a36Sopenharmony_ci		/* VAP_VF_MAX_VTX_INDX */
38362306a36Sopenharmony_ci		track->max_indx = idx_value & 0x00FFFFFFUL;
38462306a36Sopenharmony_ci		break;
38562306a36Sopenharmony_ci	case R200_SE_VTX_FMT_0:
38662306a36Sopenharmony_ci		track->vtx_size = r200_get_vtx_size_0(idx_value);
38762306a36Sopenharmony_ci		break;
38862306a36Sopenharmony_ci	case R200_SE_VTX_FMT_1:
38962306a36Sopenharmony_ci		track->vtx_size += r200_get_vtx_size_1(idx_value);
39062306a36Sopenharmony_ci		break;
39162306a36Sopenharmony_ci	case R200_PP_TXSIZE_0:
39262306a36Sopenharmony_ci	case R200_PP_TXSIZE_1:
39362306a36Sopenharmony_ci	case R200_PP_TXSIZE_2:
39462306a36Sopenharmony_ci	case R200_PP_TXSIZE_3:
39562306a36Sopenharmony_ci	case R200_PP_TXSIZE_4:
39662306a36Sopenharmony_ci	case R200_PP_TXSIZE_5:
39762306a36Sopenharmony_ci		i = (reg - R200_PP_TXSIZE_0) / 32;
39862306a36Sopenharmony_ci		track->textures[i].width = (idx_value & RADEON_TEX_USIZE_MASK) + 1;
39962306a36Sopenharmony_ci		track->textures[i].height = ((idx_value & RADEON_TEX_VSIZE_MASK) >> RADEON_TEX_VSIZE_SHIFT) + 1;
40062306a36Sopenharmony_ci		track->tex_dirty = true;
40162306a36Sopenharmony_ci		break;
40262306a36Sopenharmony_ci	case R200_PP_TXPITCH_0:
40362306a36Sopenharmony_ci	case R200_PP_TXPITCH_1:
40462306a36Sopenharmony_ci	case R200_PP_TXPITCH_2:
40562306a36Sopenharmony_ci	case R200_PP_TXPITCH_3:
40662306a36Sopenharmony_ci	case R200_PP_TXPITCH_4:
40762306a36Sopenharmony_ci	case R200_PP_TXPITCH_5:
40862306a36Sopenharmony_ci		i = (reg - R200_PP_TXPITCH_0) / 32;
40962306a36Sopenharmony_ci		track->textures[i].pitch = idx_value + 32;
41062306a36Sopenharmony_ci		track->tex_dirty = true;
41162306a36Sopenharmony_ci		break;
41262306a36Sopenharmony_ci	case R200_PP_TXFILTER_0:
41362306a36Sopenharmony_ci	case R200_PP_TXFILTER_1:
41462306a36Sopenharmony_ci	case R200_PP_TXFILTER_2:
41562306a36Sopenharmony_ci	case R200_PP_TXFILTER_3:
41662306a36Sopenharmony_ci	case R200_PP_TXFILTER_4:
41762306a36Sopenharmony_ci	case R200_PP_TXFILTER_5:
41862306a36Sopenharmony_ci		i = (reg - R200_PP_TXFILTER_0) / 32;
41962306a36Sopenharmony_ci		track->textures[i].num_levels = ((idx_value & R200_MAX_MIP_LEVEL_MASK)
42062306a36Sopenharmony_ci						 >> R200_MAX_MIP_LEVEL_SHIFT);
42162306a36Sopenharmony_ci		tmp = (idx_value >> 23) & 0x7;
42262306a36Sopenharmony_ci		if (tmp == 2 || tmp == 6)
42362306a36Sopenharmony_ci			track->textures[i].roundup_w = false;
42462306a36Sopenharmony_ci		tmp = (idx_value >> 27) & 0x7;
42562306a36Sopenharmony_ci		if (tmp == 2 || tmp == 6)
42662306a36Sopenharmony_ci			track->textures[i].roundup_h = false;
42762306a36Sopenharmony_ci		track->tex_dirty = true;
42862306a36Sopenharmony_ci		break;
42962306a36Sopenharmony_ci	case R200_PP_TXMULTI_CTL_0:
43062306a36Sopenharmony_ci	case R200_PP_TXMULTI_CTL_1:
43162306a36Sopenharmony_ci	case R200_PP_TXMULTI_CTL_2:
43262306a36Sopenharmony_ci	case R200_PP_TXMULTI_CTL_3:
43362306a36Sopenharmony_ci	case R200_PP_TXMULTI_CTL_4:
43462306a36Sopenharmony_ci	case R200_PP_TXMULTI_CTL_5:
43562306a36Sopenharmony_ci		i = (reg - R200_PP_TXMULTI_CTL_0) / 32;
43662306a36Sopenharmony_ci		break;
43762306a36Sopenharmony_ci	case R200_PP_TXFORMAT_X_0:
43862306a36Sopenharmony_ci	case R200_PP_TXFORMAT_X_1:
43962306a36Sopenharmony_ci	case R200_PP_TXFORMAT_X_2:
44062306a36Sopenharmony_ci	case R200_PP_TXFORMAT_X_3:
44162306a36Sopenharmony_ci	case R200_PP_TXFORMAT_X_4:
44262306a36Sopenharmony_ci	case R200_PP_TXFORMAT_X_5:
44362306a36Sopenharmony_ci		i = (reg - R200_PP_TXFORMAT_X_0) / 32;
44462306a36Sopenharmony_ci		track->textures[i].txdepth = idx_value & 0x7;
44562306a36Sopenharmony_ci		tmp = (idx_value >> 16) & 0x3;
44662306a36Sopenharmony_ci		/* 2D, 3D, CUBE */
44762306a36Sopenharmony_ci		switch (tmp) {
44862306a36Sopenharmony_ci		case 0:
44962306a36Sopenharmony_ci		case 3:
45062306a36Sopenharmony_ci		case 4:
45162306a36Sopenharmony_ci		case 5:
45262306a36Sopenharmony_ci		case 6:
45362306a36Sopenharmony_ci		case 7:
45462306a36Sopenharmony_ci			/* 1D/2D */
45562306a36Sopenharmony_ci			track->textures[i].tex_coord_type = 0;
45662306a36Sopenharmony_ci			break;
45762306a36Sopenharmony_ci		case 1:
45862306a36Sopenharmony_ci			/* CUBE */
45962306a36Sopenharmony_ci			track->textures[i].tex_coord_type = 2;
46062306a36Sopenharmony_ci			break;
46162306a36Sopenharmony_ci		case 2:
46262306a36Sopenharmony_ci			/* 3D */
46362306a36Sopenharmony_ci			track->textures[i].tex_coord_type = 1;
46462306a36Sopenharmony_ci			break;
46562306a36Sopenharmony_ci		}
46662306a36Sopenharmony_ci		track->tex_dirty = true;
46762306a36Sopenharmony_ci		break;
46862306a36Sopenharmony_ci	case R200_PP_TXFORMAT_0:
46962306a36Sopenharmony_ci	case R200_PP_TXFORMAT_1:
47062306a36Sopenharmony_ci	case R200_PP_TXFORMAT_2:
47162306a36Sopenharmony_ci	case R200_PP_TXFORMAT_3:
47262306a36Sopenharmony_ci	case R200_PP_TXFORMAT_4:
47362306a36Sopenharmony_ci	case R200_PP_TXFORMAT_5:
47462306a36Sopenharmony_ci		i = (reg - R200_PP_TXFORMAT_0) / 32;
47562306a36Sopenharmony_ci		if (idx_value & R200_TXFORMAT_NON_POWER2) {
47662306a36Sopenharmony_ci			track->textures[i].use_pitch = 1;
47762306a36Sopenharmony_ci		} else {
47862306a36Sopenharmony_ci			track->textures[i].use_pitch = 0;
47962306a36Sopenharmony_ci			track->textures[i].width = 1 << ((idx_value & RADEON_TXFORMAT_WIDTH_MASK) >> RADEON_TXFORMAT_WIDTH_SHIFT);
48062306a36Sopenharmony_ci			track->textures[i].height = 1 << ((idx_value & RADEON_TXFORMAT_HEIGHT_MASK) >> RADEON_TXFORMAT_HEIGHT_SHIFT);
48162306a36Sopenharmony_ci		}
48262306a36Sopenharmony_ci		if (idx_value & R200_TXFORMAT_LOOKUP_DISABLE)
48362306a36Sopenharmony_ci			track->textures[i].lookup_disable = true;
48462306a36Sopenharmony_ci		switch ((idx_value & RADEON_TXFORMAT_FORMAT_MASK)) {
48562306a36Sopenharmony_ci		case R200_TXFORMAT_I8:
48662306a36Sopenharmony_ci		case R200_TXFORMAT_RGB332:
48762306a36Sopenharmony_ci		case R200_TXFORMAT_Y8:
48862306a36Sopenharmony_ci			track->textures[i].cpp = 1;
48962306a36Sopenharmony_ci			track->textures[i].compress_format = R100_TRACK_COMP_NONE;
49062306a36Sopenharmony_ci			break;
49162306a36Sopenharmony_ci		case R200_TXFORMAT_AI88:
49262306a36Sopenharmony_ci		case R200_TXFORMAT_ARGB1555:
49362306a36Sopenharmony_ci		case R200_TXFORMAT_RGB565:
49462306a36Sopenharmony_ci		case R200_TXFORMAT_ARGB4444:
49562306a36Sopenharmony_ci		case R200_TXFORMAT_VYUY422:
49662306a36Sopenharmony_ci		case R200_TXFORMAT_YVYU422:
49762306a36Sopenharmony_ci		case R200_TXFORMAT_LDVDU655:
49862306a36Sopenharmony_ci		case R200_TXFORMAT_DVDU88:
49962306a36Sopenharmony_ci		case R200_TXFORMAT_AVYU4444:
50062306a36Sopenharmony_ci			track->textures[i].cpp = 2;
50162306a36Sopenharmony_ci			track->textures[i].compress_format = R100_TRACK_COMP_NONE;
50262306a36Sopenharmony_ci			break;
50362306a36Sopenharmony_ci		case R200_TXFORMAT_ARGB8888:
50462306a36Sopenharmony_ci		case R200_TXFORMAT_RGBA8888:
50562306a36Sopenharmony_ci		case R200_TXFORMAT_ABGR8888:
50662306a36Sopenharmony_ci		case R200_TXFORMAT_BGR111110:
50762306a36Sopenharmony_ci		case R200_TXFORMAT_LDVDU8888:
50862306a36Sopenharmony_ci			track->textures[i].cpp = 4;
50962306a36Sopenharmony_ci			track->textures[i].compress_format = R100_TRACK_COMP_NONE;
51062306a36Sopenharmony_ci			break;
51162306a36Sopenharmony_ci		case R200_TXFORMAT_DXT1:
51262306a36Sopenharmony_ci			track->textures[i].cpp = 1;
51362306a36Sopenharmony_ci			track->textures[i].compress_format = R100_TRACK_COMP_DXT1;
51462306a36Sopenharmony_ci			break;
51562306a36Sopenharmony_ci		case R200_TXFORMAT_DXT23:
51662306a36Sopenharmony_ci		case R200_TXFORMAT_DXT45:
51762306a36Sopenharmony_ci			track->textures[i].cpp = 1;
51862306a36Sopenharmony_ci			track->textures[i].compress_format = R100_TRACK_COMP_DXT1;
51962306a36Sopenharmony_ci			break;
52062306a36Sopenharmony_ci		}
52162306a36Sopenharmony_ci		track->textures[i].cube_info[4].width = 1 << ((idx_value >> 16) & 0xf);
52262306a36Sopenharmony_ci		track->textures[i].cube_info[4].height = 1 << ((idx_value >> 20) & 0xf);
52362306a36Sopenharmony_ci		track->tex_dirty = true;
52462306a36Sopenharmony_ci		break;
52562306a36Sopenharmony_ci	case R200_PP_CUBIC_FACES_0:
52662306a36Sopenharmony_ci	case R200_PP_CUBIC_FACES_1:
52762306a36Sopenharmony_ci	case R200_PP_CUBIC_FACES_2:
52862306a36Sopenharmony_ci	case R200_PP_CUBIC_FACES_3:
52962306a36Sopenharmony_ci	case R200_PP_CUBIC_FACES_4:
53062306a36Sopenharmony_ci	case R200_PP_CUBIC_FACES_5:
53162306a36Sopenharmony_ci		tmp = idx_value;
53262306a36Sopenharmony_ci		i = (reg - R200_PP_CUBIC_FACES_0) / 32;
53362306a36Sopenharmony_ci		for (face = 0; face < 4; face++) {
53462306a36Sopenharmony_ci			track->textures[i].cube_info[face].width = 1 << ((tmp >> (face * 8)) & 0xf);
53562306a36Sopenharmony_ci			track->textures[i].cube_info[face].height = 1 << ((tmp >> ((face * 8) + 4)) & 0xf);
53662306a36Sopenharmony_ci		}
53762306a36Sopenharmony_ci		track->tex_dirty = true;
53862306a36Sopenharmony_ci		break;
53962306a36Sopenharmony_ci	default:
54062306a36Sopenharmony_ci		pr_err("Forbidden register 0x%04X in cs at %d\n", reg, idx);
54162306a36Sopenharmony_ci		return -EINVAL;
54262306a36Sopenharmony_ci	}
54362306a36Sopenharmony_ci	return 0;
54462306a36Sopenharmony_ci}
54562306a36Sopenharmony_ci
54662306a36Sopenharmony_civoid r200_set_safe_registers(struct radeon_device *rdev)
54762306a36Sopenharmony_ci{
54862306a36Sopenharmony_ci	rdev->config.r100.reg_safe_bm = r200_reg_safe_bm;
54962306a36Sopenharmony_ci	rdev->config.r100.reg_safe_bm_size = ARRAY_SIZE(r200_reg_safe_bm);
55062306a36Sopenharmony_ci}
551