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#include <linux/kernel.h>
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci#include "radeon.h"
3162306a36Sopenharmony_ci#include "radeon_asic.h"
3262306a36Sopenharmony_ci#include "r600.h"
3362306a36Sopenharmony_ci#include "r600d.h"
3462306a36Sopenharmony_ci#include "r600_reg_safe.h"
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_cistatic int r600_nomm;
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_cistruct r600_cs_track {
3962306a36Sopenharmony_ci	/* configuration we mirror so that we use same code btw kms/ums */
4062306a36Sopenharmony_ci	u32			group_size;
4162306a36Sopenharmony_ci	u32			nbanks;
4262306a36Sopenharmony_ci	u32			npipes;
4362306a36Sopenharmony_ci	/* value we track */
4462306a36Sopenharmony_ci	u32			sq_config;
4562306a36Sopenharmony_ci	u32			log_nsamples;
4662306a36Sopenharmony_ci	u32			nsamples;
4762306a36Sopenharmony_ci	u32			cb_color_base_last[8];
4862306a36Sopenharmony_ci	struct radeon_bo	*cb_color_bo[8];
4962306a36Sopenharmony_ci	u64			cb_color_bo_mc[8];
5062306a36Sopenharmony_ci	u64			cb_color_bo_offset[8];
5162306a36Sopenharmony_ci	struct radeon_bo	*cb_color_frag_bo[8];
5262306a36Sopenharmony_ci	u64			cb_color_frag_offset[8];
5362306a36Sopenharmony_ci	struct radeon_bo	*cb_color_tile_bo[8];
5462306a36Sopenharmony_ci	u64			cb_color_tile_offset[8];
5562306a36Sopenharmony_ci	u32			cb_color_mask[8];
5662306a36Sopenharmony_ci	u32			cb_color_info[8];
5762306a36Sopenharmony_ci	u32			cb_color_view[8];
5862306a36Sopenharmony_ci	u32			cb_color_size_idx[8]; /* unused */
5962306a36Sopenharmony_ci	u32			cb_target_mask;
6062306a36Sopenharmony_ci	u32			cb_shader_mask;  /* unused */
6162306a36Sopenharmony_ci	bool			is_resolve;
6262306a36Sopenharmony_ci	u32			cb_color_size[8];
6362306a36Sopenharmony_ci	u32			vgt_strmout_en;
6462306a36Sopenharmony_ci	u32			vgt_strmout_buffer_en;
6562306a36Sopenharmony_ci	struct radeon_bo	*vgt_strmout_bo[4];
6662306a36Sopenharmony_ci	u64			vgt_strmout_bo_mc[4]; /* unused */
6762306a36Sopenharmony_ci	u32			vgt_strmout_bo_offset[4];
6862306a36Sopenharmony_ci	u32			vgt_strmout_size[4];
6962306a36Sopenharmony_ci	u32			db_depth_control;
7062306a36Sopenharmony_ci	u32			db_depth_info;
7162306a36Sopenharmony_ci	u32			db_depth_size_idx;
7262306a36Sopenharmony_ci	u32			db_depth_view;
7362306a36Sopenharmony_ci	u32			db_depth_size;
7462306a36Sopenharmony_ci	u32			db_offset;
7562306a36Sopenharmony_ci	struct radeon_bo	*db_bo;
7662306a36Sopenharmony_ci	u64			db_bo_mc;
7762306a36Sopenharmony_ci	bool			sx_misc_kill_all_prims;
7862306a36Sopenharmony_ci	bool			cb_dirty;
7962306a36Sopenharmony_ci	bool			db_dirty;
8062306a36Sopenharmony_ci	bool			streamout_dirty;
8162306a36Sopenharmony_ci	struct radeon_bo	*htile_bo;
8262306a36Sopenharmony_ci	u64			htile_offset;
8362306a36Sopenharmony_ci	u32			htile_surface;
8462306a36Sopenharmony_ci};
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_ci#define FMT_8_BIT(fmt, vc)   [fmt] = { 1, 1, 1, vc, CHIP_R600 }
8762306a36Sopenharmony_ci#define FMT_16_BIT(fmt, vc)  [fmt] = { 1, 1, 2, vc, CHIP_R600 }
8862306a36Sopenharmony_ci#define FMT_24_BIT(fmt)      [fmt] = { 1, 1, 4,  0, CHIP_R600 }
8962306a36Sopenharmony_ci#define FMT_32_BIT(fmt, vc)  [fmt] = { 1, 1, 4, vc, CHIP_R600 }
9062306a36Sopenharmony_ci#define FMT_48_BIT(fmt)      [fmt] = { 1, 1, 8,  0, CHIP_R600 }
9162306a36Sopenharmony_ci#define FMT_64_BIT(fmt, vc)  [fmt] = { 1, 1, 8, vc, CHIP_R600 }
9262306a36Sopenharmony_ci#define FMT_96_BIT(fmt)      [fmt] = { 1, 1, 12, 0, CHIP_R600 }
9362306a36Sopenharmony_ci#define FMT_128_BIT(fmt, vc) [fmt] = { 1, 1, 16,vc, CHIP_R600 }
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_cistruct gpu_formats {
9662306a36Sopenharmony_ci	unsigned blockwidth;
9762306a36Sopenharmony_ci	unsigned blockheight;
9862306a36Sopenharmony_ci	unsigned blocksize;
9962306a36Sopenharmony_ci	unsigned valid_color;
10062306a36Sopenharmony_ci	enum radeon_family min_family;
10162306a36Sopenharmony_ci};
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_cistatic const struct gpu_formats color_formats_table[] = {
10462306a36Sopenharmony_ci	/* 8 bit */
10562306a36Sopenharmony_ci	FMT_8_BIT(V_038004_COLOR_8, 1),
10662306a36Sopenharmony_ci	FMT_8_BIT(V_038004_COLOR_4_4, 1),
10762306a36Sopenharmony_ci	FMT_8_BIT(V_038004_COLOR_3_3_2, 1),
10862306a36Sopenharmony_ci	FMT_8_BIT(V_038004_FMT_1, 0),
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_ci	/* 16-bit */
11162306a36Sopenharmony_ci	FMT_16_BIT(V_038004_COLOR_16, 1),
11262306a36Sopenharmony_ci	FMT_16_BIT(V_038004_COLOR_16_FLOAT, 1),
11362306a36Sopenharmony_ci	FMT_16_BIT(V_038004_COLOR_8_8, 1),
11462306a36Sopenharmony_ci	FMT_16_BIT(V_038004_COLOR_5_6_5, 1),
11562306a36Sopenharmony_ci	FMT_16_BIT(V_038004_COLOR_6_5_5, 1),
11662306a36Sopenharmony_ci	FMT_16_BIT(V_038004_COLOR_1_5_5_5, 1),
11762306a36Sopenharmony_ci	FMT_16_BIT(V_038004_COLOR_4_4_4_4, 1),
11862306a36Sopenharmony_ci	FMT_16_BIT(V_038004_COLOR_5_5_5_1, 1),
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_ci	/* 24-bit */
12162306a36Sopenharmony_ci	FMT_24_BIT(V_038004_FMT_8_8_8),
12262306a36Sopenharmony_ci
12362306a36Sopenharmony_ci	/* 32-bit */
12462306a36Sopenharmony_ci	FMT_32_BIT(V_038004_COLOR_32, 1),
12562306a36Sopenharmony_ci	FMT_32_BIT(V_038004_COLOR_32_FLOAT, 1),
12662306a36Sopenharmony_ci	FMT_32_BIT(V_038004_COLOR_16_16, 1),
12762306a36Sopenharmony_ci	FMT_32_BIT(V_038004_COLOR_16_16_FLOAT, 1),
12862306a36Sopenharmony_ci	FMT_32_BIT(V_038004_COLOR_8_24, 1),
12962306a36Sopenharmony_ci	FMT_32_BIT(V_038004_COLOR_8_24_FLOAT, 1),
13062306a36Sopenharmony_ci	FMT_32_BIT(V_038004_COLOR_24_8, 1),
13162306a36Sopenharmony_ci	FMT_32_BIT(V_038004_COLOR_24_8_FLOAT, 1),
13262306a36Sopenharmony_ci	FMT_32_BIT(V_038004_COLOR_10_11_11, 1),
13362306a36Sopenharmony_ci	FMT_32_BIT(V_038004_COLOR_10_11_11_FLOAT, 1),
13462306a36Sopenharmony_ci	FMT_32_BIT(V_038004_COLOR_11_11_10, 1),
13562306a36Sopenharmony_ci	FMT_32_BIT(V_038004_COLOR_11_11_10_FLOAT, 1),
13662306a36Sopenharmony_ci	FMT_32_BIT(V_038004_COLOR_2_10_10_10, 1),
13762306a36Sopenharmony_ci	FMT_32_BIT(V_038004_COLOR_8_8_8_8, 1),
13862306a36Sopenharmony_ci	FMT_32_BIT(V_038004_COLOR_10_10_10_2, 1),
13962306a36Sopenharmony_ci	FMT_32_BIT(V_038004_FMT_5_9_9_9_SHAREDEXP, 0),
14062306a36Sopenharmony_ci	FMT_32_BIT(V_038004_FMT_32_AS_8, 0),
14162306a36Sopenharmony_ci	FMT_32_BIT(V_038004_FMT_32_AS_8_8, 0),
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci	/* 48-bit */
14462306a36Sopenharmony_ci	FMT_48_BIT(V_038004_FMT_16_16_16),
14562306a36Sopenharmony_ci	FMT_48_BIT(V_038004_FMT_16_16_16_FLOAT),
14662306a36Sopenharmony_ci
14762306a36Sopenharmony_ci	/* 64-bit */
14862306a36Sopenharmony_ci	FMT_64_BIT(V_038004_COLOR_X24_8_32_FLOAT, 1),
14962306a36Sopenharmony_ci	FMT_64_BIT(V_038004_COLOR_32_32, 1),
15062306a36Sopenharmony_ci	FMT_64_BIT(V_038004_COLOR_32_32_FLOAT, 1),
15162306a36Sopenharmony_ci	FMT_64_BIT(V_038004_COLOR_16_16_16_16, 1),
15262306a36Sopenharmony_ci	FMT_64_BIT(V_038004_COLOR_16_16_16_16_FLOAT, 1),
15362306a36Sopenharmony_ci
15462306a36Sopenharmony_ci	FMT_96_BIT(V_038004_FMT_32_32_32),
15562306a36Sopenharmony_ci	FMT_96_BIT(V_038004_FMT_32_32_32_FLOAT),
15662306a36Sopenharmony_ci
15762306a36Sopenharmony_ci	/* 128-bit */
15862306a36Sopenharmony_ci	FMT_128_BIT(V_038004_COLOR_32_32_32_32, 1),
15962306a36Sopenharmony_ci	FMT_128_BIT(V_038004_COLOR_32_32_32_32_FLOAT, 1),
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci	[V_038004_FMT_GB_GR] = { 2, 1, 4, 0 },
16262306a36Sopenharmony_ci	[V_038004_FMT_BG_RG] = { 2, 1, 4, 0 },
16362306a36Sopenharmony_ci
16462306a36Sopenharmony_ci	/* block compressed formats */
16562306a36Sopenharmony_ci	[V_038004_FMT_BC1] = { 4, 4, 8, 0 },
16662306a36Sopenharmony_ci	[V_038004_FMT_BC2] = { 4, 4, 16, 0 },
16762306a36Sopenharmony_ci	[V_038004_FMT_BC3] = { 4, 4, 16, 0 },
16862306a36Sopenharmony_ci	[V_038004_FMT_BC4] = { 4, 4, 8, 0 },
16962306a36Sopenharmony_ci	[V_038004_FMT_BC5] = { 4, 4, 16, 0},
17062306a36Sopenharmony_ci	[V_038004_FMT_BC6] = { 4, 4, 16, 0, CHIP_CEDAR}, /* Evergreen-only */
17162306a36Sopenharmony_ci	[V_038004_FMT_BC7] = { 4, 4, 16, 0, CHIP_CEDAR}, /* Evergreen-only */
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_ci	/* The other Evergreen formats */
17462306a36Sopenharmony_ci	[V_038004_FMT_32_AS_32_32_32_32] = { 1, 1, 4, 0, CHIP_CEDAR},
17562306a36Sopenharmony_ci};
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_cibool r600_fmt_is_valid_color(u32 format)
17862306a36Sopenharmony_ci{
17962306a36Sopenharmony_ci	if (format >= ARRAY_SIZE(color_formats_table))
18062306a36Sopenharmony_ci		return false;
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_ci	if (color_formats_table[format].valid_color)
18362306a36Sopenharmony_ci		return true;
18462306a36Sopenharmony_ci
18562306a36Sopenharmony_ci	return false;
18662306a36Sopenharmony_ci}
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_cibool r600_fmt_is_valid_texture(u32 format, enum radeon_family family)
18962306a36Sopenharmony_ci{
19062306a36Sopenharmony_ci	if (format >= ARRAY_SIZE(color_formats_table))
19162306a36Sopenharmony_ci		return false;
19262306a36Sopenharmony_ci
19362306a36Sopenharmony_ci	if (family < color_formats_table[format].min_family)
19462306a36Sopenharmony_ci		return false;
19562306a36Sopenharmony_ci
19662306a36Sopenharmony_ci	if (color_formats_table[format].blockwidth > 0)
19762306a36Sopenharmony_ci		return true;
19862306a36Sopenharmony_ci
19962306a36Sopenharmony_ci	return false;
20062306a36Sopenharmony_ci}
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ciint r600_fmt_get_blocksize(u32 format)
20362306a36Sopenharmony_ci{
20462306a36Sopenharmony_ci	if (format >= ARRAY_SIZE(color_formats_table))
20562306a36Sopenharmony_ci		return 0;
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_ci	return color_formats_table[format].blocksize;
20862306a36Sopenharmony_ci}
20962306a36Sopenharmony_ci
21062306a36Sopenharmony_ciint r600_fmt_get_nblocksx(u32 format, u32 w)
21162306a36Sopenharmony_ci{
21262306a36Sopenharmony_ci	unsigned bw;
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ci	if (format >= ARRAY_SIZE(color_formats_table))
21562306a36Sopenharmony_ci		return 0;
21662306a36Sopenharmony_ci
21762306a36Sopenharmony_ci	bw = color_formats_table[format].blockwidth;
21862306a36Sopenharmony_ci	if (bw == 0)
21962306a36Sopenharmony_ci		return 0;
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci	return DIV_ROUND_UP(w, bw);
22262306a36Sopenharmony_ci}
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_ciint r600_fmt_get_nblocksy(u32 format, u32 h)
22562306a36Sopenharmony_ci{
22662306a36Sopenharmony_ci	unsigned bh;
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_ci	if (format >= ARRAY_SIZE(color_formats_table))
22962306a36Sopenharmony_ci		return 0;
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_ci	bh = color_formats_table[format].blockheight;
23262306a36Sopenharmony_ci	if (bh == 0)
23362306a36Sopenharmony_ci		return 0;
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_ci	return DIV_ROUND_UP(h, bh);
23662306a36Sopenharmony_ci}
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_cistruct array_mode_checker {
23962306a36Sopenharmony_ci	int array_mode;
24062306a36Sopenharmony_ci	u32 group_size;
24162306a36Sopenharmony_ci	u32 nbanks;
24262306a36Sopenharmony_ci	u32 npipes;
24362306a36Sopenharmony_ci	u32 nsamples;
24462306a36Sopenharmony_ci	u32 blocksize;
24562306a36Sopenharmony_ci};
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_ci/* returns alignment in pixels for pitch/height/depth and bytes for base */
24862306a36Sopenharmony_cistatic int r600_get_array_mode_alignment(struct array_mode_checker *values,
24962306a36Sopenharmony_ci						u32 *pitch_align,
25062306a36Sopenharmony_ci						u32 *height_align,
25162306a36Sopenharmony_ci						u32 *depth_align,
25262306a36Sopenharmony_ci						u64 *base_align)
25362306a36Sopenharmony_ci{
25462306a36Sopenharmony_ci	u32 tile_width = 8;
25562306a36Sopenharmony_ci	u32 tile_height = 8;
25662306a36Sopenharmony_ci	u32 macro_tile_width = values->nbanks;
25762306a36Sopenharmony_ci	u32 macro_tile_height = values->npipes;
25862306a36Sopenharmony_ci	u32 tile_bytes = tile_width * tile_height * values->blocksize * values->nsamples;
25962306a36Sopenharmony_ci	u32 macro_tile_bytes = macro_tile_width * macro_tile_height * tile_bytes;
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_ci	switch (values->array_mode) {
26262306a36Sopenharmony_ci	case ARRAY_LINEAR_GENERAL:
26362306a36Sopenharmony_ci		/* technically tile_width/_height for pitch/height */
26462306a36Sopenharmony_ci		*pitch_align = 1; /* tile_width */
26562306a36Sopenharmony_ci		*height_align = 1; /* tile_height */
26662306a36Sopenharmony_ci		*depth_align = 1;
26762306a36Sopenharmony_ci		*base_align = 1;
26862306a36Sopenharmony_ci		break;
26962306a36Sopenharmony_ci	case ARRAY_LINEAR_ALIGNED:
27062306a36Sopenharmony_ci		*pitch_align = max((u32)64, (u32)(values->group_size / values->blocksize));
27162306a36Sopenharmony_ci		*height_align = 1;
27262306a36Sopenharmony_ci		*depth_align = 1;
27362306a36Sopenharmony_ci		*base_align = values->group_size;
27462306a36Sopenharmony_ci		break;
27562306a36Sopenharmony_ci	case ARRAY_1D_TILED_THIN1:
27662306a36Sopenharmony_ci		*pitch_align = max((u32)tile_width,
27762306a36Sopenharmony_ci				   (u32)(values->group_size /
27862306a36Sopenharmony_ci					 (tile_height * values->blocksize * values->nsamples)));
27962306a36Sopenharmony_ci		*height_align = tile_height;
28062306a36Sopenharmony_ci		*depth_align = 1;
28162306a36Sopenharmony_ci		*base_align = values->group_size;
28262306a36Sopenharmony_ci		break;
28362306a36Sopenharmony_ci	case ARRAY_2D_TILED_THIN1:
28462306a36Sopenharmony_ci		*pitch_align = max((u32)macro_tile_width * tile_width,
28562306a36Sopenharmony_ci				(u32)((values->group_size * values->nbanks) /
28662306a36Sopenharmony_ci				(values->blocksize * values->nsamples * tile_width)));
28762306a36Sopenharmony_ci		*height_align = macro_tile_height * tile_height;
28862306a36Sopenharmony_ci		*depth_align = 1;
28962306a36Sopenharmony_ci		*base_align = max(macro_tile_bytes,
29062306a36Sopenharmony_ci				  (*pitch_align) * values->blocksize * (*height_align) * values->nsamples);
29162306a36Sopenharmony_ci		break;
29262306a36Sopenharmony_ci	default:
29362306a36Sopenharmony_ci		return -EINVAL;
29462306a36Sopenharmony_ci	}
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ci	return 0;
29762306a36Sopenharmony_ci}
29862306a36Sopenharmony_ci
29962306a36Sopenharmony_cistatic void r600_cs_track_init(struct r600_cs_track *track)
30062306a36Sopenharmony_ci{
30162306a36Sopenharmony_ci	int i;
30262306a36Sopenharmony_ci
30362306a36Sopenharmony_ci	/* assume DX9 mode */
30462306a36Sopenharmony_ci	track->sq_config = DX9_CONSTS;
30562306a36Sopenharmony_ci	for (i = 0; i < 8; i++) {
30662306a36Sopenharmony_ci		track->cb_color_base_last[i] = 0;
30762306a36Sopenharmony_ci		track->cb_color_size[i] = 0;
30862306a36Sopenharmony_ci		track->cb_color_size_idx[i] = 0;
30962306a36Sopenharmony_ci		track->cb_color_info[i] = 0;
31062306a36Sopenharmony_ci		track->cb_color_view[i] = 0xFFFFFFFF;
31162306a36Sopenharmony_ci		track->cb_color_bo[i] = NULL;
31262306a36Sopenharmony_ci		track->cb_color_bo_offset[i] = 0xFFFFFFFF;
31362306a36Sopenharmony_ci		track->cb_color_bo_mc[i] = 0xFFFFFFFF;
31462306a36Sopenharmony_ci		track->cb_color_frag_bo[i] = NULL;
31562306a36Sopenharmony_ci		track->cb_color_frag_offset[i] = 0xFFFFFFFF;
31662306a36Sopenharmony_ci		track->cb_color_tile_bo[i] = NULL;
31762306a36Sopenharmony_ci		track->cb_color_tile_offset[i] = 0xFFFFFFFF;
31862306a36Sopenharmony_ci		track->cb_color_mask[i] = 0xFFFFFFFF;
31962306a36Sopenharmony_ci	}
32062306a36Sopenharmony_ci	track->is_resolve = false;
32162306a36Sopenharmony_ci	track->nsamples = 16;
32262306a36Sopenharmony_ci	track->log_nsamples = 4;
32362306a36Sopenharmony_ci	track->cb_target_mask = 0xFFFFFFFF;
32462306a36Sopenharmony_ci	track->cb_shader_mask = 0xFFFFFFFF;
32562306a36Sopenharmony_ci	track->cb_dirty = true;
32662306a36Sopenharmony_ci	track->db_bo = NULL;
32762306a36Sopenharmony_ci	track->db_bo_mc = 0xFFFFFFFF;
32862306a36Sopenharmony_ci	/* assume the biggest format and that htile is enabled */
32962306a36Sopenharmony_ci	track->db_depth_info = 7 | (1 << 25);
33062306a36Sopenharmony_ci	track->db_depth_view = 0xFFFFC000;
33162306a36Sopenharmony_ci	track->db_depth_size = 0xFFFFFFFF;
33262306a36Sopenharmony_ci	track->db_depth_size_idx = 0;
33362306a36Sopenharmony_ci	track->db_depth_control = 0xFFFFFFFF;
33462306a36Sopenharmony_ci	track->db_dirty = true;
33562306a36Sopenharmony_ci	track->htile_bo = NULL;
33662306a36Sopenharmony_ci	track->htile_offset = 0xFFFFFFFF;
33762306a36Sopenharmony_ci	track->htile_surface = 0;
33862306a36Sopenharmony_ci
33962306a36Sopenharmony_ci	for (i = 0; i < 4; i++) {
34062306a36Sopenharmony_ci		track->vgt_strmout_size[i] = 0;
34162306a36Sopenharmony_ci		track->vgt_strmout_bo[i] = NULL;
34262306a36Sopenharmony_ci		track->vgt_strmout_bo_offset[i] = 0xFFFFFFFF;
34362306a36Sopenharmony_ci		track->vgt_strmout_bo_mc[i] = 0xFFFFFFFF;
34462306a36Sopenharmony_ci	}
34562306a36Sopenharmony_ci	track->streamout_dirty = true;
34662306a36Sopenharmony_ci	track->sx_misc_kill_all_prims = false;
34762306a36Sopenharmony_ci}
34862306a36Sopenharmony_ci
34962306a36Sopenharmony_cistatic int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
35062306a36Sopenharmony_ci{
35162306a36Sopenharmony_ci	struct r600_cs_track *track = p->track;
35262306a36Sopenharmony_ci	u32 slice_tile_max, tmp;
35362306a36Sopenharmony_ci	u32 height, height_align, pitch, pitch_align, depth_align;
35462306a36Sopenharmony_ci	u64 base_offset, base_align;
35562306a36Sopenharmony_ci	struct array_mode_checker array_check;
35662306a36Sopenharmony_ci	volatile u32 *ib = p->ib.ptr;
35762306a36Sopenharmony_ci	unsigned array_mode;
35862306a36Sopenharmony_ci	u32 format;
35962306a36Sopenharmony_ci	/* When resolve is used, the second colorbuffer has always 1 sample. */
36062306a36Sopenharmony_ci	unsigned nsamples = track->is_resolve && i == 1 ? 1 : track->nsamples;
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_ci	format = G_0280A0_FORMAT(track->cb_color_info[i]);
36362306a36Sopenharmony_ci	if (!r600_fmt_is_valid_color(format)) {
36462306a36Sopenharmony_ci		dev_warn(p->dev, "%s:%d cb invalid format %d for %d (0x%08X)\n",
36562306a36Sopenharmony_ci			 __func__, __LINE__, format,
36662306a36Sopenharmony_ci			i, track->cb_color_info[i]);
36762306a36Sopenharmony_ci		return -EINVAL;
36862306a36Sopenharmony_ci	}
36962306a36Sopenharmony_ci	/* pitch in pixels */
37062306a36Sopenharmony_ci	pitch = (G_028060_PITCH_TILE_MAX(track->cb_color_size[i]) + 1) * 8;
37162306a36Sopenharmony_ci	slice_tile_max = G_028060_SLICE_TILE_MAX(track->cb_color_size[i]) + 1;
37262306a36Sopenharmony_ci	slice_tile_max *= 64;
37362306a36Sopenharmony_ci	height = slice_tile_max / pitch;
37462306a36Sopenharmony_ci	if (height > 8192)
37562306a36Sopenharmony_ci		height = 8192;
37662306a36Sopenharmony_ci	array_mode = G_0280A0_ARRAY_MODE(track->cb_color_info[i]);
37762306a36Sopenharmony_ci
37862306a36Sopenharmony_ci	base_offset = track->cb_color_bo_mc[i] + track->cb_color_bo_offset[i];
37962306a36Sopenharmony_ci	array_check.array_mode = array_mode;
38062306a36Sopenharmony_ci	array_check.group_size = track->group_size;
38162306a36Sopenharmony_ci	array_check.nbanks = track->nbanks;
38262306a36Sopenharmony_ci	array_check.npipes = track->npipes;
38362306a36Sopenharmony_ci	array_check.nsamples = nsamples;
38462306a36Sopenharmony_ci	array_check.blocksize = r600_fmt_get_blocksize(format);
38562306a36Sopenharmony_ci	if (r600_get_array_mode_alignment(&array_check,
38662306a36Sopenharmony_ci					  &pitch_align, &height_align, &depth_align, &base_align)) {
38762306a36Sopenharmony_ci		dev_warn(p->dev, "%s invalid tiling %d for %d (0x%08X)\n", __func__,
38862306a36Sopenharmony_ci			 G_0280A0_ARRAY_MODE(track->cb_color_info[i]), i,
38962306a36Sopenharmony_ci			 track->cb_color_info[i]);
39062306a36Sopenharmony_ci		return -EINVAL;
39162306a36Sopenharmony_ci	}
39262306a36Sopenharmony_ci	switch (array_mode) {
39362306a36Sopenharmony_ci	case V_0280A0_ARRAY_LINEAR_GENERAL:
39462306a36Sopenharmony_ci		break;
39562306a36Sopenharmony_ci	case V_0280A0_ARRAY_LINEAR_ALIGNED:
39662306a36Sopenharmony_ci		break;
39762306a36Sopenharmony_ci	case V_0280A0_ARRAY_1D_TILED_THIN1:
39862306a36Sopenharmony_ci		/* avoid breaking userspace */
39962306a36Sopenharmony_ci		if (height > 7)
40062306a36Sopenharmony_ci			height &= ~0x7;
40162306a36Sopenharmony_ci		break;
40262306a36Sopenharmony_ci	case V_0280A0_ARRAY_2D_TILED_THIN1:
40362306a36Sopenharmony_ci		break;
40462306a36Sopenharmony_ci	default:
40562306a36Sopenharmony_ci		dev_warn(p->dev, "%s invalid tiling %d for %d (0x%08X)\n", __func__,
40662306a36Sopenharmony_ci			G_0280A0_ARRAY_MODE(track->cb_color_info[i]), i,
40762306a36Sopenharmony_ci			track->cb_color_info[i]);
40862306a36Sopenharmony_ci		return -EINVAL;
40962306a36Sopenharmony_ci	}
41062306a36Sopenharmony_ci
41162306a36Sopenharmony_ci	if (!IS_ALIGNED(pitch, pitch_align)) {
41262306a36Sopenharmony_ci		dev_warn(p->dev, "%s:%d cb pitch (%d, 0x%x, %d) invalid\n",
41362306a36Sopenharmony_ci			 __func__, __LINE__, pitch, pitch_align, array_mode);
41462306a36Sopenharmony_ci		return -EINVAL;
41562306a36Sopenharmony_ci	}
41662306a36Sopenharmony_ci	if (!IS_ALIGNED(height, height_align)) {
41762306a36Sopenharmony_ci		dev_warn(p->dev, "%s:%d cb height (%d, 0x%x, %d) invalid\n",
41862306a36Sopenharmony_ci			 __func__, __LINE__, height, height_align, array_mode);
41962306a36Sopenharmony_ci		return -EINVAL;
42062306a36Sopenharmony_ci	}
42162306a36Sopenharmony_ci	if (!IS_ALIGNED(base_offset, base_align)) {
42262306a36Sopenharmony_ci		dev_warn(p->dev, "%s offset[%d] 0x%llx 0x%llx, %d not aligned\n", __func__, i,
42362306a36Sopenharmony_ci			 base_offset, base_align, array_mode);
42462306a36Sopenharmony_ci		return -EINVAL;
42562306a36Sopenharmony_ci	}
42662306a36Sopenharmony_ci
42762306a36Sopenharmony_ci	/* check offset */
42862306a36Sopenharmony_ci	tmp = r600_fmt_get_nblocksy(format, height) * r600_fmt_get_nblocksx(format, pitch) *
42962306a36Sopenharmony_ci	      r600_fmt_get_blocksize(format) * nsamples;
43062306a36Sopenharmony_ci	switch (array_mode) {
43162306a36Sopenharmony_ci	default:
43262306a36Sopenharmony_ci	case V_0280A0_ARRAY_LINEAR_GENERAL:
43362306a36Sopenharmony_ci	case V_0280A0_ARRAY_LINEAR_ALIGNED:
43462306a36Sopenharmony_ci		tmp += track->cb_color_view[i] & 0xFF;
43562306a36Sopenharmony_ci		break;
43662306a36Sopenharmony_ci	case V_0280A0_ARRAY_1D_TILED_THIN1:
43762306a36Sopenharmony_ci	case V_0280A0_ARRAY_2D_TILED_THIN1:
43862306a36Sopenharmony_ci		tmp += G_028080_SLICE_MAX(track->cb_color_view[i]) * tmp;
43962306a36Sopenharmony_ci		break;
44062306a36Sopenharmony_ci	}
44162306a36Sopenharmony_ci	if ((tmp + track->cb_color_bo_offset[i]) > radeon_bo_size(track->cb_color_bo[i])) {
44262306a36Sopenharmony_ci		if (array_mode == V_0280A0_ARRAY_LINEAR_GENERAL) {
44362306a36Sopenharmony_ci			/* the initial DDX does bad things with the CB size occasionally */
44462306a36Sopenharmony_ci			/* it rounds up height too far for slice tile max but the BO is smaller */
44562306a36Sopenharmony_ci			/* r600c,g also seem to flush at bad times in some apps resulting in
44662306a36Sopenharmony_ci			 * bogus values here. So for linear just allow anything to avoid breaking
44762306a36Sopenharmony_ci			 * broken userspace.
44862306a36Sopenharmony_ci			 */
44962306a36Sopenharmony_ci		} else {
45062306a36Sopenharmony_ci			dev_warn(p->dev, "%s offset[%d] %d %llu %d %lu too big (%d %d) (%d %d %d)\n",
45162306a36Sopenharmony_ci				 __func__, i, array_mode,
45262306a36Sopenharmony_ci				 track->cb_color_bo_offset[i], tmp,
45362306a36Sopenharmony_ci				 radeon_bo_size(track->cb_color_bo[i]),
45462306a36Sopenharmony_ci				 pitch, height, r600_fmt_get_nblocksx(format, pitch),
45562306a36Sopenharmony_ci				 r600_fmt_get_nblocksy(format, height),
45662306a36Sopenharmony_ci				 r600_fmt_get_blocksize(format));
45762306a36Sopenharmony_ci			return -EINVAL;
45862306a36Sopenharmony_ci		}
45962306a36Sopenharmony_ci	}
46062306a36Sopenharmony_ci	/* limit max tile */
46162306a36Sopenharmony_ci	tmp = (height * pitch) >> 6;
46262306a36Sopenharmony_ci	if (tmp < slice_tile_max)
46362306a36Sopenharmony_ci		slice_tile_max = tmp;
46462306a36Sopenharmony_ci	tmp = S_028060_PITCH_TILE_MAX((pitch / 8) - 1) |
46562306a36Sopenharmony_ci		S_028060_SLICE_TILE_MAX(slice_tile_max - 1);
46662306a36Sopenharmony_ci	ib[track->cb_color_size_idx[i]] = tmp;
46762306a36Sopenharmony_ci
46862306a36Sopenharmony_ci	/* FMASK/CMASK */
46962306a36Sopenharmony_ci	switch (G_0280A0_TILE_MODE(track->cb_color_info[i])) {
47062306a36Sopenharmony_ci	case V_0280A0_TILE_DISABLE:
47162306a36Sopenharmony_ci		break;
47262306a36Sopenharmony_ci	case V_0280A0_FRAG_ENABLE:
47362306a36Sopenharmony_ci		if (track->nsamples > 1) {
47462306a36Sopenharmony_ci			uint32_t tile_max = G_028100_FMASK_TILE_MAX(track->cb_color_mask[i]);
47562306a36Sopenharmony_ci			/* the tile size is 8x8, but the size is in units of bits.
47662306a36Sopenharmony_ci			 * for bytes, do just * 8. */
47762306a36Sopenharmony_ci			uint32_t bytes = track->nsamples * track->log_nsamples * 8 * (tile_max + 1);
47862306a36Sopenharmony_ci
47962306a36Sopenharmony_ci			if (bytes + track->cb_color_frag_offset[i] >
48062306a36Sopenharmony_ci			    radeon_bo_size(track->cb_color_frag_bo[i])) {
48162306a36Sopenharmony_ci				dev_warn(p->dev, "%s FMASK_TILE_MAX too large "
48262306a36Sopenharmony_ci					 "(tile_max=%u, bytes=%u, offset=%llu, bo_size=%lu)\n",
48362306a36Sopenharmony_ci					 __func__, tile_max, bytes,
48462306a36Sopenharmony_ci					 track->cb_color_frag_offset[i],
48562306a36Sopenharmony_ci					 radeon_bo_size(track->cb_color_frag_bo[i]));
48662306a36Sopenharmony_ci				return -EINVAL;
48762306a36Sopenharmony_ci			}
48862306a36Sopenharmony_ci		}
48962306a36Sopenharmony_ci		fallthrough;
49062306a36Sopenharmony_ci	case V_0280A0_CLEAR_ENABLE:
49162306a36Sopenharmony_ci	{
49262306a36Sopenharmony_ci		uint32_t block_max = G_028100_CMASK_BLOCK_MAX(track->cb_color_mask[i]);
49362306a36Sopenharmony_ci		/* One block = 128x128 pixels, one 8x8 tile has 4 bits..
49462306a36Sopenharmony_ci		 * (128*128) / (8*8) / 2 = 128 bytes per block. */
49562306a36Sopenharmony_ci		uint32_t bytes = (block_max + 1) * 128;
49662306a36Sopenharmony_ci
49762306a36Sopenharmony_ci		if (bytes + track->cb_color_tile_offset[i] >
49862306a36Sopenharmony_ci		    radeon_bo_size(track->cb_color_tile_bo[i])) {
49962306a36Sopenharmony_ci			dev_warn(p->dev, "%s CMASK_BLOCK_MAX too large "
50062306a36Sopenharmony_ci				 "(block_max=%u, bytes=%u, offset=%llu, bo_size=%lu)\n",
50162306a36Sopenharmony_ci				 __func__, block_max, bytes,
50262306a36Sopenharmony_ci				 track->cb_color_tile_offset[i],
50362306a36Sopenharmony_ci				 radeon_bo_size(track->cb_color_tile_bo[i]));
50462306a36Sopenharmony_ci			return -EINVAL;
50562306a36Sopenharmony_ci		}
50662306a36Sopenharmony_ci		break;
50762306a36Sopenharmony_ci	}
50862306a36Sopenharmony_ci	default:
50962306a36Sopenharmony_ci		dev_warn(p->dev, "%s invalid tile mode\n", __func__);
51062306a36Sopenharmony_ci		return -EINVAL;
51162306a36Sopenharmony_ci	}
51262306a36Sopenharmony_ci	return 0;
51362306a36Sopenharmony_ci}
51462306a36Sopenharmony_ci
51562306a36Sopenharmony_cistatic int r600_cs_track_validate_db(struct radeon_cs_parser *p)
51662306a36Sopenharmony_ci{
51762306a36Sopenharmony_ci	struct r600_cs_track *track = p->track;
51862306a36Sopenharmony_ci	u32 nviews, bpe, ntiles, slice_tile_max, tmp;
51962306a36Sopenharmony_ci	u32 height_align, pitch_align, depth_align;
52062306a36Sopenharmony_ci	u32 pitch = 8192;
52162306a36Sopenharmony_ci	u32 height = 8192;
52262306a36Sopenharmony_ci	u64 base_offset, base_align;
52362306a36Sopenharmony_ci	struct array_mode_checker array_check;
52462306a36Sopenharmony_ci	int array_mode;
52562306a36Sopenharmony_ci	volatile u32 *ib = p->ib.ptr;
52662306a36Sopenharmony_ci
52762306a36Sopenharmony_ci
52862306a36Sopenharmony_ci	if (track->db_bo == NULL) {
52962306a36Sopenharmony_ci		dev_warn(p->dev, "z/stencil with no depth buffer\n");
53062306a36Sopenharmony_ci		return -EINVAL;
53162306a36Sopenharmony_ci	}
53262306a36Sopenharmony_ci	switch (G_028010_FORMAT(track->db_depth_info)) {
53362306a36Sopenharmony_ci	case V_028010_DEPTH_16:
53462306a36Sopenharmony_ci		bpe = 2;
53562306a36Sopenharmony_ci		break;
53662306a36Sopenharmony_ci	case V_028010_DEPTH_X8_24:
53762306a36Sopenharmony_ci	case V_028010_DEPTH_8_24:
53862306a36Sopenharmony_ci	case V_028010_DEPTH_X8_24_FLOAT:
53962306a36Sopenharmony_ci	case V_028010_DEPTH_8_24_FLOAT:
54062306a36Sopenharmony_ci	case V_028010_DEPTH_32_FLOAT:
54162306a36Sopenharmony_ci		bpe = 4;
54262306a36Sopenharmony_ci		break;
54362306a36Sopenharmony_ci	case V_028010_DEPTH_X24_8_32_FLOAT:
54462306a36Sopenharmony_ci		bpe = 8;
54562306a36Sopenharmony_ci		break;
54662306a36Sopenharmony_ci	default:
54762306a36Sopenharmony_ci		dev_warn(p->dev, "z/stencil with invalid format %d\n", G_028010_FORMAT(track->db_depth_info));
54862306a36Sopenharmony_ci		return -EINVAL;
54962306a36Sopenharmony_ci	}
55062306a36Sopenharmony_ci	if ((track->db_depth_size & 0xFFFFFC00) == 0xFFFFFC00) {
55162306a36Sopenharmony_ci		if (!track->db_depth_size_idx) {
55262306a36Sopenharmony_ci			dev_warn(p->dev, "z/stencil buffer size not set\n");
55362306a36Sopenharmony_ci			return -EINVAL;
55462306a36Sopenharmony_ci		}
55562306a36Sopenharmony_ci		tmp = radeon_bo_size(track->db_bo) - track->db_offset;
55662306a36Sopenharmony_ci		tmp = (tmp / bpe) >> 6;
55762306a36Sopenharmony_ci		if (!tmp) {
55862306a36Sopenharmony_ci			dev_warn(p->dev, "z/stencil buffer too small (0x%08X %d %d %ld)\n",
55962306a36Sopenharmony_ci					track->db_depth_size, bpe, track->db_offset,
56062306a36Sopenharmony_ci					radeon_bo_size(track->db_bo));
56162306a36Sopenharmony_ci			return -EINVAL;
56262306a36Sopenharmony_ci		}
56362306a36Sopenharmony_ci		ib[track->db_depth_size_idx] = S_028000_SLICE_TILE_MAX(tmp - 1) | (track->db_depth_size & 0x3FF);
56462306a36Sopenharmony_ci	} else {
56562306a36Sopenharmony_ci		/* pitch in pixels */
56662306a36Sopenharmony_ci		pitch = (G_028000_PITCH_TILE_MAX(track->db_depth_size) + 1) * 8;
56762306a36Sopenharmony_ci		slice_tile_max = G_028000_SLICE_TILE_MAX(track->db_depth_size) + 1;
56862306a36Sopenharmony_ci		slice_tile_max *= 64;
56962306a36Sopenharmony_ci		height = slice_tile_max / pitch;
57062306a36Sopenharmony_ci		if (height > 8192)
57162306a36Sopenharmony_ci			height = 8192;
57262306a36Sopenharmony_ci		base_offset = track->db_bo_mc + track->db_offset;
57362306a36Sopenharmony_ci		array_mode = G_028010_ARRAY_MODE(track->db_depth_info);
57462306a36Sopenharmony_ci		array_check.array_mode = array_mode;
57562306a36Sopenharmony_ci		array_check.group_size = track->group_size;
57662306a36Sopenharmony_ci		array_check.nbanks = track->nbanks;
57762306a36Sopenharmony_ci		array_check.npipes = track->npipes;
57862306a36Sopenharmony_ci		array_check.nsamples = track->nsamples;
57962306a36Sopenharmony_ci		array_check.blocksize = bpe;
58062306a36Sopenharmony_ci		if (r600_get_array_mode_alignment(&array_check,
58162306a36Sopenharmony_ci					&pitch_align, &height_align, &depth_align, &base_align)) {
58262306a36Sopenharmony_ci			dev_warn(p->dev, "%s invalid tiling %d (0x%08X)\n", __func__,
58362306a36Sopenharmony_ci					G_028010_ARRAY_MODE(track->db_depth_info),
58462306a36Sopenharmony_ci					track->db_depth_info);
58562306a36Sopenharmony_ci			return -EINVAL;
58662306a36Sopenharmony_ci		}
58762306a36Sopenharmony_ci		switch (array_mode) {
58862306a36Sopenharmony_ci		case V_028010_ARRAY_1D_TILED_THIN1:
58962306a36Sopenharmony_ci			/* don't break userspace */
59062306a36Sopenharmony_ci			height &= ~0x7;
59162306a36Sopenharmony_ci			break;
59262306a36Sopenharmony_ci		case V_028010_ARRAY_2D_TILED_THIN1:
59362306a36Sopenharmony_ci			break;
59462306a36Sopenharmony_ci		default:
59562306a36Sopenharmony_ci			dev_warn(p->dev, "%s invalid tiling %d (0x%08X)\n", __func__,
59662306a36Sopenharmony_ci					G_028010_ARRAY_MODE(track->db_depth_info),
59762306a36Sopenharmony_ci					track->db_depth_info);
59862306a36Sopenharmony_ci			return -EINVAL;
59962306a36Sopenharmony_ci		}
60062306a36Sopenharmony_ci
60162306a36Sopenharmony_ci		if (!IS_ALIGNED(pitch, pitch_align)) {
60262306a36Sopenharmony_ci			dev_warn(p->dev, "%s:%d db pitch (%d, 0x%x, %d) invalid\n",
60362306a36Sopenharmony_ci					__func__, __LINE__, pitch, pitch_align, array_mode);
60462306a36Sopenharmony_ci			return -EINVAL;
60562306a36Sopenharmony_ci		}
60662306a36Sopenharmony_ci		if (!IS_ALIGNED(height, height_align)) {
60762306a36Sopenharmony_ci			dev_warn(p->dev, "%s:%d db height (%d, 0x%x, %d) invalid\n",
60862306a36Sopenharmony_ci					__func__, __LINE__, height, height_align, array_mode);
60962306a36Sopenharmony_ci			return -EINVAL;
61062306a36Sopenharmony_ci		}
61162306a36Sopenharmony_ci		if (!IS_ALIGNED(base_offset, base_align)) {
61262306a36Sopenharmony_ci			dev_warn(p->dev, "%s offset 0x%llx, 0x%llx, %d not aligned\n", __func__,
61362306a36Sopenharmony_ci					base_offset, base_align, array_mode);
61462306a36Sopenharmony_ci			return -EINVAL;
61562306a36Sopenharmony_ci		}
61662306a36Sopenharmony_ci
61762306a36Sopenharmony_ci		ntiles = G_028000_SLICE_TILE_MAX(track->db_depth_size) + 1;
61862306a36Sopenharmony_ci		nviews = G_028004_SLICE_MAX(track->db_depth_view) + 1;
61962306a36Sopenharmony_ci		tmp = ntiles * bpe * 64 * nviews * track->nsamples;
62062306a36Sopenharmony_ci		if ((tmp + track->db_offset) > radeon_bo_size(track->db_bo)) {
62162306a36Sopenharmony_ci			dev_warn(p->dev, "z/stencil buffer (%d) too small (0x%08X %d %d %d -> %u have %lu)\n",
62262306a36Sopenharmony_ci					array_mode,
62362306a36Sopenharmony_ci					track->db_depth_size, ntiles, nviews, bpe, tmp + track->db_offset,
62462306a36Sopenharmony_ci					radeon_bo_size(track->db_bo));
62562306a36Sopenharmony_ci			return -EINVAL;
62662306a36Sopenharmony_ci		}
62762306a36Sopenharmony_ci	}
62862306a36Sopenharmony_ci
62962306a36Sopenharmony_ci	/* hyperz */
63062306a36Sopenharmony_ci	if (G_028010_TILE_SURFACE_ENABLE(track->db_depth_info)) {
63162306a36Sopenharmony_ci		unsigned long size;
63262306a36Sopenharmony_ci		unsigned nbx, nby;
63362306a36Sopenharmony_ci
63462306a36Sopenharmony_ci		if (track->htile_bo == NULL) {
63562306a36Sopenharmony_ci			dev_warn(p->dev, "%s:%d htile enabled without htile surface 0x%08x\n",
63662306a36Sopenharmony_ci				 __func__, __LINE__, track->db_depth_info);
63762306a36Sopenharmony_ci			return -EINVAL;
63862306a36Sopenharmony_ci		}
63962306a36Sopenharmony_ci		if ((track->db_depth_size & 0xFFFFFC00) == 0xFFFFFC00) {
64062306a36Sopenharmony_ci			dev_warn(p->dev, "%s:%d htile can't be enabled with bogus db_depth_size 0x%08x\n",
64162306a36Sopenharmony_ci				 __func__, __LINE__, track->db_depth_size);
64262306a36Sopenharmony_ci			return -EINVAL;
64362306a36Sopenharmony_ci		}
64462306a36Sopenharmony_ci
64562306a36Sopenharmony_ci		nbx = pitch;
64662306a36Sopenharmony_ci		nby = height;
64762306a36Sopenharmony_ci		if (G_028D24_LINEAR(track->htile_surface)) {
64862306a36Sopenharmony_ci			/* nbx must be 16 htiles aligned == 16 * 8 pixel aligned */
64962306a36Sopenharmony_ci			nbx = round_up(nbx, 16 * 8);
65062306a36Sopenharmony_ci			/* nby is npipes htiles aligned == npipes * 8 pixel aligned */
65162306a36Sopenharmony_ci			nby = round_up(nby, track->npipes * 8);
65262306a36Sopenharmony_ci		} else {
65362306a36Sopenharmony_ci			/* always assume 8x8 htile */
65462306a36Sopenharmony_ci			/* align is htile align * 8, htile align vary according to
65562306a36Sopenharmony_ci			 * number of pipe and tile width and nby
65662306a36Sopenharmony_ci			 */
65762306a36Sopenharmony_ci			switch (track->npipes) {
65862306a36Sopenharmony_ci			case 8:
65962306a36Sopenharmony_ci				/* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/
66062306a36Sopenharmony_ci				nbx = round_up(nbx, 64 * 8);
66162306a36Sopenharmony_ci				nby = round_up(nby, 64 * 8);
66262306a36Sopenharmony_ci				break;
66362306a36Sopenharmony_ci			case 4:
66462306a36Sopenharmony_ci				/* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/
66562306a36Sopenharmony_ci				nbx = round_up(nbx, 64 * 8);
66662306a36Sopenharmony_ci				nby = round_up(nby, 32 * 8);
66762306a36Sopenharmony_ci				break;
66862306a36Sopenharmony_ci			case 2:
66962306a36Sopenharmony_ci				/* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/
67062306a36Sopenharmony_ci				nbx = round_up(nbx, 32 * 8);
67162306a36Sopenharmony_ci				nby = round_up(nby, 32 * 8);
67262306a36Sopenharmony_ci				break;
67362306a36Sopenharmony_ci			case 1:
67462306a36Sopenharmony_ci				/* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/
67562306a36Sopenharmony_ci				nbx = round_up(nbx, 32 * 8);
67662306a36Sopenharmony_ci				nby = round_up(nby, 16 * 8);
67762306a36Sopenharmony_ci				break;
67862306a36Sopenharmony_ci			default:
67962306a36Sopenharmony_ci				dev_warn(p->dev, "%s:%d invalid num pipes %d\n",
68062306a36Sopenharmony_ci					 __func__, __LINE__, track->npipes);
68162306a36Sopenharmony_ci				return -EINVAL;
68262306a36Sopenharmony_ci			}
68362306a36Sopenharmony_ci		}
68462306a36Sopenharmony_ci		/* compute number of htile */
68562306a36Sopenharmony_ci		nbx = nbx >> 3;
68662306a36Sopenharmony_ci		nby = nby >> 3;
68762306a36Sopenharmony_ci		/* size must be aligned on npipes * 2K boundary */
68862306a36Sopenharmony_ci		size = roundup(nbx * nby * 4, track->npipes * (2 << 10));
68962306a36Sopenharmony_ci		size += track->htile_offset;
69062306a36Sopenharmony_ci
69162306a36Sopenharmony_ci		if (size > radeon_bo_size(track->htile_bo)) {
69262306a36Sopenharmony_ci			dev_warn(p->dev, "%s:%d htile surface too small %ld for %ld (%d %d)\n",
69362306a36Sopenharmony_ci				 __func__, __LINE__, radeon_bo_size(track->htile_bo),
69462306a36Sopenharmony_ci				 size, nbx, nby);
69562306a36Sopenharmony_ci			return -EINVAL;
69662306a36Sopenharmony_ci		}
69762306a36Sopenharmony_ci	}
69862306a36Sopenharmony_ci
69962306a36Sopenharmony_ci	track->db_dirty = false;
70062306a36Sopenharmony_ci	return 0;
70162306a36Sopenharmony_ci}
70262306a36Sopenharmony_ci
70362306a36Sopenharmony_cistatic int r600_cs_track_check(struct radeon_cs_parser *p)
70462306a36Sopenharmony_ci{
70562306a36Sopenharmony_ci	struct r600_cs_track *track = p->track;
70662306a36Sopenharmony_ci	u32 tmp;
70762306a36Sopenharmony_ci	int r, i;
70862306a36Sopenharmony_ci
70962306a36Sopenharmony_ci	/* on legacy kernel we don't perform advanced check */
71062306a36Sopenharmony_ci	if (p->rdev == NULL)
71162306a36Sopenharmony_ci		return 0;
71262306a36Sopenharmony_ci
71362306a36Sopenharmony_ci	/* check streamout */
71462306a36Sopenharmony_ci	if (track->streamout_dirty && track->vgt_strmout_en) {
71562306a36Sopenharmony_ci		for (i = 0; i < 4; i++) {
71662306a36Sopenharmony_ci			if (track->vgt_strmout_buffer_en & (1 << i)) {
71762306a36Sopenharmony_ci				if (track->vgt_strmout_bo[i]) {
71862306a36Sopenharmony_ci					u64 offset = (u64)track->vgt_strmout_bo_offset[i] +
71962306a36Sopenharmony_ci						(u64)track->vgt_strmout_size[i];
72062306a36Sopenharmony_ci					if (offset > radeon_bo_size(track->vgt_strmout_bo[i])) {
72162306a36Sopenharmony_ci						DRM_ERROR("streamout %d bo too small: 0x%llx, 0x%lx\n",
72262306a36Sopenharmony_ci							  i, offset,
72362306a36Sopenharmony_ci							  radeon_bo_size(track->vgt_strmout_bo[i]));
72462306a36Sopenharmony_ci						return -EINVAL;
72562306a36Sopenharmony_ci					}
72662306a36Sopenharmony_ci				} else {
72762306a36Sopenharmony_ci					dev_warn(p->dev, "No buffer for streamout %d\n", i);
72862306a36Sopenharmony_ci					return -EINVAL;
72962306a36Sopenharmony_ci				}
73062306a36Sopenharmony_ci			}
73162306a36Sopenharmony_ci		}
73262306a36Sopenharmony_ci		track->streamout_dirty = false;
73362306a36Sopenharmony_ci	}
73462306a36Sopenharmony_ci
73562306a36Sopenharmony_ci	if (track->sx_misc_kill_all_prims)
73662306a36Sopenharmony_ci		return 0;
73762306a36Sopenharmony_ci
73862306a36Sopenharmony_ci	/* check that we have a cb for each enabled target, we don't check
73962306a36Sopenharmony_ci	 * shader_mask because it seems mesa isn't always setting it :(
74062306a36Sopenharmony_ci	 */
74162306a36Sopenharmony_ci	if (track->cb_dirty) {
74262306a36Sopenharmony_ci		tmp = track->cb_target_mask;
74362306a36Sopenharmony_ci
74462306a36Sopenharmony_ci		/* We must check both colorbuffers for RESOLVE. */
74562306a36Sopenharmony_ci		if (track->is_resolve) {
74662306a36Sopenharmony_ci			tmp |= 0xff;
74762306a36Sopenharmony_ci		}
74862306a36Sopenharmony_ci
74962306a36Sopenharmony_ci		for (i = 0; i < 8; i++) {
75062306a36Sopenharmony_ci			u32 format = G_0280A0_FORMAT(track->cb_color_info[i]);
75162306a36Sopenharmony_ci
75262306a36Sopenharmony_ci			if (format != V_0280A0_COLOR_INVALID &&
75362306a36Sopenharmony_ci			    (tmp >> (i * 4)) & 0xF) {
75462306a36Sopenharmony_ci				/* at least one component is enabled */
75562306a36Sopenharmony_ci				if (track->cb_color_bo[i] == NULL) {
75662306a36Sopenharmony_ci					dev_warn(p->dev, "%s:%d mask 0x%08X | 0x%08X no cb for %d\n",
75762306a36Sopenharmony_ci						__func__, __LINE__, track->cb_target_mask, track->cb_shader_mask, i);
75862306a36Sopenharmony_ci					return -EINVAL;
75962306a36Sopenharmony_ci				}
76062306a36Sopenharmony_ci				/* perform rewrite of CB_COLOR[0-7]_SIZE */
76162306a36Sopenharmony_ci				r = r600_cs_track_validate_cb(p, i);
76262306a36Sopenharmony_ci				if (r)
76362306a36Sopenharmony_ci					return r;
76462306a36Sopenharmony_ci			}
76562306a36Sopenharmony_ci		}
76662306a36Sopenharmony_ci		track->cb_dirty = false;
76762306a36Sopenharmony_ci	}
76862306a36Sopenharmony_ci
76962306a36Sopenharmony_ci	/* Check depth buffer */
77062306a36Sopenharmony_ci	if (track->db_dirty &&
77162306a36Sopenharmony_ci	    G_028010_FORMAT(track->db_depth_info) != V_028010_DEPTH_INVALID &&
77262306a36Sopenharmony_ci	    (G_028800_STENCIL_ENABLE(track->db_depth_control) ||
77362306a36Sopenharmony_ci	     G_028800_Z_ENABLE(track->db_depth_control))) {
77462306a36Sopenharmony_ci		r = r600_cs_track_validate_db(p);
77562306a36Sopenharmony_ci		if (r)
77662306a36Sopenharmony_ci			return r;
77762306a36Sopenharmony_ci	}
77862306a36Sopenharmony_ci
77962306a36Sopenharmony_ci	return 0;
78062306a36Sopenharmony_ci}
78162306a36Sopenharmony_ci
78262306a36Sopenharmony_ci/**
78362306a36Sopenharmony_ci * r600_cs_packet_parse_vline() - parse userspace VLINE packet
78462306a36Sopenharmony_ci * @p:		parser structure holding parsing context.
78562306a36Sopenharmony_ci *
78662306a36Sopenharmony_ci * This is an R600-specific function for parsing VLINE packets.
78762306a36Sopenharmony_ci * Real work is done by r600_cs_common_vline_parse function.
78862306a36Sopenharmony_ci * Here we just set up ASIC-specific register table and call
78962306a36Sopenharmony_ci * the common implementation function.
79062306a36Sopenharmony_ci */
79162306a36Sopenharmony_cistatic int r600_cs_packet_parse_vline(struct radeon_cs_parser *p)
79262306a36Sopenharmony_ci{
79362306a36Sopenharmony_ci	static uint32_t vline_start_end[2] = {AVIVO_D1MODE_VLINE_START_END,
79462306a36Sopenharmony_ci					      AVIVO_D2MODE_VLINE_START_END};
79562306a36Sopenharmony_ci	static uint32_t vline_status[2] = {AVIVO_D1MODE_VLINE_STATUS,
79662306a36Sopenharmony_ci					   AVIVO_D2MODE_VLINE_STATUS};
79762306a36Sopenharmony_ci
79862306a36Sopenharmony_ci	return r600_cs_common_vline_parse(p, vline_start_end, vline_status);
79962306a36Sopenharmony_ci}
80062306a36Sopenharmony_ci
80162306a36Sopenharmony_ci/**
80262306a36Sopenharmony_ci * r600_cs_common_vline_parse() - common vline parser
80362306a36Sopenharmony_ci * @p:			parser structure holding parsing context.
80462306a36Sopenharmony_ci * @vline_start_end:    table of vline_start_end registers
80562306a36Sopenharmony_ci * @vline_status:       table of vline_status registers
80662306a36Sopenharmony_ci *
80762306a36Sopenharmony_ci * Userspace sends a special sequence for VLINE waits.
80862306a36Sopenharmony_ci * PACKET0 - VLINE_START_END + value
80962306a36Sopenharmony_ci * PACKET3 - WAIT_REG_MEM poll vline status reg
81062306a36Sopenharmony_ci * RELOC (P3) - crtc_id in reloc.
81162306a36Sopenharmony_ci *
81262306a36Sopenharmony_ci * This function parses this and relocates the VLINE START END
81362306a36Sopenharmony_ci * and WAIT_REG_MEM packets to the correct crtc.
81462306a36Sopenharmony_ci * It also detects a switched off crtc and nulls out the
81562306a36Sopenharmony_ci * wait in that case. This function is common for all ASICs that
81662306a36Sopenharmony_ci * are R600 and newer. The parsing algorithm is the same, and only
81762306a36Sopenharmony_ci * differs in which registers are used.
81862306a36Sopenharmony_ci *
81962306a36Sopenharmony_ci * Caller is the ASIC-specific function which passes the parser
82062306a36Sopenharmony_ci * context and ASIC-specific register table
82162306a36Sopenharmony_ci */
82262306a36Sopenharmony_ciint r600_cs_common_vline_parse(struct radeon_cs_parser *p,
82362306a36Sopenharmony_ci			       uint32_t *vline_start_end,
82462306a36Sopenharmony_ci			       uint32_t *vline_status)
82562306a36Sopenharmony_ci{
82662306a36Sopenharmony_ci	struct drm_crtc *crtc;
82762306a36Sopenharmony_ci	struct radeon_crtc *radeon_crtc;
82862306a36Sopenharmony_ci	struct radeon_cs_packet p3reloc, wait_reg_mem;
82962306a36Sopenharmony_ci	int crtc_id;
83062306a36Sopenharmony_ci	int r;
83162306a36Sopenharmony_ci	uint32_t header, h_idx, reg, wait_reg_mem_info;
83262306a36Sopenharmony_ci	volatile uint32_t *ib;
83362306a36Sopenharmony_ci
83462306a36Sopenharmony_ci	ib = p->ib.ptr;
83562306a36Sopenharmony_ci
83662306a36Sopenharmony_ci	/* parse the WAIT_REG_MEM */
83762306a36Sopenharmony_ci	r = radeon_cs_packet_parse(p, &wait_reg_mem, p->idx);
83862306a36Sopenharmony_ci	if (r)
83962306a36Sopenharmony_ci		return r;
84062306a36Sopenharmony_ci
84162306a36Sopenharmony_ci	/* check its a WAIT_REG_MEM */
84262306a36Sopenharmony_ci	if (wait_reg_mem.type != RADEON_PACKET_TYPE3 ||
84362306a36Sopenharmony_ci	    wait_reg_mem.opcode != PACKET3_WAIT_REG_MEM) {
84462306a36Sopenharmony_ci		DRM_ERROR("vline wait missing WAIT_REG_MEM segment\n");
84562306a36Sopenharmony_ci		return -EINVAL;
84662306a36Sopenharmony_ci	}
84762306a36Sopenharmony_ci
84862306a36Sopenharmony_ci	wait_reg_mem_info = radeon_get_ib_value(p, wait_reg_mem.idx + 1);
84962306a36Sopenharmony_ci	/* bit 4 is reg (0) or mem (1) */
85062306a36Sopenharmony_ci	if (wait_reg_mem_info & 0x10) {
85162306a36Sopenharmony_ci		DRM_ERROR("vline WAIT_REG_MEM waiting on MEM instead of REG\n");
85262306a36Sopenharmony_ci		return -EINVAL;
85362306a36Sopenharmony_ci	}
85462306a36Sopenharmony_ci	/* bit 8 is me (0) or pfp (1) */
85562306a36Sopenharmony_ci	if (wait_reg_mem_info & 0x100) {
85662306a36Sopenharmony_ci		DRM_ERROR("vline WAIT_REG_MEM waiting on PFP instead of ME\n");
85762306a36Sopenharmony_ci		return -EINVAL;
85862306a36Sopenharmony_ci	}
85962306a36Sopenharmony_ci	/* waiting for value to be equal */
86062306a36Sopenharmony_ci	if ((wait_reg_mem_info & 0x7) != 0x3) {
86162306a36Sopenharmony_ci		DRM_ERROR("vline WAIT_REG_MEM function not equal\n");
86262306a36Sopenharmony_ci		return -EINVAL;
86362306a36Sopenharmony_ci	}
86462306a36Sopenharmony_ci	if ((radeon_get_ib_value(p, wait_reg_mem.idx + 2) << 2) != vline_status[0]) {
86562306a36Sopenharmony_ci		DRM_ERROR("vline WAIT_REG_MEM bad reg\n");
86662306a36Sopenharmony_ci		return -EINVAL;
86762306a36Sopenharmony_ci	}
86862306a36Sopenharmony_ci
86962306a36Sopenharmony_ci	if (radeon_get_ib_value(p, wait_reg_mem.idx + 5) != RADEON_VLINE_STAT) {
87062306a36Sopenharmony_ci		DRM_ERROR("vline WAIT_REG_MEM bad bit mask\n");
87162306a36Sopenharmony_ci		return -EINVAL;
87262306a36Sopenharmony_ci	}
87362306a36Sopenharmony_ci
87462306a36Sopenharmony_ci	/* jump over the NOP */
87562306a36Sopenharmony_ci	r = radeon_cs_packet_parse(p, &p3reloc, p->idx + wait_reg_mem.count + 2);
87662306a36Sopenharmony_ci	if (r)
87762306a36Sopenharmony_ci		return r;
87862306a36Sopenharmony_ci
87962306a36Sopenharmony_ci	h_idx = p->idx - 2;
88062306a36Sopenharmony_ci	p->idx += wait_reg_mem.count + 2;
88162306a36Sopenharmony_ci	p->idx += p3reloc.count + 2;
88262306a36Sopenharmony_ci
88362306a36Sopenharmony_ci	header = radeon_get_ib_value(p, h_idx);
88462306a36Sopenharmony_ci	crtc_id = radeon_get_ib_value(p, h_idx + 2 + 7 + 1);
88562306a36Sopenharmony_ci	reg = R600_CP_PACKET0_GET_REG(header);
88662306a36Sopenharmony_ci
88762306a36Sopenharmony_ci	crtc = drm_crtc_find(p->rdev->ddev, p->filp, crtc_id);
88862306a36Sopenharmony_ci	if (!crtc) {
88962306a36Sopenharmony_ci		DRM_ERROR("cannot find crtc %d\n", crtc_id);
89062306a36Sopenharmony_ci		return -ENOENT;
89162306a36Sopenharmony_ci	}
89262306a36Sopenharmony_ci	radeon_crtc = to_radeon_crtc(crtc);
89362306a36Sopenharmony_ci	crtc_id = radeon_crtc->crtc_id;
89462306a36Sopenharmony_ci
89562306a36Sopenharmony_ci	if (!crtc->enabled) {
89662306a36Sopenharmony_ci		/* CRTC isn't enabled - we need to nop out the WAIT_REG_MEM */
89762306a36Sopenharmony_ci		ib[h_idx + 2] = PACKET2(0);
89862306a36Sopenharmony_ci		ib[h_idx + 3] = PACKET2(0);
89962306a36Sopenharmony_ci		ib[h_idx + 4] = PACKET2(0);
90062306a36Sopenharmony_ci		ib[h_idx + 5] = PACKET2(0);
90162306a36Sopenharmony_ci		ib[h_idx + 6] = PACKET2(0);
90262306a36Sopenharmony_ci		ib[h_idx + 7] = PACKET2(0);
90362306a36Sopenharmony_ci		ib[h_idx + 8] = PACKET2(0);
90462306a36Sopenharmony_ci	} else if (reg == vline_start_end[0]) {
90562306a36Sopenharmony_ci		header &= ~R600_CP_PACKET0_REG_MASK;
90662306a36Sopenharmony_ci		header |= vline_start_end[crtc_id] >> 2;
90762306a36Sopenharmony_ci		ib[h_idx] = header;
90862306a36Sopenharmony_ci		ib[h_idx + 4] = vline_status[crtc_id] >> 2;
90962306a36Sopenharmony_ci	} else {
91062306a36Sopenharmony_ci		DRM_ERROR("unknown crtc reloc\n");
91162306a36Sopenharmony_ci		return -EINVAL;
91262306a36Sopenharmony_ci	}
91362306a36Sopenharmony_ci	return 0;
91462306a36Sopenharmony_ci}
91562306a36Sopenharmony_ci
91662306a36Sopenharmony_cistatic int r600_packet0_check(struct radeon_cs_parser *p,
91762306a36Sopenharmony_ci				struct radeon_cs_packet *pkt,
91862306a36Sopenharmony_ci				unsigned idx, unsigned reg)
91962306a36Sopenharmony_ci{
92062306a36Sopenharmony_ci	int r;
92162306a36Sopenharmony_ci
92262306a36Sopenharmony_ci	switch (reg) {
92362306a36Sopenharmony_ci	case AVIVO_D1MODE_VLINE_START_END:
92462306a36Sopenharmony_ci		r = r600_cs_packet_parse_vline(p);
92562306a36Sopenharmony_ci		if (r) {
92662306a36Sopenharmony_ci			DRM_ERROR("No reloc for ib[%d]=0x%04X\n",
92762306a36Sopenharmony_ci					idx, reg);
92862306a36Sopenharmony_ci			return r;
92962306a36Sopenharmony_ci		}
93062306a36Sopenharmony_ci		break;
93162306a36Sopenharmony_ci	default:
93262306a36Sopenharmony_ci		pr_err("Forbidden register 0x%04X in cs at %d\n", reg, idx);
93362306a36Sopenharmony_ci		return -EINVAL;
93462306a36Sopenharmony_ci	}
93562306a36Sopenharmony_ci	return 0;
93662306a36Sopenharmony_ci}
93762306a36Sopenharmony_ci
93862306a36Sopenharmony_cistatic int r600_cs_parse_packet0(struct radeon_cs_parser *p,
93962306a36Sopenharmony_ci				struct radeon_cs_packet *pkt)
94062306a36Sopenharmony_ci{
94162306a36Sopenharmony_ci	unsigned reg, i;
94262306a36Sopenharmony_ci	unsigned idx;
94362306a36Sopenharmony_ci	int r;
94462306a36Sopenharmony_ci
94562306a36Sopenharmony_ci	idx = pkt->idx + 1;
94662306a36Sopenharmony_ci	reg = pkt->reg;
94762306a36Sopenharmony_ci	for (i = 0; i <= pkt->count; i++, idx++, reg += 4) {
94862306a36Sopenharmony_ci		r = r600_packet0_check(p, pkt, idx, reg);
94962306a36Sopenharmony_ci		if (r) {
95062306a36Sopenharmony_ci			return r;
95162306a36Sopenharmony_ci		}
95262306a36Sopenharmony_ci	}
95362306a36Sopenharmony_ci	return 0;
95462306a36Sopenharmony_ci}
95562306a36Sopenharmony_ci
95662306a36Sopenharmony_ci/**
95762306a36Sopenharmony_ci * r600_cs_check_reg() - check if register is authorized or not
95862306a36Sopenharmony_ci * @p: parser structure holding parsing context
95962306a36Sopenharmony_ci * @reg: register we are testing
96062306a36Sopenharmony_ci * @idx: index into the cs buffer
96162306a36Sopenharmony_ci *
96262306a36Sopenharmony_ci * This function will test against r600_reg_safe_bm and return 0
96362306a36Sopenharmony_ci * if register is safe. If register is not flag as safe this function
96462306a36Sopenharmony_ci * will test it against a list of register needing special handling.
96562306a36Sopenharmony_ci */
96662306a36Sopenharmony_cistatic int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
96762306a36Sopenharmony_ci{
96862306a36Sopenharmony_ci	struct r600_cs_track *track = (struct r600_cs_track *)p->track;
96962306a36Sopenharmony_ci	struct radeon_bo_list *reloc;
97062306a36Sopenharmony_ci	u32 m, i, tmp, *ib;
97162306a36Sopenharmony_ci	int r;
97262306a36Sopenharmony_ci
97362306a36Sopenharmony_ci	i = (reg >> 7);
97462306a36Sopenharmony_ci	if (i >= ARRAY_SIZE(r600_reg_safe_bm)) {
97562306a36Sopenharmony_ci		dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
97662306a36Sopenharmony_ci		return -EINVAL;
97762306a36Sopenharmony_ci	}
97862306a36Sopenharmony_ci	m = 1 << ((reg >> 2) & 31);
97962306a36Sopenharmony_ci	if (!(r600_reg_safe_bm[i] & m))
98062306a36Sopenharmony_ci		return 0;
98162306a36Sopenharmony_ci	ib = p->ib.ptr;
98262306a36Sopenharmony_ci	switch (reg) {
98362306a36Sopenharmony_ci	/* force following reg to 0 in an attempt to disable out buffer
98462306a36Sopenharmony_ci	 * which will need us to better understand how it works to perform
98562306a36Sopenharmony_ci	 * security check on it (Jerome)
98662306a36Sopenharmony_ci	 */
98762306a36Sopenharmony_ci	case R_0288A8_SQ_ESGS_RING_ITEMSIZE:
98862306a36Sopenharmony_ci	case R_008C44_SQ_ESGS_RING_SIZE:
98962306a36Sopenharmony_ci	case R_0288B0_SQ_ESTMP_RING_ITEMSIZE:
99062306a36Sopenharmony_ci	case R_008C54_SQ_ESTMP_RING_SIZE:
99162306a36Sopenharmony_ci	case R_0288C0_SQ_FBUF_RING_ITEMSIZE:
99262306a36Sopenharmony_ci	case R_008C74_SQ_FBUF_RING_SIZE:
99362306a36Sopenharmony_ci	case R_0288B4_SQ_GSTMP_RING_ITEMSIZE:
99462306a36Sopenharmony_ci	case R_008C5C_SQ_GSTMP_RING_SIZE:
99562306a36Sopenharmony_ci	case R_0288AC_SQ_GSVS_RING_ITEMSIZE:
99662306a36Sopenharmony_ci	case R_008C4C_SQ_GSVS_RING_SIZE:
99762306a36Sopenharmony_ci	case R_0288BC_SQ_PSTMP_RING_ITEMSIZE:
99862306a36Sopenharmony_ci	case R_008C6C_SQ_PSTMP_RING_SIZE:
99962306a36Sopenharmony_ci	case R_0288C4_SQ_REDUC_RING_ITEMSIZE:
100062306a36Sopenharmony_ci	case R_008C7C_SQ_REDUC_RING_SIZE:
100162306a36Sopenharmony_ci	case R_0288B8_SQ_VSTMP_RING_ITEMSIZE:
100262306a36Sopenharmony_ci	case R_008C64_SQ_VSTMP_RING_SIZE:
100362306a36Sopenharmony_ci	case R_0288C8_SQ_GS_VERT_ITEMSIZE:
100462306a36Sopenharmony_ci		/* get value to populate the IB don't remove */
100562306a36Sopenharmony_ci		/*tmp =radeon_get_ib_value(p, idx);
100662306a36Sopenharmony_ci		  ib[idx] = 0;*/
100762306a36Sopenharmony_ci		break;
100862306a36Sopenharmony_ci	case SQ_ESGS_RING_BASE:
100962306a36Sopenharmony_ci	case SQ_GSVS_RING_BASE:
101062306a36Sopenharmony_ci	case SQ_ESTMP_RING_BASE:
101162306a36Sopenharmony_ci	case SQ_GSTMP_RING_BASE:
101262306a36Sopenharmony_ci	case SQ_PSTMP_RING_BASE:
101362306a36Sopenharmony_ci	case SQ_VSTMP_RING_BASE:
101462306a36Sopenharmony_ci		r = radeon_cs_packet_next_reloc(p, &reloc, 0);
101562306a36Sopenharmony_ci		if (r) {
101662306a36Sopenharmony_ci			dev_warn(p->dev, "bad SET_CONTEXT_REG "
101762306a36Sopenharmony_ci					"0x%04X\n", reg);
101862306a36Sopenharmony_ci			return -EINVAL;
101962306a36Sopenharmony_ci		}
102062306a36Sopenharmony_ci		ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
102162306a36Sopenharmony_ci		break;
102262306a36Sopenharmony_ci	case SQ_CONFIG:
102362306a36Sopenharmony_ci		track->sq_config = radeon_get_ib_value(p, idx);
102462306a36Sopenharmony_ci		break;
102562306a36Sopenharmony_ci	case R_028800_DB_DEPTH_CONTROL:
102662306a36Sopenharmony_ci		track->db_depth_control = radeon_get_ib_value(p, idx);
102762306a36Sopenharmony_ci		track->db_dirty = true;
102862306a36Sopenharmony_ci		break;
102962306a36Sopenharmony_ci	case R_028010_DB_DEPTH_INFO:
103062306a36Sopenharmony_ci		if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS) &&
103162306a36Sopenharmony_ci		    radeon_cs_packet_next_is_pkt3_nop(p)) {
103262306a36Sopenharmony_ci			r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
103362306a36Sopenharmony_ci			if (r) {
103462306a36Sopenharmony_ci				dev_warn(p->dev, "bad SET_CONTEXT_REG "
103562306a36Sopenharmony_ci					 "0x%04X\n", reg);
103662306a36Sopenharmony_ci				return -EINVAL;
103762306a36Sopenharmony_ci			}
103862306a36Sopenharmony_ci			track->db_depth_info = radeon_get_ib_value(p, idx);
103962306a36Sopenharmony_ci			ib[idx] &= C_028010_ARRAY_MODE;
104062306a36Sopenharmony_ci			track->db_depth_info &= C_028010_ARRAY_MODE;
104162306a36Sopenharmony_ci			if (reloc->tiling_flags & RADEON_TILING_MACRO) {
104262306a36Sopenharmony_ci				ib[idx] |= S_028010_ARRAY_MODE(V_028010_ARRAY_2D_TILED_THIN1);
104362306a36Sopenharmony_ci				track->db_depth_info |= S_028010_ARRAY_MODE(V_028010_ARRAY_2D_TILED_THIN1);
104462306a36Sopenharmony_ci			} else {
104562306a36Sopenharmony_ci				ib[idx] |= S_028010_ARRAY_MODE(V_028010_ARRAY_1D_TILED_THIN1);
104662306a36Sopenharmony_ci				track->db_depth_info |= S_028010_ARRAY_MODE(V_028010_ARRAY_1D_TILED_THIN1);
104762306a36Sopenharmony_ci			}
104862306a36Sopenharmony_ci		} else {
104962306a36Sopenharmony_ci			track->db_depth_info = radeon_get_ib_value(p, idx);
105062306a36Sopenharmony_ci		}
105162306a36Sopenharmony_ci		track->db_dirty = true;
105262306a36Sopenharmony_ci		break;
105362306a36Sopenharmony_ci	case R_028004_DB_DEPTH_VIEW:
105462306a36Sopenharmony_ci		track->db_depth_view = radeon_get_ib_value(p, idx);
105562306a36Sopenharmony_ci		track->db_dirty = true;
105662306a36Sopenharmony_ci		break;
105762306a36Sopenharmony_ci	case R_028000_DB_DEPTH_SIZE:
105862306a36Sopenharmony_ci		track->db_depth_size = radeon_get_ib_value(p, idx);
105962306a36Sopenharmony_ci		track->db_depth_size_idx = idx;
106062306a36Sopenharmony_ci		track->db_dirty = true;
106162306a36Sopenharmony_ci		break;
106262306a36Sopenharmony_ci	case R_028AB0_VGT_STRMOUT_EN:
106362306a36Sopenharmony_ci		track->vgt_strmout_en = radeon_get_ib_value(p, idx);
106462306a36Sopenharmony_ci		track->streamout_dirty = true;
106562306a36Sopenharmony_ci		break;
106662306a36Sopenharmony_ci	case R_028B20_VGT_STRMOUT_BUFFER_EN:
106762306a36Sopenharmony_ci		track->vgt_strmout_buffer_en = radeon_get_ib_value(p, idx);
106862306a36Sopenharmony_ci		track->streamout_dirty = true;
106962306a36Sopenharmony_ci		break;
107062306a36Sopenharmony_ci	case VGT_STRMOUT_BUFFER_BASE_0:
107162306a36Sopenharmony_ci	case VGT_STRMOUT_BUFFER_BASE_1:
107262306a36Sopenharmony_ci	case VGT_STRMOUT_BUFFER_BASE_2:
107362306a36Sopenharmony_ci	case VGT_STRMOUT_BUFFER_BASE_3:
107462306a36Sopenharmony_ci		r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
107562306a36Sopenharmony_ci		if (r) {
107662306a36Sopenharmony_ci			dev_warn(p->dev, "bad SET_CONTEXT_REG "
107762306a36Sopenharmony_ci					"0x%04X\n", reg);
107862306a36Sopenharmony_ci			return -EINVAL;
107962306a36Sopenharmony_ci		}
108062306a36Sopenharmony_ci		tmp = (reg - VGT_STRMOUT_BUFFER_BASE_0) / 16;
108162306a36Sopenharmony_ci		track->vgt_strmout_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8;
108262306a36Sopenharmony_ci		ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
108362306a36Sopenharmony_ci		track->vgt_strmout_bo[tmp] = reloc->robj;
108462306a36Sopenharmony_ci		track->vgt_strmout_bo_mc[tmp] = reloc->gpu_offset;
108562306a36Sopenharmony_ci		track->streamout_dirty = true;
108662306a36Sopenharmony_ci		break;
108762306a36Sopenharmony_ci	case VGT_STRMOUT_BUFFER_SIZE_0:
108862306a36Sopenharmony_ci	case VGT_STRMOUT_BUFFER_SIZE_1:
108962306a36Sopenharmony_ci	case VGT_STRMOUT_BUFFER_SIZE_2:
109062306a36Sopenharmony_ci	case VGT_STRMOUT_BUFFER_SIZE_3:
109162306a36Sopenharmony_ci		tmp = (reg - VGT_STRMOUT_BUFFER_SIZE_0) / 16;
109262306a36Sopenharmony_ci		/* size in register is DWs, convert to bytes */
109362306a36Sopenharmony_ci		track->vgt_strmout_size[tmp] = radeon_get_ib_value(p, idx) * 4;
109462306a36Sopenharmony_ci		track->streamout_dirty = true;
109562306a36Sopenharmony_ci		break;
109662306a36Sopenharmony_ci	case CP_COHER_BASE:
109762306a36Sopenharmony_ci		r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
109862306a36Sopenharmony_ci		if (r) {
109962306a36Sopenharmony_ci			dev_warn(p->dev, "missing reloc for CP_COHER_BASE "
110062306a36Sopenharmony_ci					"0x%04X\n", reg);
110162306a36Sopenharmony_ci			return -EINVAL;
110262306a36Sopenharmony_ci		}
110362306a36Sopenharmony_ci		ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
110462306a36Sopenharmony_ci		break;
110562306a36Sopenharmony_ci	case R_028238_CB_TARGET_MASK:
110662306a36Sopenharmony_ci		track->cb_target_mask = radeon_get_ib_value(p, idx);
110762306a36Sopenharmony_ci		track->cb_dirty = true;
110862306a36Sopenharmony_ci		break;
110962306a36Sopenharmony_ci	case R_02823C_CB_SHADER_MASK:
111062306a36Sopenharmony_ci		track->cb_shader_mask = radeon_get_ib_value(p, idx);
111162306a36Sopenharmony_ci		break;
111262306a36Sopenharmony_ci	case R_028C04_PA_SC_AA_CONFIG:
111362306a36Sopenharmony_ci		tmp = G_028C04_MSAA_NUM_SAMPLES(radeon_get_ib_value(p, idx));
111462306a36Sopenharmony_ci		track->log_nsamples = tmp;
111562306a36Sopenharmony_ci		track->nsamples = 1 << tmp;
111662306a36Sopenharmony_ci		track->cb_dirty = true;
111762306a36Sopenharmony_ci		break;
111862306a36Sopenharmony_ci	case R_028808_CB_COLOR_CONTROL:
111962306a36Sopenharmony_ci		tmp = G_028808_SPECIAL_OP(radeon_get_ib_value(p, idx));
112062306a36Sopenharmony_ci		track->is_resolve = tmp == V_028808_SPECIAL_RESOLVE_BOX;
112162306a36Sopenharmony_ci		track->cb_dirty = true;
112262306a36Sopenharmony_ci		break;
112362306a36Sopenharmony_ci	case R_0280A0_CB_COLOR0_INFO:
112462306a36Sopenharmony_ci	case R_0280A4_CB_COLOR1_INFO:
112562306a36Sopenharmony_ci	case R_0280A8_CB_COLOR2_INFO:
112662306a36Sopenharmony_ci	case R_0280AC_CB_COLOR3_INFO:
112762306a36Sopenharmony_ci	case R_0280B0_CB_COLOR4_INFO:
112862306a36Sopenharmony_ci	case R_0280B4_CB_COLOR5_INFO:
112962306a36Sopenharmony_ci	case R_0280B8_CB_COLOR6_INFO:
113062306a36Sopenharmony_ci	case R_0280BC_CB_COLOR7_INFO:
113162306a36Sopenharmony_ci		if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS) &&
113262306a36Sopenharmony_ci		     radeon_cs_packet_next_is_pkt3_nop(p)) {
113362306a36Sopenharmony_ci			r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
113462306a36Sopenharmony_ci			if (r) {
113562306a36Sopenharmony_ci				dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
113662306a36Sopenharmony_ci				return -EINVAL;
113762306a36Sopenharmony_ci			}
113862306a36Sopenharmony_ci			tmp = (reg - R_0280A0_CB_COLOR0_INFO) / 4;
113962306a36Sopenharmony_ci			track->cb_color_info[tmp] = radeon_get_ib_value(p, idx);
114062306a36Sopenharmony_ci			if (reloc->tiling_flags & RADEON_TILING_MACRO) {
114162306a36Sopenharmony_ci				ib[idx] |= S_0280A0_ARRAY_MODE(V_0280A0_ARRAY_2D_TILED_THIN1);
114262306a36Sopenharmony_ci				track->cb_color_info[tmp] |= S_0280A0_ARRAY_MODE(V_0280A0_ARRAY_2D_TILED_THIN1);
114362306a36Sopenharmony_ci			} else if (reloc->tiling_flags & RADEON_TILING_MICRO) {
114462306a36Sopenharmony_ci				ib[idx] |= S_0280A0_ARRAY_MODE(V_0280A0_ARRAY_1D_TILED_THIN1);
114562306a36Sopenharmony_ci				track->cb_color_info[tmp] |= S_0280A0_ARRAY_MODE(V_0280A0_ARRAY_1D_TILED_THIN1);
114662306a36Sopenharmony_ci			}
114762306a36Sopenharmony_ci		} else {
114862306a36Sopenharmony_ci			tmp = (reg - R_0280A0_CB_COLOR0_INFO) / 4;
114962306a36Sopenharmony_ci			track->cb_color_info[tmp] = radeon_get_ib_value(p, idx);
115062306a36Sopenharmony_ci		}
115162306a36Sopenharmony_ci		track->cb_dirty = true;
115262306a36Sopenharmony_ci		break;
115362306a36Sopenharmony_ci	case R_028080_CB_COLOR0_VIEW:
115462306a36Sopenharmony_ci	case R_028084_CB_COLOR1_VIEW:
115562306a36Sopenharmony_ci	case R_028088_CB_COLOR2_VIEW:
115662306a36Sopenharmony_ci	case R_02808C_CB_COLOR3_VIEW:
115762306a36Sopenharmony_ci	case R_028090_CB_COLOR4_VIEW:
115862306a36Sopenharmony_ci	case R_028094_CB_COLOR5_VIEW:
115962306a36Sopenharmony_ci	case R_028098_CB_COLOR6_VIEW:
116062306a36Sopenharmony_ci	case R_02809C_CB_COLOR7_VIEW:
116162306a36Sopenharmony_ci		tmp = (reg - R_028080_CB_COLOR0_VIEW) / 4;
116262306a36Sopenharmony_ci		track->cb_color_view[tmp] = radeon_get_ib_value(p, idx);
116362306a36Sopenharmony_ci		track->cb_dirty = true;
116462306a36Sopenharmony_ci		break;
116562306a36Sopenharmony_ci	case R_028060_CB_COLOR0_SIZE:
116662306a36Sopenharmony_ci	case R_028064_CB_COLOR1_SIZE:
116762306a36Sopenharmony_ci	case R_028068_CB_COLOR2_SIZE:
116862306a36Sopenharmony_ci	case R_02806C_CB_COLOR3_SIZE:
116962306a36Sopenharmony_ci	case R_028070_CB_COLOR4_SIZE:
117062306a36Sopenharmony_ci	case R_028074_CB_COLOR5_SIZE:
117162306a36Sopenharmony_ci	case R_028078_CB_COLOR6_SIZE:
117262306a36Sopenharmony_ci	case R_02807C_CB_COLOR7_SIZE:
117362306a36Sopenharmony_ci		tmp = (reg - R_028060_CB_COLOR0_SIZE) / 4;
117462306a36Sopenharmony_ci		track->cb_color_size[tmp] = radeon_get_ib_value(p, idx);
117562306a36Sopenharmony_ci		track->cb_color_size_idx[tmp] = idx;
117662306a36Sopenharmony_ci		track->cb_dirty = true;
117762306a36Sopenharmony_ci		break;
117862306a36Sopenharmony_ci		/* This register were added late, there is userspace
117962306a36Sopenharmony_ci		 * which does provide relocation for those but set
118062306a36Sopenharmony_ci		 * 0 offset. In order to avoid breaking old userspace
118162306a36Sopenharmony_ci		 * we detect this and set address to point to last
118262306a36Sopenharmony_ci		 * CB_COLOR0_BASE, note that if userspace doesn't set
118362306a36Sopenharmony_ci		 * CB_COLOR0_BASE before this register we will report
118462306a36Sopenharmony_ci		 * error. Old userspace always set CB_COLOR0_BASE
118562306a36Sopenharmony_ci		 * before any of this.
118662306a36Sopenharmony_ci		 */
118762306a36Sopenharmony_ci	case R_0280E0_CB_COLOR0_FRAG:
118862306a36Sopenharmony_ci	case R_0280E4_CB_COLOR1_FRAG:
118962306a36Sopenharmony_ci	case R_0280E8_CB_COLOR2_FRAG:
119062306a36Sopenharmony_ci	case R_0280EC_CB_COLOR3_FRAG:
119162306a36Sopenharmony_ci	case R_0280F0_CB_COLOR4_FRAG:
119262306a36Sopenharmony_ci	case R_0280F4_CB_COLOR5_FRAG:
119362306a36Sopenharmony_ci	case R_0280F8_CB_COLOR6_FRAG:
119462306a36Sopenharmony_ci	case R_0280FC_CB_COLOR7_FRAG:
119562306a36Sopenharmony_ci		tmp = (reg - R_0280E0_CB_COLOR0_FRAG) / 4;
119662306a36Sopenharmony_ci		if (!radeon_cs_packet_next_is_pkt3_nop(p)) {
119762306a36Sopenharmony_ci			if (!track->cb_color_base_last[tmp]) {
119862306a36Sopenharmony_ci				dev_err(p->dev, "Broken old userspace ? no cb_color0_base supplied before trying to write 0x%08X\n", reg);
119962306a36Sopenharmony_ci				return -EINVAL;
120062306a36Sopenharmony_ci			}
120162306a36Sopenharmony_ci			track->cb_color_frag_bo[tmp] = track->cb_color_bo[tmp];
120262306a36Sopenharmony_ci			track->cb_color_frag_offset[tmp] = track->cb_color_bo_offset[tmp];
120362306a36Sopenharmony_ci			ib[idx] = track->cb_color_base_last[tmp];
120462306a36Sopenharmony_ci		} else {
120562306a36Sopenharmony_ci			r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
120662306a36Sopenharmony_ci			if (r) {
120762306a36Sopenharmony_ci				dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
120862306a36Sopenharmony_ci				return -EINVAL;
120962306a36Sopenharmony_ci			}
121062306a36Sopenharmony_ci			track->cb_color_frag_bo[tmp] = reloc->robj;
121162306a36Sopenharmony_ci			track->cb_color_frag_offset[tmp] = (u64)ib[idx] << 8;
121262306a36Sopenharmony_ci			ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
121362306a36Sopenharmony_ci		}
121462306a36Sopenharmony_ci		if (G_0280A0_TILE_MODE(track->cb_color_info[tmp])) {
121562306a36Sopenharmony_ci			track->cb_dirty = true;
121662306a36Sopenharmony_ci		}
121762306a36Sopenharmony_ci		break;
121862306a36Sopenharmony_ci	case R_0280C0_CB_COLOR0_TILE:
121962306a36Sopenharmony_ci	case R_0280C4_CB_COLOR1_TILE:
122062306a36Sopenharmony_ci	case R_0280C8_CB_COLOR2_TILE:
122162306a36Sopenharmony_ci	case R_0280CC_CB_COLOR3_TILE:
122262306a36Sopenharmony_ci	case R_0280D0_CB_COLOR4_TILE:
122362306a36Sopenharmony_ci	case R_0280D4_CB_COLOR5_TILE:
122462306a36Sopenharmony_ci	case R_0280D8_CB_COLOR6_TILE:
122562306a36Sopenharmony_ci	case R_0280DC_CB_COLOR7_TILE:
122662306a36Sopenharmony_ci		tmp = (reg - R_0280C0_CB_COLOR0_TILE) / 4;
122762306a36Sopenharmony_ci		if (!radeon_cs_packet_next_is_pkt3_nop(p)) {
122862306a36Sopenharmony_ci			if (!track->cb_color_base_last[tmp]) {
122962306a36Sopenharmony_ci				dev_err(p->dev, "Broken old userspace ? no cb_color0_base supplied before trying to write 0x%08X\n", reg);
123062306a36Sopenharmony_ci				return -EINVAL;
123162306a36Sopenharmony_ci			}
123262306a36Sopenharmony_ci			track->cb_color_tile_bo[tmp] = track->cb_color_bo[tmp];
123362306a36Sopenharmony_ci			track->cb_color_tile_offset[tmp] = track->cb_color_bo_offset[tmp];
123462306a36Sopenharmony_ci			ib[idx] = track->cb_color_base_last[tmp];
123562306a36Sopenharmony_ci		} else {
123662306a36Sopenharmony_ci			r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
123762306a36Sopenharmony_ci			if (r) {
123862306a36Sopenharmony_ci				dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg);
123962306a36Sopenharmony_ci				return -EINVAL;
124062306a36Sopenharmony_ci			}
124162306a36Sopenharmony_ci			track->cb_color_tile_bo[tmp] = reloc->robj;
124262306a36Sopenharmony_ci			track->cb_color_tile_offset[tmp] = (u64)ib[idx] << 8;
124362306a36Sopenharmony_ci			ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
124462306a36Sopenharmony_ci		}
124562306a36Sopenharmony_ci		if (G_0280A0_TILE_MODE(track->cb_color_info[tmp])) {
124662306a36Sopenharmony_ci			track->cb_dirty = true;
124762306a36Sopenharmony_ci		}
124862306a36Sopenharmony_ci		break;
124962306a36Sopenharmony_ci	case R_028100_CB_COLOR0_MASK:
125062306a36Sopenharmony_ci	case R_028104_CB_COLOR1_MASK:
125162306a36Sopenharmony_ci	case R_028108_CB_COLOR2_MASK:
125262306a36Sopenharmony_ci	case R_02810C_CB_COLOR3_MASK:
125362306a36Sopenharmony_ci	case R_028110_CB_COLOR4_MASK:
125462306a36Sopenharmony_ci	case R_028114_CB_COLOR5_MASK:
125562306a36Sopenharmony_ci	case R_028118_CB_COLOR6_MASK:
125662306a36Sopenharmony_ci	case R_02811C_CB_COLOR7_MASK:
125762306a36Sopenharmony_ci		tmp = (reg - R_028100_CB_COLOR0_MASK) / 4;
125862306a36Sopenharmony_ci		track->cb_color_mask[tmp] = radeon_get_ib_value(p, idx);
125962306a36Sopenharmony_ci		if (G_0280A0_TILE_MODE(track->cb_color_info[tmp])) {
126062306a36Sopenharmony_ci			track->cb_dirty = true;
126162306a36Sopenharmony_ci		}
126262306a36Sopenharmony_ci		break;
126362306a36Sopenharmony_ci	case CB_COLOR0_BASE:
126462306a36Sopenharmony_ci	case CB_COLOR1_BASE:
126562306a36Sopenharmony_ci	case CB_COLOR2_BASE:
126662306a36Sopenharmony_ci	case CB_COLOR3_BASE:
126762306a36Sopenharmony_ci	case CB_COLOR4_BASE:
126862306a36Sopenharmony_ci	case CB_COLOR5_BASE:
126962306a36Sopenharmony_ci	case CB_COLOR6_BASE:
127062306a36Sopenharmony_ci	case CB_COLOR7_BASE:
127162306a36Sopenharmony_ci		r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
127262306a36Sopenharmony_ci		if (r) {
127362306a36Sopenharmony_ci			dev_warn(p->dev, "bad SET_CONTEXT_REG "
127462306a36Sopenharmony_ci					"0x%04X\n", reg);
127562306a36Sopenharmony_ci			return -EINVAL;
127662306a36Sopenharmony_ci		}
127762306a36Sopenharmony_ci		tmp = (reg - CB_COLOR0_BASE) / 4;
127862306a36Sopenharmony_ci		track->cb_color_bo_offset[tmp] = (u64)radeon_get_ib_value(p, idx) << 8;
127962306a36Sopenharmony_ci		ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
128062306a36Sopenharmony_ci		track->cb_color_base_last[tmp] = ib[idx];
128162306a36Sopenharmony_ci		track->cb_color_bo[tmp] = reloc->robj;
128262306a36Sopenharmony_ci		track->cb_color_bo_mc[tmp] = reloc->gpu_offset;
128362306a36Sopenharmony_ci		track->cb_dirty = true;
128462306a36Sopenharmony_ci		break;
128562306a36Sopenharmony_ci	case DB_DEPTH_BASE:
128662306a36Sopenharmony_ci		r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
128762306a36Sopenharmony_ci		if (r) {
128862306a36Sopenharmony_ci			dev_warn(p->dev, "bad SET_CONTEXT_REG "
128962306a36Sopenharmony_ci					"0x%04X\n", reg);
129062306a36Sopenharmony_ci			return -EINVAL;
129162306a36Sopenharmony_ci		}
129262306a36Sopenharmony_ci		track->db_offset = radeon_get_ib_value(p, idx) << 8;
129362306a36Sopenharmony_ci		ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
129462306a36Sopenharmony_ci		track->db_bo = reloc->robj;
129562306a36Sopenharmony_ci		track->db_bo_mc = reloc->gpu_offset;
129662306a36Sopenharmony_ci		track->db_dirty = true;
129762306a36Sopenharmony_ci		break;
129862306a36Sopenharmony_ci	case DB_HTILE_DATA_BASE:
129962306a36Sopenharmony_ci		r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
130062306a36Sopenharmony_ci		if (r) {
130162306a36Sopenharmony_ci			dev_warn(p->dev, "bad SET_CONTEXT_REG "
130262306a36Sopenharmony_ci					"0x%04X\n", reg);
130362306a36Sopenharmony_ci			return -EINVAL;
130462306a36Sopenharmony_ci		}
130562306a36Sopenharmony_ci		track->htile_offset = (u64)radeon_get_ib_value(p, idx) << 8;
130662306a36Sopenharmony_ci		ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
130762306a36Sopenharmony_ci		track->htile_bo = reloc->robj;
130862306a36Sopenharmony_ci		track->db_dirty = true;
130962306a36Sopenharmony_ci		break;
131062306a36Sopenharmony_ci	case DB_HTILE_SURFACE:
131162306a36Sopenharmony_ci		track->htile_surface = radeon_get_ib_value(p, idx);
131262306a36Sopenharmony_ci		/* force 8x8 htile width and height */
131362306a36Sopenharmony_ci		ib[idx] |= 3;
131462306a36Sopenharmony_ci		track->db_dirty = true;
131562306a36Sopenharmony_ci		break;
131662306a36Sopenharmony_ci	case SQ_PGM_START_FS:
131762306a36Sopenharmony_ci	case SQ_PGM_START_ES:
131862306a36Sopenharmony_ci	case SQ_PGM_START_VS:
131962306a36Sopenharmony_ci	case SQ_PGM_START_GS:
132062306a36Sopenharmony_ci	case SQ_PGM_START_PS:
132162306a36Sopenharmony_ci	case SQ_ALU_CONST_CACHE_GS_0:
132262306a36Sopenharmony_ci	case SQ_ALU_CONST_CACHE_GS_1:
132362306a36Sopenharmony_ci	case SQ_ALU_CONST_CACHE_GS_2:
132462306a36Sopenharmony_ci	case SQ_ALU_CONST_CACHE_GS_3:
132562306a36Sopenharmony_ci	case SQ_ALU_CONST_CACHE_GS_4:
132662306a36Sopenharmony_ci	case SQ_ALU_CONST_CACHE_GS_5:
132762306a36Sopenharmony_ci	case SQ_ALU_CONST_CACHE_GS_6:
132862306a36Sopenharmony_ci	case SQ_ALU_CONST_CACHE_GS_7:
132962306a36Sopenharmony_ci	case SQ_ALU_CONST_CACHE_GS_8:
133062306a36Sopenharmony_ci	case SQ_ALU_CONST_CACHE_GS_9:
133162306a36Sopenharmony_ci	case SQ_ALU_CONST_CACHE_GS_10:
133262306a36Sopenharmony_ci	case SQ_ALU_CONST_CACHE_GS_11:
133362306a36Sopenharmony_ci	case SQ_ALU_CONST_CACHE_GS_12:
133462306a36Sopenharmony_ci	case SQ_ALU_CONST_CACHE_GS_13:
133562306a36Sopenharmony_ci	case SQ_ALU_CONST_CACHE_GS_14:
133662306a36Sopenharmony_ci	case SQ_ALU_CONST_CACHE_GS_15:
133762306a36Sopenharmony_ci	case SQ_ALU_CONST_CACHE_PS_0:
133862306a36Sopenharmony_ci	case SQ_ALU_CONST_CACHE_PS_1:
133962306a36Sopenharmony_ci	case SQ_ALU_CONST_CACHE_PS_2:
134062306a36Sopenharmony_ci	case SQ_ALU_CONST_CACHE_PS_3:
134162306a36Sopenharmony_ci	case SQ_ALU_CONST_CACHE_PS_4:
134262306a36Sopenharmony_ci	case SQ_ALU_CONST_CACHE_PS_5:
134362306a36Sopenharmony_ci	case SQ_ALU_CONST_CACHE_PS_6:
134462306a36Sopenharmony_ci	case SQ_ALU_CONST_CACHE_PS_7:
134562306a36Sopenharmony_ci	case SQ_ALU_CONST_CACHE_PS_8:
134662306a36Sopenharmony_ci	case SQ_ALU_CONST_CACHE_PS_9:
134762306a36Sopenharmony_ci	case SQ_ALU_CONST_CACHE_PS_10:
134862306a36Sopenharmony_ci	case SQ_ALU_CONST_CACHE_PS_11:
134962306a36Sopenharmony_ci	case SQ_ALU_CONST_CACHE_PS_12:
135062306a36Sopenharmony_ci	case SQ_ALU_CONST_CACHE_PS_13:
135162306a36Sopenharmony_ci	case SQ_ALU_CONST_CACHE_PS_14:
135262306a36Sopenharmony_ci	case SQ_ALU_CONST_CACHE_PS_15:
135362306a36Sopenharmony_ci	case SQ_ALU_CONST_CACHE_VS_0:
135462306a36Sopenharmony_ci	case SQ_ALU_CONST_CACHE_VS_1:
135562306a36Sopenharmony_ci	case SQ_ALU_CONST_CACHE_VS_2:
135662306a36Sopenharmony_ci	case SQ_ALU_CONST_CACHE_VS_3:
135762306a36Sopenharmony_ci	case SQ_ALU_CONST_CACHE_VS_4:
135862306a36Sopenharmony_ci	case SQ_ALU_CONST_CACHE_VS_5:
135962306a36Sopenharmony_ci	case SQ_ALU_CONST_CACHE_VS_6:
136062306a36Sopenharmony_ci	case SQ_ALU_CONST_CACHE_VS_7:
136162306a36Sopenharmony_ci	case SQ_ALU_CONST_CACHE_VS_8:
136262306a36Sopenharmony_ci	case SQ_ALU_CONST_CACHE_VS_9:
136362306a36Sopenharmony_ci	case SQ_ALU_CONST_CACHE_VS_10:
136462306a36Sopenharmony_ci	case SQ_ALU_CONST_CACHE_VS_11:
136562306a36Sopenharmony_ci	case SQ_ALU_CONST_CACHE_VS_12:
136662306a36Sopenharmony_ci	case SQ_ALU_CONST_CACHE_VS_13:
136762306a36Sopenharmony_ci	case SQ_ALU_CONST_CACHE_VS_14:
136862306a36Sopenharmony_ci	case SQ_ALU_CONST_CACHE_VS_15:
136962306a36Sopenharmony_ci		r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
137062306a36Sopenharmony_ci		if (r) {
137162306a36Sopenharmony_ci			dev_warn(p->dev, "bad SET_CONTEXT_REG "
137262306a36Sopenharmony_ci					"0x%04X\n", reg);
137362306a36Sopenharmony_ci			return -EINVAL;
137462306a36Sopenharmony_ci		}
137562306a36Sopenharmony_ci		ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
137662306a36Sopenharmony_ci		break;
137762306a36Sopenharmony_ci	case SX_MEMORY_EXPORT_BASE:
137862306a36Sopenharmony_ci		r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
137962306a36Sopenharmony_ci		if (r) {
138062306a36Sopenharmony_ci			dev_warn(p->dev, "bad SET_CONFIG_REG "
138162306a36Sopenharmony_ci					"0x%04X\n", reg);
138262306a36Sopenharmony_ci			return -EINVAL;
138362306a36Sopenharmony_ci		}
138462306a36Sopenharmony_ci		ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
138562306a36Sopenharmony_ci		break;
138662306a36Sopenharmony_ci	case SX_MISC:
138762306a36Sopenharmony_ci		track->sx_misc_kill_all_prims = (radeon_get_ib_value(p, idx) & 0x1) != 0;
138862306a36Sopenharmony_ci		break;
138962306a36Sopenharmony_ci	default:
139062306a36Sopenharmony_ci		dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
139162306a36Sopenharmony_ci		return -EINVAL;
139262306a36Sopenharmony_ci	}
139362306a36Sopenharmony_ci	return 0;
139462306a36Sopenharmony_ci}
139562306a36Sopenharmony_ci
139662306a36Sopenharmony_ciunsigned r600_mip_minify(unsigned size, unsigned level)
139762306a36Sopenharmony_ci{
139862306a36Sopenharmony_ci	unsigned val;
139962306a36Sopenharmony_ci
140062306a36Sopenharmony_ci	val = max(1U, size >> level);
140162306a36Sopenharmony_ci	if (level > 0)
140262306a36Sopenharmony_ci		val = roundup_pow_of_two(val);
140362306a36Sopenharmony_ci	return val;
140462306a36Sopenharmony_ci}
140562306a36Sopenharmony_ci
140662306a36Sopenharmony_cistatic void r600_texture_size(unsigned nfaces, unsigned blevel, unsigned llevel,
140762306a36Sopenharmony_ci			      unsigned w0, unsigned h0, unsigned d0, unsigned nsamples, unsigned format,
140862306a36Sopenharmony_ci			      unsigned block_align, unsigned height_align, unsigned base_align,
140962306a36Sopenharmony_ci			      unsigned *l0_size, unsigned *mipmap_size)
141062306a36Sopenharmony_ci{
141162306a36Sopenharmony_ci	unsigned offset, i, level;
141262306a36Sopenharmony_ci	unsigned width, height, depth, size;
141362306a36Sopenharmony_ci	unsigned blocksize;
141462306a36Sopenharmony_ci	unsigned nbx, nby;
141562306a36Sopenharmony_ci	unsigned nlevels = llevel - blevel + 1;
141662306a36Sopenharmony_ci
141762306a36Sopenharmony_ci	*l0_size = -1;
141862306a36Sopenharmony_ci	blocksize = r600_fmt_get_blocksize(format);
141962306a36Sopenharmony_ci
142062306a36Sopenharmony_ci	w0 = r600_mip_minify(w0, 0);
142162306a36Sopenharmony_ci	h0 = r600_mip_minify(h0, 0);
142262306a36Sopenharmony_ci	d0 = r600_mip_minify(d0, 0);
142362306a36Sopenharmony_ci	for(i = 0, offset = 0, level = blevel; i < nlevels; i++, level++) {
142462306a36Sopenharmony_ci		width = r600_mip_minify(w0, i);
142562306a36Sopenharmony_ci		nbx = r600_fmt_get_nblocksx(format, width);
142662306a36Sopenharmony_ci
142762306a36Sopenharmony_ci		nbx = round_up(nbx, block_align);
142862306a36Sopenharmony_ci
142962306a36Sopenharmony_ci		height = r600_mip_minify(h0, i);
143062306a36Sopenharmony_ci		nby = r600_fmt_get_nblocksy(format, height);
143162306a36Sopenharmony_ci		nby = round_up(nby, height_align);
143262306a36Sopenharmony_ci
143362306a36Sopenharmony_ci		depth = r600_mip_minify(d0, i);
143462306a36Sopenharmony_ci
143562306a36Sopenharmony_ci		size = nbx * nby * blocksize * nsamples;
143662306a36Sopenharmony_ci		if (nfaces)
143762306a36Sopenharmony_ci			size *= nfaces;
143862306a36Sopenharmony_ci		else
143962306a36Sopenharmony_ci			size *= depth;
144062306a36Sopenharmony_ci
144162306a36Sopenharmony_ci		if (i == 0)
144262306a36Sopenharmony_ci			*l0_size = size;
144362306a36Sopenharmony_ci
144462306a36Sopenharmony_ci		if (i == 0 || i == 1)
144562306a36Sopenharmony_ci			offset = round_up(offset, base_align);
144662306a36Sopenharmony_ci
144762306a36Sopenharmony_ci		offset += size;
144862306a36Sopenharmony_ci	}
144962306a36Sopenharmony_ci	*mipmap_size = offset;
145062306a36Sopenharmony_ci	if (llevel == 0)
145162306a36Sopenharmony_ci		*mipmap_size = *l0_size;
145262306a36Sopenharmony_ci	if (!blevel)
145362306a36Sopenharmony_ci		*mipmap_size -= *l0_size;
145462306a36Sopenharmony_ci}
145562306a36Sopenharmony_ci
145662306a36Sopenharmony_ci/**
145762306a36Sopenharmony_ci * r600_check_texture_resource() - check if register is authorized or not
145862306a36Sopenharmony_ci * @p: parser structure holding parsing context
145962306a36Sopenharmony_ci * @idx: index into the cs buffer
146062306a36Sopenharmony_ci * @texture: texture's bo structure
146162306a36Sopenharmony_ci * @mipmap: mipmap's bo structure
146262306a36Sopenharmony_ci * @base_offset: base offset (used for error checking)
146362306a36Sopenharmony_ci * @mip_offset: mip offset (used for error checking)
146462306a36Sopenharmony_ci * @tiling_flags: tiling flags
146562306a36Sopenharmony_ci *
146662306a36Sopenharmony_ci * This function will check that the resource has valid field and that
146762306a36Sopenharmony_ci * the texture and mipmap bo object are big enough to cover this resource.
146862306a36Sopenharmony_ci */
146962306a36Sopenharmony_cistatic int r600_check_texture_resource(struct radeon_cs_parser *p,  u32 idx,
147062306a36Sopenharmony_ci					      struct radeon_bo *texture,
147162306a36Sopenharmony_ci					      struct radeon_bo *mipmap,
147262306a36Sopenharmony_ci					      u64 base_offset,
147362306a36Sopenharmony_ci					      u64 mip_offset,
147462306a36Sopenharmony_ci					      u32 tiling_flags)
147562306a36Sopenharmony_ci{
147662306a36Sopenharmony_ci	struct r600_cs_track *track = p->track;
147762306a36Sopenharmony_ci	u32 dim, nfaces, llevel, blevel, w0, h0, d0;
147862306a36Sopenharmony_ci	u32 word0, word1, l0_size, mipmap_size, word2, word3, word4, word5;
147962306a36Sopenharmony_ci	u32 height_align, pitch, pitch_align, depth_align;
148062306a36Sopenharmony_ci	u32 barray, larray;
148162306a36Sopenharmony_ci	u64 base_align;
148262306a36Sopenharmony_ci	struct array_mode_checker array_check;
148362306a36Sopenharmony_ci	u32 format;
148462306a36Sopenharmony_ci	bool is_array;
148562306a36Sopenharmony_ci
148662306a36Sopenharmony_ci	/* on legacy kernel we don't perform advanced check */
148762306a36Sopenharmony_ci	if (p->rdev == NULL)
148862306a36Sopenharmony_ci		return 0;
148962306a36Sopenharmony_ci
149062306a36Sopenharmony_ci	/* convert to bytes */
149162306a36Sopenharmony_ci	base_offset <<= 8;
149262306a36Sopenharmony_ci	mip_offset <<= 8;
149362306a36Sopenharmony_ci
149462306a36Sopenharmony_ci	word0 = radeon_get_ib_value(p, idx + 0);
149562306a36Sopenharmony_ci	if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
149662306a36Sopenharmony_ci		if (tiling_flags & RADEON_TILING_MACRO)
149762306a36Sopenharmony_ci			word0 |= S_038000_TILE_MODE(V_038000_ARRAY_2D_TILED_THIN1);
149862306a36Sopenharmony_ci		else if (tiling_flags & RADEON_TILING_MICRO)
149962306a36Sopenharmony_ci			word0 |= S_038000_TILE_MODE(V_038000_ARRAY_1D_TILED_THIN1);
150062306a36Sopenharmony_ci	}
150162306a36Sopenharmony_ci	word1 = radeon_get_ib_value(p, idx + 1);
150262306a36Sopenharmony_ci	word2 = radeon_get_ib_value(p, idx + 2) << 8;
150362306a36Sopenharmony_ci	word3 = radeon_get_ib_value(p, idx + 3) << 8;
150462306a36Sopenharmony_ci	word4 = radeon_get_ib_value(p, idx + 4);
150562306a36Sopenharmony_ci	word5 = radeon_get_ib_value(p, idx + 5);
150662306a36Sopenharmony_ci	dim = G_038000_DIM(word0);
150762306a36Sopenharmony_ci	w0 = G_038000_TEX_WIDTH(word0) + 1;
150862306a36Sopenharmony_ci	pitch = (G_038000_PITCH(word0) + 1) * 8;
150962306a36Sopenharmony_ci	h0 = G_038004_TEX_HEIGHT(word1) + 1;
151062306a36Sopenharmony_ci	d0 = G_038004_TEX_DEPTH(word1);
151162306a36Sopenharmony_ci	format = G_038004_DATA_FORMAT(word1);
151262306a36Sopenharmony_ci	blevel = G_038010_BASE_LEVEL(word4);
151362306a36Sopenharmony_ci	llevel = G_038014_LAST_LEVEL(word5);
151462306a36Sopenharmony_ci	/* pitch in texels */
151562306a36Sopenharmony_ci	array_check.array_mode = G_038000_TILE_MODE(word0);
151662306a36Sopenharmony_ci	array_check.group_size = track->group_size;
151762306a36Sopenharmony_ci	array_check.nbanks = track->nbanks;
151862306a36Sopenharmony_ci	array_check.npipes = track->npipes;
151962306a36Sopenharmony_ci	array_check.nsamples = 1;
152062306a36Sopenharmony_ci	array_check.blocksize = r600_fmt_get_blocksize(format);
152162306a36Sopenharmony_ci	nfaces = 1;
152262306a36Sopenharmony_ci	is_array = false;
152362306a36Sopenharmony_ci	switch (dim) {
152462306a36Sopenharmony_ci	case V_038000_SQ_TEX_DIM_1D:
152562306a36Sopenharmony_ci	case V_038000_SQ_TEX_DIM_2D:
152662306a36Sopenharmony_ci	case V_038000_SQ_TEX_DIM_3D:
152762306a36Sopenharmony_ci		break;
152862306a36Sopenharmony_ci	case V_038000_SQ_TEX_DIM_CUBEMAP:
152962306a36Sopenharmony_ci		if (p->family >= CHIP_RV770)
153062306a36Sopenharmony_ci			nfaces = 8;
153162306a36Sopenharmony_ci		else
153262306a36Sopenharmony_ci			nfaces = 6;
153362306a36Sopenharmony_ci		break;
153462306a36Sopenharmony_ci	case V_038000_SQ_TEX_DIM_1D_ARRAY:
153562306a36Sopenharmony_ci	case V_038000_SQ_TEX_DIM_2D_ARRAY:
153662306a36Sopenharmony_ci		is_array = true;
153762306a36Sopenharmony_ci		break;
153862306a36Sopenharmony_ci	case V_038000_SQ_TEX_DIM_2D_ARRAY_MSAA:
153962306a36Sopenharmony_ci		is_array = true;
154062306a36Sopenharmony_ci		fallthrough;
154162306a36Sopenharmony_ci	case V_038000_SQ_TEX_DIM_2D_MSAA:
154262306a36Sopenharmony_ci		array_check.nsamples = 1 << llevel;
154362306a36Sopenharmony_ci		llevel = 0;
154462306a36Sopenharmony_ci		break;
154562306a36Sopenharmony_ci	default:
154662306a36Sopenharmony_ci		dev_warn(p->dev, "this kernel doesn't support %d texture dim\n", G_038000_DIM(word0));
154762306a36Sopenharmony_ci		return -EINVAL;
154862306a36Sopenharmony_ci	}
154962306a36Sopenharmony_ci	if (!r600_fmt_is_valid_texture(format, p->family)) {
155062306a36Sopenharmony_ci		dev_warn(p->dev, "%s:%d texture invalid format %d\n",
155162306a36Sopenharmony_ci			 __func__, __LINE__, format);
155262306a36Sopenharmony_ci		return -EINVAL;
155362306a36Sopenharmony_ci	}
155462306a36Sopenharmony_ci
155562306a36Sopenharmony_ci	if (r600_get_array_mode_alignment(&array_check,
155662306a36Sopenharmony_ci					  &pitch_align, &height_align, &depth_align, &base_align)) {
155762306a36Sopenharmony_ci		dev_warn(p->dev, "%s:%d tex array mode (%d) invalid\n",
155862306a36Sopenharmony_ci			 __func__, __LINE__, G_038000_TILE_MODE(word0));
155962306a36Sopenharmony_ci		return -EINVAL;
156062306a36Sopenharmony_ci	}
156162306a36Sopenharmony_ci
156262306a36Sopenharmony_ci	/* XXX check height as well... */
156362306a36Sopenharmony_ci
156462306a36Sopenharmony_ci	if (!IS_ALIGNED(pitch, pitch_align)) {
156562306a36Sopenharmony_ci		dev_warn(p->dev, "%s:%d tex pitch (%d, 0x%x, %d) invalid\n",
156662306a36Sopenharmony_ci			 __func__, __LINE__, pitch, pitch_align, G_038000_TILE_MODE(word0));
156762306a36Sopenharmony_ci		return -EINVAL;
156862306a36Sopenharmony_ci	}
156962306a36Sopenharmony_ci	if (!IS_ALIGNED(base_offset, base_align)) {
157062306a36Sopenharmony_ci		dev_warn(p->dev, "%s:%d tex base offset (0x%llx, 0x%llx, %d) invalid\n",
157162306a36Sopenharmony_ci			 __func__, __LINE__, base_offset, base_align, G_038000_TILE_MODE(word0));
157262306a36Sopenharmony_ci		return -EINVAL;
157362306a36Sopenharmony_ci	}
157462306a36Sopenharmony_ci	if (!IS_ALIGNED(mip_offset, base_align)) {
157562306a36Sopenharmony_ci		dev_warn(p->dev, "%s:%d tex mip offset (0x%llx, 0x%llx, %d) invalid\n",
157662306a36Sopenharmony_ci			 __func__, __LINE__, mip_offset, base_align, G_038000_TILE_MODE(word0));
157762306a36Sopenharmony_ci		return -EINVAL;
157862306a36Sopenharmony_ci	}
157962306a36Sopenharmony_ci
158062306a36Sopenharmony_ci	if (blevel > llevel) {
158162306a36Sopenharmony_ci		dev_warn(p->dev, "texture blevel %d > llevel %d\n",
158262306a36Sopenharmony_ci			 blevel, llevel);
158362306a36Sopenharmony_ci	}
158462306a36Sopenharmony_ci	if (is_array) {
158562306a36Sopenharmony_ci		barray = G_038014_BASE_ARRAY(word5);
158662306a36Sopenharmony_ci		larray = G_038014_LAST_ARRAY(word5);
158762306a36Sopenharmony_ci
158862306a36Sopenharmony_ci		nfaces = larray - barray + 1;
158962306a36Sopenharmony_ci	}
159062306a36Sopenharmony_ci	r600_texture_size(nfaces, blevel, llevel, w0, h0, d0, array_check.nsamples, format,
159162306a36Sopenharmony_ci			  pitch_align, height_align, base_align,
159262306a36Sopenharmony_ci			  &l0_size, &mipmap_size);
159362306a36Sopenharmony_ci	/* using get ib will give us the offset into the texture bo */
159462306a36Sopenharmony_ci	if ((l0_size + word2) > radeon_bo_size(texture)) {
159562306a36Sopenharmony_ci		dev_warn(p->dev, "texture bo too small ((%d %d) (%d %d) %d %d %d -> %d have %ld)\n",
159662306a36Sopenharmony_ci			 w0, h0, pitch_align, height_align,
159762306a36Sopenharmony_ci			 array_check.array_mode, format, word2,
159862306a36Sopenharmony_ci			 l0_size, radeon_bo_size(texture));
159962306a36Sopenharmony_ci		dev_warn(p->dev, "alignments %d %d %d %lld\n", pitch, pitch_align, height_align, base_align);
160062306a36Sopenharmony_ci		return -EINVAL;
160162306a36Sopenharmony_ci	}
160262306a36Sopenharmony_ci	/* using get ib will give us the offset into the mipmap bo */
160362306a36Sopenharmony_ci	if ((mipmap_size + word3) > radeon_bo_size(mipmap)) {
160462306a36Sopenharmony_ci		/*dev_warn(p->dev, "mipmap bo too small (%d %d %d %d %d %d -> %d have %ld)\n",
160562306a36Sopenharmony_ci		  w0, h0, format, blevel, nlevels, word3, mipmap_size, radeon_bo_size(texture));*/
160662306a36Sopenharmony_ci	}
160762306a36Sopenharmony_ci	return 0;
160862306a36Sopenharmony_ci}
160962306a36Sopenharmony_ci
161062306a36Sopenharmony_cistatic bool r600_is_safe_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
161162306a36Sopenharmony_ci{
161262306a36Sopenharmony_ci	u32 m, i;
161362306a36Sopenharmony_ci
161462306a36Sopenharmony_ci	i = (reg >> 7);
161562306a36Sopenharmony_ci	if (i >= ARRAY_SIZE(r600_reg_safe_bm)) {
161662306a36Sopenharmony_ci		dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
161762306a36Sopenharmony_ci		return false;
161862306a36Sopenharmony_ci	}
161962306a36Sopenharmony_ci	m = 1 << ((reg >> 2) & 31);
162062306a36Sopenharmony_ci	if (!(r600_reg_safe_bm[i] & m))
162162306a36Sopenharmony_ci		return true;
162262306a36Sopenharmony_ci	dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
162362306a36Sopenharmony_ci	return false;
162462306a36Sopenharmony_ci}
162562306a36Sopenharmony_ci
162662306a36Sopenharmony_cistatic int r600_packet3_check(struct radeon_cs_parser *p,
162762306a36Sopenharmony_ci				struct radeon_cs_packet *pkt)
162862306a36Sopenharmony_ci{
162962306a36Sopenharmony_ci	struct radeon_bo_list *reloc;
163062306a36Sopenharmony_ci	struct r600_cs_track *track;
163162306a36Sopenharmony_ci	volatile u32 *ib;
163262306a36Sopenharmony_ci	unsigned idx;
163362306a36Sopenharmony_ci	unsigned i;
163462306a36Sopenharmony_ci	unsigned start_reg, end_reg, reg;
163562306a36Sopenharmony_ci	int r;
163662306a36Sopenharmony_ci	u32 idx_value;
163762306a36Sopenharmony_ci
163862306a36Sopenharmony_ci	track = (struct r600_cs_track *)p->track;
163962306a36Sopenharmony_ci	ib = p->ib.ptr;
164062306a36Sopenharmony_ci	idx = pkt->idx + 1;
164162306a36Sopenharmony_ci	idx_value = radeon_get_ib_value(p, idx);
164262306a36Sopenharmony_ci
164362306a36Sopenharmony_ci	switch (pkt->opcode) {
164462306a36Sopenharmony_ci	case PACKET3_SET_PREDICATION:
164562306a36Sopenharmony_ci	{
164662306a36Sopenharmony_ci		int pred_op;
164762306a36Sopenharmony_ci		int tmp;
164862306a36Sopenharmony_ci		uint64_t offset;
164962306a36Sopenharmony_ci
165062306a36Sopenharmony_ci		if (pkt->count != 1) {
165162306a36Sopenharmony_ci			DRM_ERROR("bad SET PREDICATION\n");
165262306a36Sopenharmony_ci			return -EINVAL;
165362306a36Sopenharmony_ci		}
165462306a36Sopenharmony_ci
165562306a36Sopenharmony_ci		tmp = radeon_get_ib_value(p, idx + 1);
165662306a36Sopenharmony_ci		pred_op = (tmp >> 16) & 0x7;
165762306a36Sopenharmony_ci
165862306a36Sopenharmony_ci		/* for the clear predicate operation */
165962306a36Sopenharmony_ci		if (pred_op == 0)
166062306a36Sopenharmony_ci			return 0;
166162306a36Sopenharmony_ci
166262306a36Sopenharmony_ci		if (pred_op > 2) {
166362306a36Sopenharmony_ci			DRM_ERROR("bad SET PREDICATION operation %d\n", pred_op);
166462306a36Sopenharmony_ci			return -EINVAL;
166562306a36Sopenharmony_ci		}
166662306a36Sopenharmony_ci
166762306a36Sopenharmony_ci		r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
166862306a36Sopenharmony_ci		if (r) {
166962306a36Sopenharmony_ci			DRM_ERROR("bad SET PREDICATION\n");
167062306a36Sopenharmony_ci			return -EINVAL;
167162306a36Sopenharmony_ci		}
167262306a36Sopenharmony_ci
167362306a36Sopenharmony_ci		offset = reloc->gpu_offset +
167462306a36Sopenharmony_ci			 (idx_value & 0xfffffff0) +
167562306a36Sopenharmony_ci			 ((u64)(tmp & 0xff) << 32);
167662306a36Sopenharmony_ci
167762306a36Sopenharmony_ci		ib[idx + 0] = offset;
167862306a36Sopenharmony_ci		ib[idx + 1] = (tmp & 0xffffff00) | (upper_32_bits(offset) & 0xff);
167962306a36Sopenharmony_ci	}
168062306a36Sopenharmony_ci	break;
168162306a36Sopenharmony_ci
168262306a36Sopenharmony_ci	case PACKET3_START_3D_CMDBUF:
168362306a36Sopenharmony_ci		if (p->family >= CHIP_RV770 || pkt->count) {
168462306a36Sopenharmony_ci			DRM_ERROR("bad START_3D\n");
168562306a36Sopenharmony_ci			return -EINVAL;
168662306a36Sopenharmony_ci		}
168762306a36Sopenharmony_ci		break;
168862306a36Sopenharmony_ci	case PACKET3_CONTEXT_CONTROL:
168962306a36Sopenharmony_ci		if (pkt->count != 1) {
169062306a36Sopenharmony_ci			DRM_ERROR("bad CONTEXT_CONTROL\n");
169162306a36Sopenharmony_ci			return -EINVAL;
169262306a36Sopenharmony_ci		}
169362306a36Sopenharmony_ci		break;
169462306a36Sopenharmony_ci	case PACKET3_INDEX_TYPE:
169562306a36Sopenharmony_ci	case PACKET3_NUM_INSTANCES:
169662306a36Sopenharmony_ci		if (pkt->count) {
169762306a36Sopenharmony_ci			DRM_ERROR("bad INDEX_TYPE/NUM_INSTANCES\n");
169862306a36Sopenharmony_ci			return -EINVAL;
169962306a36Sopenharmony_ci		}
170062306a36Sopenharmony_ci		break;
170162306a36Sopenharmony_ci	case PACKET3_DRAW_INDEX:
170262306a36Sopenharmony_ci	{
170362306a36Sopenharmony_ci		uint64_t offset;
170462306a36Sopenharmony_ci		if (pkt->count != 3) {
170562306a36Sopenharmony_ci			DRM_ERROR("bad DRAW_INDEX\n");
170662306a36Sopenharmony_ci			return -EINVAL;
170762306a36Sopenharmony_ci		}
170862306a36Sopenharmony_ci		r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
170962306a36Sopenharmony_ci		if (r) {
171062306a36Sopenharmony_ci			DRM_ERROR("bad DRAW_INDEX\n");
171162306a36Sopenharmony_ci			return -EINVAL;
171262306a36Sopenharmony_ci		}
171362306a36Sopenharmony_ci
171462306a36Sopenharmony_ci		offset = reloc->gpu_offset +
171562306a36Sopenharmony_ci			 idx_value +
171662306a36Sopenharmony_ci			 ((u64)(radeon_get_ib_value(p, idx+1) & 0xff) << 32);
171762306a36Sopenharmony_ci
171862306a36Sopenharmony_ci		ib[idx+0] = offset;
171962306a36Sopenharmony_ci		ib[idx+1] = upper_32_bits(offset) & 0xff;
172062306a36Sopenharmony_ci
172162306a36Sopenharmony_ci		r = r600_cs_track_check(p);
172262306a36Sopenharmony_ci		if (r) {
172362306a36Sopenharmony_ci			dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
172462306a36Sopenharmony_ci			return r;
172562306a36Sopenharmony_ci		}
172662306a36Sopenharmony_ci		break;
172762306a36Sopenharmony_ci	}
172862306a36Sopenharmony_ci	case PACKET3_DRAW_INDEX_AUTO:
172962306a36Sopenharmony_ci		if (pkt->count != 1) {
173062306a36Sopenharmony_ci			DRM_ERROR("bad DRAW_INDEX_AUTO\n");
173162306a36Sopenharmony_ci			return -EINVAL;
173262306a36Sopenharmony_ci		}
173362306a36Sopenharmony_ci		r = r600_cs_track_check(p);
173462306a36Sopenharmony_ci		if (r) {
173562306a36Sopenharmony_ci			dev_warn(p->dev, "%s:%d invalid cmd stream %d\n", __func__, __LINE__, idx);
173662306a36Sopenharmony_ci			return r;
173762306a36Sopenharmony_ci		}
173862306a36Sopenharmony_ci		break;
173962306a36Sopenharmony_ci	case PACKET3_DRAW_INDEX_IMMD_BE:
174062306a36Sopenharmony_ci	case PACKET3_DRAW_INDEX_IMMD:
174162306a36Sopenharmony_ci		if (pkt->count < 2) {
174262306a36Sopenharmony_ci			DRM_ERROR("bad DRAW_INDEX_IMMD\n");
174362306a36Sopenharmony_ci			return -EINVAL;
174462306a36Sopenharmony_ci		}
174562306a36Sopenharmony_ci		r = r600_cs_track_check(p);
174662306a36Sopenharmony_ci		if (r) {
174762306a36Sopenharmony_ci			dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__);
174862306a36Sopenharmony_ci			return r;
174962306a36Sopenharmony_ci		}
175062306a36Sopenharmony_ci		break;
175162306a36Sopenharmony_ci	case PACKET3_WAIT_REG_MEM:
175262306a36Sopenharmony_ci		if (pkt->count != 5) {
175362306a36Sopenharmony_ci			DRM_ERROR("bad WAIT_REG_MEM\n");
175462306a36Sopenharmony_ci			return -EINVAL;
175562306a36Sopenharmony_ci		}
175662306a36Sopenharmony_ci		/* bit 4 is reg (0) or mem (1) */
175762306a36Sopenharmony_ci		if (idx_value & 0x10) {
175862306a36Sopenharmony_ci			uint64_t offset;
175962306a36Sopenharmony_ci
176062306a36Sopenharmony_ci			r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
176162306a36Sopenharmony_ci			if (r) {
176262306a36Sopenharmony_ci				DRM_ERROR("bad WAIT_REG_MEM\n");
176362306a36Sopenharmony_ci				return -EINVAL;
176462306a36Sopenharmony_ci			}
176562306a36Sopenharmony_ci
176662306a36Sopenharmony_ci			offset = reloc->gpu_offset +
176762306a36Sopenharmony_ci				 (radeon_get_ib_value(p, idx+1) & 0xfffffff0) +
176862306a36Sopenharmony_ci				 ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32);
176962306a36Sopenharmony_ci
177062306a36Sopenharmony_ci			ib[idx+1] = (ib[idx+1] & 0x3) | (offset & 0xfffffff0);
177162306a36Sopenharmony_ci			ib[idx+2] = upper_32_bits(offset) & 0xff;
177262306a36Sopenharmony_ci		} else if (idx_value & 0x100) {
177362306a36Sopenharmony_ci			DRM_ERROR("cannot use PFP on REG wait\n");
177462306a36Sopenharmony_ci			return -EINVAL;
177562306a36Sopenharmony_ci		}
177662306a36Sopenharmony_ci		break;
177762306a36Sopenharmony_ci	case PACKET3_CP_DMA:
177862306a36Sopenharmony_ci	{
177962306a36Sopenharmony_ci		u32 command, size;
178062306a36Sopenharmony_ci		u64 offset, tmp;
178162306a36Sopenharmony_ci		if (pkt->count != 4) {
178262306a36Sopenharmony_ci			DRM_ERROR("bad CP DMA\n");
178362306a36Sopenharmony_ci			return -EINVAL;
178462306a36Sopenharmony_ci		}
178562306a36Sopenharmony_ci		command = radeon_get_ib_value(p, idx+4);
178662306a36Sopenharmony_ci		size = command & 0x1fffff;
178762306a36Sopenharmony_ci		if (command & PACKET3_CP_DMA_CMD_SAS) {
178862306a36Sopenharmony_ci			/* src address space is register */
178962306a36Sopenharmony_ci			DRM_ERROR("CP DMA SAS not supported\n");
179062306a36Sopenharmony_ci			return -EINVAL;
179162306a36Sopenharmony_ci		} else {
179262306a36Sopenharmony_ci			if (command & PACKET3_CP_DMA_CMD_SAIC) {
179362306a36Sopenharmony_ci				DRM_ERROR("CP DMA SAIC only supported for registers\n");
179462306a36Sopenharmony_ci				return -EINVAL;
179562306a36Sopenharmony_ci			}
179662306a36Sopenharmony_ci			/* src address space is memory */
179762306a36Sopenharmony_ci			r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
179862306a36Sopenharmony_ci			if (r) {
179962306a36Sopenharmony_ci				DRM_ERROR("bad CP DMA SRC\n");
180062306a36Sopenharmony_ci				return -EINVAL;
180162306a36Sopenharmony_ci			}
180262306a36Sopenharmony_ci
180362306a36Sopenharmony_ci			tmp = radeon_get_ib_value(p, idx) +
180462306a36Sopenharmony_ci				((u64)(radeon_get_ib_value(p, idx+1) & 0xff) << 32);
180562306a36Sopenharmony_ci
180662306a36Sopenharmony_ci			offset = reloc->gpu_offset + tmp;
180762306a36Sopenharmony_ci
180862306a36Sopenharmony_ci			if ((tmp + size) > radeon_bo_size(reloc->robj)) {
180962306a36Sopenharmony_ci				dev_warn(p->dev, "CP DMA src buffer too small (%llu %lu)\n",
181062306a36Sopenharmony_ci					 tmp + size, radeon_bo_size(reloc->robj));
181162306a36Sopenharmony_ci				return -EINVAL;
181262306a36Sopenharmony_ci			}
181362306a36Sopenharmony_ci
181462306a36Sopenharmony_ci			ib[idx] = offset;
181562306a36Sopenharmony_ci			ib[idx+1] = (ib[idx+1] & 0xffffff00) | (upper_32_bits(offset) & 0xff);
181662306a36Sopenharmony_ci		}
181762306a36Sopenharmony_ci		if (command & PACKET3_CP_DMA_CMD_DAS) {
181862306a36Sopenharmony_ci			/* dst address space is register */
181962306a36Sopenharmony_ci			DRM_ERROR("CP DMA DAS not supported\n");
182062306a36Sopenharmony_ci			return -EINVAL;
182162306a36Sopenharmony_ci		} else {
182262306a36Sopenharmony_ci			/* dst address space is memory */
182362306a36Sopenharmony_ci			if (command & PACKET3_CP_DMA_CMD_DAIC) {
182462306a36Sopenharmony_ci				DRM_ERROR("CP DMA DAIC only supported for registers\n");
182562306a36Sopenharmony_ci				return -EINVAL;
182662306a36Sopenharmony_ci			}
182762306a36Sopenharmony_ci			r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
182862306a36Sopenharmony_ci			if (r) {
182962306a36Sopenharmony_ci				DRM_ERROR("bad CP DMA DST\n");
183062306a36Sopenharmony_ci				return -EINVAL;
183162306a36Sopenharmony_ci			}
183262306a36Sopenharmony_ci
183362306a36Sopenharmony_ci			tmp = radeon_get_ib_value(p, idx+2) +
183462306a36Sopenharmony_ci				((u64)(radeon_get_ib_value(p, idx+3) & 0xff) << 32);
183562306a36Sopenharmony_ci
183662306a36Sopenharmony_ci			offset = reloc->gpu_offset + tmp;
183762306a36Sopenharmony_ci
183862306a36Sopenharmony_ci			if ((tmp + size) > radeon_bo_size(reloc->robj)) {
183962306a36Sopenharmony_ci				dev_warn(p->dev, "CP DMA dst buffer too small (%llu %lu)\n",
184062306a36Sopenharmony_ci					 tmp + size, radeon_bo_size(reloc->robj));
184162306a36Sopenharmony_ci				return -EINVAL;
184262306a36Sopenharmony_ci			}
184362306a36Sopenharmony_ci
184462306a36Sopenharmony_ci			ib[idx+2] = offset;
184562306a36Sopenharmony_ci			ib[idx+3] = upper_32_bits(offset) & 0xff;
184662306a36Sopenharmony_ci		}
184762306a36Sopenharmony_ci		break;
184862306a36Sopenharmony_ci	}
184962306a36Sopenharmony_ci	case PACKET3_SURFACE_SYNC:
185062306a36Sopenharmony_ci		if (pkt->count != 3) {
185162306a36Sopenharmony_ci			DRM_ERROR("bad SURFACE_SYNC\n");
185262306a36Sopenharmony_ci			return -EINVAL;
185362306a36Sopenharmony_ci		}
185462306a36Sopenharmony_ci		/* 0xffffffff/0x0 is flush all cache flag */
185562306a36Sopenharmony_ci		if (radeon_get_ib_value(p, idx + 1) != 0xffffffff ||
185662306a36Sopenharmony_ci		    radeon_get_ib_value(p, idx + 2) != 0) {
185762306a36Sopenharmony_ci			r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
185862306a36Sopenharmony_ci			if (r) {
185962306a36Sopenharmony_ci				DRM_ERROR("bad SURFACE_SYNC\n");
186062306a36Sopenharmony_ci				return -EINVAL;
186162306a36Sopenharmony_ci			}
186262306a36Sopenharmony_ci			ib[idx+2] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
186362306a36Sopenharmony_ci		}
186462306a36Sopenharmony_ci		break;
186562306a36Sopenharmony_ci	case PACKET3_EVENT_WRITE:
186662306a36Sopenharmony_ci		if (pkt->count != 2 && pkt->count != 0) {
186762306a36Sopenharmony_ci			DRM_ERROR("bad EVENT_WRITE\n");
186862306a36Sopenharmony_ci			return -EINVAL;
186962306a36Sopenharmony_ci		}
187062306a36Sopenharmony_ci		if (pkt->count) {
187162306a36Sopenharmony_ci			uint64_t offset;
187262306a36Sopenharmony_ci
187362306a36Sopenharmony_ci			r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
187462306a36Sopenharmony_ci			if (r) {
187562306a36Sopenharmony_ci				DRM_ERROR("bad EVENT_WRITE\n");
187662306a36Sopenharmony_ci				return -EINVAL;
187762306a36Sopenharmony_ci			}
187862306a36Sopenharmony_ci			offset = reloc->gpu_offset +
187962306a36Sopenharmony_ci				 (radeon_get_ib_value(p, idx+1) & 0xfffffff8) +
188062306a36Sopenharmony_ci				 ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32);
188162306a36Sopenharmony_ci
188262306a36Sopenharmony_ci			ib[idx+1] = offset & 0xfffffff8;
188362306a36Sopenharmony_ci			ib[idx+2] = upper_32_bits(offset) & 0xff;
188462306a36Sopenharmony_ci		}
188562306a36Sopenharmony_ci		break;
188662306a36Sopenharmony_ci	case PACKET3_EVENT_WRITE_EOP:
188762306a36Sopenharmony_ci	{
188862306a36Sopenharmony_ci		uint64_t offset;
188962306a36Sopenharmony_ci
189062306a36Sopenharmony_ci		if (pkt->count != 4) {
189162306a36Sopenharmony_ci			DRM_ERROR("bad EVENT_WRITE_EOP\n");
189262306a36Sopenharmony_ci			return -EINVAL;
189362306a36Sopenharmony_ci		}
189462306a36Sopenharmony_ci		r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
189562306a36Sopenharmony_ci		if (r) {
189662306a36Sopenharmony_ci			DRM_ERROR("bad EVENT_WRITE\n");
189762306a36Sopenharmony_ci			return -EINVAL;
189862306a36Sopenharmony_ci		}
189962306a36Sopenharmony_ci
190062306a36Sopenharmony_ci		offset = reloc->gpu_offset +
190162306a36Sopenharmony_ci			 (radeon_get_ib_value(p, idx+1) & 0xfffffffc) +
190262306a36Sopenharmony_ci			 ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32);
190362306a36Sopenharmony_ci
190462306a36Sopenharmony_ci		ib[idx+1] = offset & 0xfffffffc;
190562306a36Sopenharmony_ci		ib[idx+2] = (ib[idx+2] & 0xffffff00) | (upper_32_bits(offset) & 0xff);
190662306a36Sopenharmony_ci		break;
190762306a36Sopenharmony_ci	}
190862306a36Sopenharmony_ci	case PACKET3_SET_CONFIG_REG:
190962306a36Sopenharmony_ci		start_reg = (idx_value << 2) + PACKET3_SET_CONFIG_REG_OFFSET;
191062306a36Sopenharmony_ci		end_reg = 4 * pkt->count + start_reg - 4;
191162306a36Sopenharmony_ci		if ((start_reg < PACKET3_SET_CONFIG_REG_OFFSET) ||
191262306a36Sopenharmony_ci		    (start_reg >= PACKET3_SET_CONFIG_REG_END) ||
191362306a36Sopenharmony_ci		    (end_reg >= PACKET3_SET_CONFIG_REG_END)) {
191462306a36Sopenharmony_ci			DRM_ERROR("bad PACKET3_SET_CONFIG_REG\n");
191562306a36Sopenharmony_ci			return -EINVAL;
191662306a36Sopenharmony_ci		}
191762306a36Sopenharmony_ci		for (i = 0; i < pkt->count; i++) {
191862306a36Sopenharmony_ci			reg = start_reg + (4 * i);
191962306a36Sopenharmony_ci			r = r600_cs_check_reg(p, reg, idx+1+i);
192062306a36Sopenharmony_ci			if (r)
192162306a36Sopenharmony_ci				return r;
192262306a36Sopenharmony_ci		}
192362306a36Sopenharmony_ci		break;
192462306a36Sopenharmony_ci	case PACKET3_SET_CONTEXT_REG:
192562306a36Sopenharmony_ci		start_reg = (idx_value << 2) + PACKET3_SET_CONTEXT_REG_OFFSET;
192662306a36Sopenharmony_ci		end_reg = 4 * pkt->count + start_reg - 4;
192762306a36Sopenharmony_ci		if ((start_reg < PACKET3_SET_CONTEXT_REG_OFFSET) ||
192862306a36Sopenharmony_ci		    (start_reg >= PACKET3_SET_CONTEXT_REG_END) ||
192962306a36Sopenharmony_ci		    (end_reg >= PACKET3_SET_CONTEXT_REG_END)) {
193062306a36Sopenharmony_ci			DRM_ERROR("bad PACKET3_SET_CONTEXT_REG\n");
193162306a36Sopenharmony_ci			return -EINVAL;
193262306a36Sopenharmony_ci		}
193362306a36Sopenharmony_ci		for (i = 0; i < pkt->count; i++) {
193462306a36Sopenharmony_ci			reg = start_reg + (4 * i);
193562306a36Sopenharmony_ci			r = r600_cs_check_reg(p, reg, idx+1+i);
193662306a36Sopenharmony_ci			if (r)
193762306a36Sopenharmony_ci				return r;
193862306a36Sopenharmony_ci		}
193962306a36Sopenharmony_ci		break;
194062306a36Sopenharmony_ci	case PACKET3_SET_RESOURCE:
194162306a36Sopenharmony_ci		if (pkt->count % 7) {
194262306a36Sopenharmony_ci			DRM_ERROR("bad SET_RESOURCE\n");
194362306a36Sopenharmony_ci			return -EINVAL;
194462306a36Sopenharmony_ci		}
194562306a36Sopenharmony_ci		start_reg = (idx_value << 2) + PACKET3_SET_RESOURCE_OFFSET;
194662306a36Sopenharmony_ci		end_reg = 4 * pkt->count + start_reg - 4;
194762306a36Sopenharmony_ci		if ((start_reg < PACKET3_SET_RESOURCE_OFFSET) ||
194862306a36Sopenharmony_ci		    (start_reg >= PACKET3_SET_RESOURCE_END) ||
194962306a36Sopenharmony_ci		    (end_reg >= PACKET3_SET_RESOURCE_END)) {
195062306a36Sopenharmony_ci			DRM_ERROR("bad SET_RESOURCE\n");
195162306a36Sopenharmony_ci			return -EINVAL;
195262306a36Sopenharmony_ci		}
195362306a36Sopenharmony_ci		for (i = 0; i < (pkt->count / 7); i++) {
195462306a36Sopenharmony_ci			struct radeon_bo *texture, *mipmap;
195562306a36Sopenharmony_ci			u32 size, offset, base_offset, mip_offset;
195662306a36Sopenharmony_ci
195762306a36Sopenharmony_ci			switch (G__SQ_VTX_CONSTANT_TYPE(radeon_get_ib_value(p, idx+(i*7)+6+1))) {
195862306a36Sopenharmony_ci			case SQ_TEX_VTX_VALID_TEXTURE:
195962306a36Sopenharmony_ci				/* tex base */
196062306a36Sopenharmony_ci				r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
196162306a36Sopenharmony_ci				if (r) {
196262306a36Sopenharmony_ci					DRM_ERROR("bad SET_RESOURCE\n");
196362306a36Sopenharmony_ci					return -EINVAL;
196462306a36Sopenharmony_ci				}
196562306a36Sopenharmony_ci				base_offset = (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
196662306a36Sopenharmony_ci				if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) {
196762306a36Sopenharmony_ci					if (reloc->tiling_flags & RADEON_TILING_MACRO)
196862306a36Sopenharmony_ci						ib[idx+1+(i*7)+0] |= S_038000_TILE_MODE(V_038000_ARRAY_2D_TILED_THIN1);
196962306a36Sopenharmony_ci					else if (reloc->tiling_flags & RADEON_TILING_MICRO)
197062306a36Sopenharmony_ci						ib[idx+1+(i*7)+0] |= S_038000_TILE_MODE(V_038000_ARRAY_1D_TILED_THIN1);
197162306a36Sopenharmony_ci				}
197262306a36Sopenharmony_ci				texture = reloc->robj;
197362306a36Sopenharmony_ci				/* tex mip base */
197462306a36Sopenharmony_ci				r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
197562306a36Sopenharmony_ci				if (r) {
197662306a36Sopenharmony_ci					DRM_ERROR("bad SET_RESOURCE\n");
197762306a36Sopenharmony_ci					return -EINVAL;
197862306a36Sopenharmony_ci				}
197962306a36Sopenharmony_ci				mip_offset = (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
198062306a36Sopenharmony_ci				mipmap = reloc->robj;
198162306a36Sopenharmony_ci				r = r600_check_texture_resource(p,  idx+(i*7)+1,
198262306a36Sopenharmony_ci								texture, mipmap,
198362306a36Sopenharmony_ci								base_offset + radeon_get_ib_value(p, idx+1+(i*7)+2),
198462306a36Sopenharmony_ci								mip_offset + radeon_get_ib_value(p, idx+1+(i*7)+3),
198562306a36Sopenharmony_ci								reloc->tiling_flags);
198662306a36Sopenharmony_ci				if (r)
198762306a36Sopenharmony_ci					return r;
198862306a36Sopenharmony_ci				ib[idx+1+(i*7)+2] += base_offset;
198962306a36Sopenharmony_ci				ib[idx+1+(i*7)+3] += mip_offset;
199062306a36Sopenharmony_ci				break;
199162306a36Sopenharmony_ci			case SQ_TEX_VTX_VALID_BUFFER:
199262306a36Sopenharmony_ci			{
199362306a36Sopenharmony_ci				uint64_t offset64;
199462306a36Sopenharmony_ci				/* vtx base */
199562306a36Sopenharmony_ci				r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
199662306a36Sopenharmony_ci				if (r) {
199762306a36Sopenharmony_ci					DRM_ERROR("bad SET_RESOURCE\n");
199862306a36Sopenharmony_ci					return -EINVAL;
199962306a36Sopenharmony_ci				}
200062306a36Sopenharmony_ci				offset = radeon_get_ib_value(p, idx+1+(i*7)+0);
200162306a36Sopenharmony_ci				size = radeon_get_ib_value(p, idx+1+(i*7)+1) + 1;
200262306a36Sopenharmony_ci				if (p->rdev && (size + offset) > radeon_bo_size(reloc->robj)) {
200362306a36Sopenharmony_ci					/* force size to size of the buffer */
200462306a36Sopenharmony_ci					dev_warn(p->dev, "vbo resource seems too big (%d) for the bo (%ld)\n",
200562306a36Sopenharmony_ci						 size + offset, radeon_bo_size(reloc->robj));
200662306a36Sopenharmony_ci					ib[idx+1+(i*7)+1] = radeon_bo_size(reloc->robj) - offset;
200762306a36Sopenharmony_ci				}
200862306a36Sopenharmony_ci
200962306a36Sopenharmony_ci				offset64 = reloc->gpu_offset + offset;
201062306a36Sopenharmony_ci				ib[idx+1+(i*8)+0] = offset64;
201162306a36Sopenharmony_ci				ib[idx+1+(i*8)+2] = (ib[idx+1+(i*8)+2] & 0xffffff00) |
201262306a36Sopenharmony_ci						    (upper_32_bits(offset64) & 0xff);
201362306a36Sopenharmony_ci				break;
201462306a36Sopenharmony_ci			}
201562306a36Sopenharmony_ci			case SQ_TEX_VTX_INVALID_TEXTURE:
201662306a36Sopenharmony_ci			case SQ_TEX_VTX_INVALID_BUFFER:
201762306a36Sopenharmony_ci			default:
201862306a36Sopenharmony_ci				DRM_ERROR("bad SET_RESOURCE\n");
201962306a36Sopenharmony_ci				return -EINVAL;
202062306a36Sopenharmony_ci			}
202162306a36Sopenharmony_ci		}
202262306a36Sopenharmony_ci		break;
202362306a36Sopenharmony_ci	case PACKET3_SET_ALU_CONST:
202462306a36Sopenharmony_ci		if (track->sq_config & DX9_CONSTS) {
202562306a36Sopenharmony_ci			start_reg = (idx_value << 2) + PACKET3_SET_ALU_CONST_OFFSET;
202662306a36Sopenharmony_ci			end_reg = 4 * pkt->count + start_reg - 4;
202762306a36Sopenharmony_ci			if ((start_reg < PACKET3_SET_ALU_CONST_OFFSET) ||
202862306a36Sopenharmony_ci			    (start_reg >= PACKET3_SET_ALU_CONST_END) ||
202962306a36Sopenharmony_ci			    (end_reg >= PACKET3_SET_ALU_CONST_END)) {
203062306a36Sopenharmony_ci				DRM_ERROR("bad SET_ALU_CONST\n");
203162306a36Sopenharmony_ci				return -EINVAL;
203262306a36Sopenharmony_ci			}
203362306a36Sopenharmony_ci		}
203462306a36Sopenharmony_ci		break;
203562306a36Sopenharmony_ci	case PACKET3_SET_BOOL_CONST:
203662306a36Sopenharmony_ci		start_reg = (idx_value << 2) + PACKET3_SET_BOOL_CONST_OFFSET;
203762306a36Sopenharmony_ci		end_reg = 4 * pkt->count + start_reg - 4;
203862306a36Sopenharmony_ci		if ((start_reg < PACKET3_SET_BOOL_CONST_OFFSET) ||
203962306a36Sopenharmony_ci		    (start_reg >= PACKET3_SET_BOOL_CONST_END) ||
204062306a36Sopenharmony_ci		    (end_reg >= PACKET3_SET_BOOL_CONST_END)) {
204162306a36Sopenharmony_ci			DRM_ERROR("bad SET_BOOL_CONST\n");
204262306a36Sopenharmony_ci			return -EINVAL;
204362306a36Sopenharmony_ci		}
204462306a36Sopenharmony_ci		break;
204562306a36Sopenharmony_ci	case PACKET3_SET_LOOP_CONST:
204662306a36Sopenharmony_ci		start_reg = (idx_value << 2) + PACKET3_SET_LOOP_CONST_OFFSET;
204762306a36Sopenharmony_ci		end_reg = 4 * pkt->count + start_reg - 4;
204862306a36Sopenharmony_ci		if ((start_reg < PACKET3_SET_LOOP_CONST_OFFSET) ||
204962306a36Sopenharmony_ci		    (start_reg >= PACKET3_SET_LOOP_CONST_END) ||
205062306a36Sopenharmony_ci		    (end_reg >= PACKET3_SET_LOOP_CONST_END)) {
205162306a36Sopenharmony_ci			DRM_ERROR("bad SET_LOOP_CONST\n");
205262306a36Sopenharmony_ci			return -EINVAL;
205362306a36Sopenharmony_ci		}
205462306a36Sopenharmony_ci		break;
205562306a36Sopenharmony_ci	case PACKET3_SET_CTL_CONST:
205662306a36Sopenharmony_ci		start_reg = (idx_value << 2) + PACKET3_SET_CTL_CONST_OFFSET;
205762306a36Sopenharmony_ci		end_reg = 4 * pkt->count + start_reg - 4;
205862306a36Sopenharmony_ci		if ((start_reg < PACKET3_SET_CTL_CONST_OFFSET) ||
205962306a36Sopenharmony_ci		    (start_reg >= PACKET3_SET_CTL_CONST_END) ||
206062306a36Sopenharmony_ci		    (end_reg >= PACKET3_SET_CTL_CONST_END)) {
206162306a36Sopenharmony_ci			DRM_ERROR("bad SET_CTL_CONST\n");
206262306a36Sopenharmony_ci			return -EINVAL;
206362306a36Sopenharmony_ci		}
206462306a36Sopenharmony_ci		break;
206562306a36Sopenharmony_ci	case PACKET3_SET_SAMPLER:
206662306a36Sopenharmony_ci		if (pkt->count % 3) {
206762306a36Sopenharmony_ci			DRM_ERROR("bad SET_SAMPLER\n");
206862306a36Sopenharmony_ci			return -EINVAL;
206962306a36Sopenharmony_ci		}
207062306a36Sopenharmony_ci		start_reg = (idx_value << 2) + PACKET3_SET_SAMPLER_OFFSET;
207162306a36Sopenharmony_ci		end_reg = 4 * pkt->count + start_reg - 4;
207262306a36Sopenharmony_ci		if ((start_reg < PACKET3_SET_SAMPLER_OFFSET) ||
207362306a36Sopenharmony_ci		    (start_reg >= PACKET3_SET_SAMPLER_END) ||
207462306a36Sopenharmony_ci		    (end_reg >= PACKET3_SET_SAMPLER_END)) {
207562306a36Sopenharmony_ci			DRM_ERROR("bad SET_SAMPLER\n");
207662306a36Sopenharmony_ci			return -EINVAL;
207762306a36Sopenharmony_ci		}
207862306a36Sopenharmony_ci		break;
207962306a36Sopenharmony_ci	case PACKET3_STRMOUT_BASE_UPDATE:
208062306a36Sopenharmony_ci		/* RS780 and RS880 also need this */
208162306a36Sopenharmony_ci		if (p->family < CHIP_RS780) {
208262306a36Sopenharmony_ci			DRM_ERROR("STRMOUT_BASE_UPDATE only supported on 7xx\n");
208362306a36Sopenharmony_ci			return -EINVAL;
208462306a36Sopenharmony_ci		}
208562306a36Sopenharmony_ci		if (pkt->count != 1) {
208662306a36Sopenharmony_ci			DRM_ERROR("bad STRMOUT_BASE_UPDATE packet count\n");
208762306a36Sopenharmony_ci			return -EINVAL;
208862306a36Sopenharmony_ci		}
208962306a36Sopenharmony_ci		if (idx_value > 3) {
209062306a36Sopenharmony_ci			DRM_ERROR("bad STRMOUT_BASE_UPDATE index\n");
209162306a36Sopenharmony_ci			return -EINVAL;
209262306a36Sopenharmony_ci		}
209362306a36Sopenharmony_ci		{
209462306a36Sopenharmony_ci			u64 offset;
209562306a36Sopenharmony_ci
209662306a36Sopenharmony_ci			r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
209762306a36Sopenharmony_ci			if (r) {
209862306a36Sopenharmony_ci				DRM_ERROR("bad STRMOUT_BASE_UPDATE reloc\n");
209962306a36Sopenharmony_ci				return -EINVAL;
210062306a36Sopenharmony_ci			}
210162306a36Sopenharmony_ci
210262306a36Sopenharmony_ci			if (reloc->robj != track->vgt_strmout_bo[idx_value]) {
210362306a36Sopenharmony_ci				DRM_ERROR("bad STRMOUT_BASE_UPDATE, bo does not match\n");
210462306a36Sopenharmony_ci				return -EINVAL;
210562306a36Sopenharmony_ci			}
210662306a36Sopenharmony_ci
210762306a36Sopenharmony_ci			offset = radeon_get_ib_value(p, idx+1) << 8;
210862306a36Sopenharmony_ci			if (offset != track->vgt_strmout_bo_offset[idx_value]) {
210962306a36Sopenharmony_ci				DRM_ERROR("bad STRMOUT_BASE_UPDATE, bo offset does not match: 0x%llx, 0x%x\n",
211062306a36Sopenharmony_ci					  offset, track->vgt_strmout_bo_offset[idx_value]);
211162306a36Sopenharmony_ci				return -EINVAL;
211262306a36Sopenharmony_ci			}
211362306a36Sopenharmony_ci
211462306a36Sopenharmony_ci			if ((offset + 4) > radeon_bo_size(reloc->robj)) {
211562306a36Sopenharmony_ci				DRM_ERROR("bad STRMOUT_BASE_UPDATE bo too small: 0x%llx, 0x%lx\n",
211662306a36Sopenharmony_ci					  offset + 4, radeon_bo_size(reloc->robj));
211762306a36Sopenharmony_ci				return -EINVAL;
211862306a36Sopenharmony_ci			}
211962306a36Sopenharmony_ci			ib[idx+1] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff);
212062306a36Sopenharmony_ci		}
212162306a36Sopenharmony_ci		break;
212262306a36Sopenharmony_ci	case PACKET3_SURFACE_BASE_UPDATE:
212362306a36Sopenharmony_ci		if (p->family >= CHIP_RV770 || p->family == CHIP_R600) {
212462306a36Sopenharmony_ci			DRM_ERROR("bad SURFACE_BASE_UPDATE\n");
212562306a36Sopenharmony_ci			return -EINVAL;
212662306a36Sopenharmony_ci		}
212762306a36Sopenharmony_ci		if (pkt->count) {
212862306a36Sopenharmony_ci			DRM_ERROR("bad SURFACE_BASE_UPDATE\n");
212962306a36Sopenharmony_ci			return -EINVAL;
213062306a36Sopenharmony_ci		}
213162306a36Sopenharmony_ci		break;
213262306a36Sopenharmony_ci	case PACKET3_STRMOUT_BUFFER_UPDATE:
213362306a36Sopenharmony_ci		if (pkt->count != 4) {
213462306a36Sopenharmony_ci			DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (invalid count)\n");
213562306a36Sopenharmony_ci			return -EINVAL;
213662306a36Sopenharmony_ci		}
213762306a36Sopenharmony_ci		/* Updating memory at DST_ADDRESS. */
213862306a36Sopenharmony_ci		if (idx_value & 0x1) {
213962306a36Sopenharmony_ci			u64 offset;
214062306a36Sopenharmony_ci			r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
214162306a36Sopenharmony_ci			if (r) {
214262306a36Sopenharmony_ci				DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing dst reloc)\n");
214362306a36Sopenharmony_ci				return -EINVAL;
214462306a36Sopenharmony_ci			}
214562306a36Sopenharmony_ci			offset = radeon_get_ib_value(p, idx+1);
214662306a36Sopenharmony_ci			offset += ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32;
214762306a36Sopenharmony_ci			if ((offset + 4) > radeon_bo_size(reloc->robj)) {
214862306a36Sopenharmony_ci				DRM_ERROR("bad STRMOUT_BUFFER_UPDATE dst bo too small: 0x%llx, 0x%lx\n",
214962306a36Sopenharmony_ci					  offset + 4, radeon_bo_size(reloc->robj));
215062306a36Sopenharmony_ci				return -EINVAL;
215162306a36Sopenharmony_ci			}
215262306a36Sopenharmony_ci			offset += reloc->gpu_offset;
215362306a36Sopenharmony_ci			ib[idx+1] = offset;
215462306a36Sopenharmony_ci			ib[idx+2] = upper_32_bits(offset) & 0xff;
215562306a36Sopenharmony_ci		}
215662306a36Sopenharmony_ci		/* Reading data from SRC_ADDRESS. */
215762306a36Sopenharmony_ci		if (((idx_value >> 1) & 0x3) == 2) {
215862306a36Sopenharmony_ci			u64 offset;
215962306a36Sopenharmony_ci			r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
216062306a36Sopenharmony_ci			if (r) {
216162306a36Sopenharmony_ci				DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing src reloc)\n");
216262306a36Sopenharmony_ci				return -EINVAL;
216362306a36Sopenharmony_ci			}
216462306a36Sopenharmony_ci			offset = radeon_get_ib_value(p, idx+3);
216562306a36Sopenharmony_ci			offset += ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32;
216662306a36Sopenharmony_ci			if ((offset + 4) > radeon_bo_size(reloc->robj)) {
216762306a36Sopenharmony_ci				DRM_ERROR("bad STRMOUT_BUFFER_UPDATE src bo too small: 0x%llx, 0x%lx\n",
216862306a36Sopenharmony_ci					  offset + 4, radeon_bo_size(reloc->robj));
216962306a36Sopenharmony_ci				return -EINVAL;
217062306a36Sopenharmony_ci			}
217162306a36Sopenharmony_ci			offset += reloc->gpu_offset;
217262306a36Sopenharmony_ci			ib[idx+3] = offset;
217362306a36Sopenharmony_ci			ib[idx+4] = upper_32_bits(offset) & 0xff;
217462306a36Sopenharmony_ci		}
217562306a36Sopenharmony_ci		break;
217662306a36Sopenharmony_ci	case PACKET3_MEM_WRITE:
217762306a36Sopenharmony_ci	{
217862306a36Sopenharmony_ci		u64 offset;
217962306a36Sopenharmony_ci
218062306a36Sopenharmony_ci		if (pkt->count != 3) {
218162306a36Sopenharmony_ci			DRM_ERROR("bad MEM_WRITE (invalid count)\n");
218262306a36Sopenharmony_ci			return -EINVAL;
218362306a36Sopenharmony_ci		}
218462306a36Sopenharmony_ci		r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
218562306a36Sopenharmony_ci		if (r) {
218662306a36Sopenharmony_ci			DRM_ERROR("bad MEM_WRITE (missing reloc)\n");
218762306a36Sopenharmony_ci			return -EINVAL;
218862306a36Sopenharmony_ci		}
218962306a36Sopenharmony_ci		offset = radeon_get_ib_value(p, idx+0);
219062306a36Sopenharmony_ci		offset += ((u64)(radeon_get_ib_value(p, idx+1) & 0xff)) << 32UL;
219162306a36Sopenharmony_ci		if (offset & 0x7) {
219262306a36Sopenharmony_ci			DRM_ERROR("bad MEM_WRITE (address not qwords aligned)\n");
219362306a36Sopenharmony_ci			return -EINVAL;
219462306a36Sopenharmony_ci		}
219562306a36Sopenharmony_ci		if ((offset + 8) > radeon_bo_size(reloc->robj)) {
219662306a36Sopenharmony_ci			DRM_ERROR("bad MEM_WRITE bo too small: 0x%llx, 0x%lx\n",
219762306a36Sopenharmony_ci				  offset + 8, radeon_bo_size(reloc->robj));
219862306a36Sopenharmony_ci			return -EINVAL;
219962306a36Sopenharmony_ci		}
220062306a36Sopenharmony_ci		offset += reloc->gpu_offset;
220162306a36Sopenharmony_ci		ib[idx+0] = offset;
220262306a36Sopenharmony_ci		ib[idx+1] = upper_32_bits(offset) & 0xff;
220362306a36Sopenharmony_ci		break;
220462306a36Sopenharmony_ci	}
220562306a36Sopenharmony_ci	case PACKET3_COPY_DW:
220662306a36Sopenharmony_ci		if (pkt->count != 4) {
220762306a36Sopenharmony_ci			DRM_ERROR("bad COPY_DW (invalid count)\n");
220862306a36Sopenharmony_ci			return -EINVAL;
220962306a36Sopenharmony_ci		}
221062306a36Sopenharmony_ci		if (idx_value & 0x1) {
221162306a36Sopenharmony_ci			u64 offset;
221262306a36Sopenharmony_ci			/* SRC is memory. */
221362306a36Sopenharmony_ci			r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
221462306a36Sopenharmony_ci			if (r) {
221562306a36Sopenharmony_ci				DRM_ERROR("bad COPY_DW (missing src reloc)\n");
221662306a36Sopenharmony_ci				return -EINVAL;
221762306a36Sopenharmony_ci			}
221862306a36Sopenharmony_ci			offset = radeon_get_ib_value(p, idx+1);
221962306a36Sopenharmony_ci			offset += ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32;
222062306a36Sopenharmony_ci			if ((offset + 4) > radeon_bo_size(reloc->robj)) {
222162306a36Sopenharmony_ci				DRM_ERROR("bad COPY_DW src bo too small: 0x%llx, 0x%lx\n",
222262306a36Sopenharmony_ci					  offset + 4, radeon_bo_size(reloc->robj));
222362306a36Sopenharmony_ci				return -EINVAL;
222462306a36Sopenharmony_ci			}
222562306a36Sopenharmony_ci			offset += reloc->gpu_offset;
222662306a36Sopenharmony_ci			ib[idx+1] = offset;
222762306a36Sopenharmony_ci			ib[idx+2] = upper_32_bits(offset) & 0xff;
222862306a36Sopenharmony_ci		} else {
222962306a36Sopenharmony_ci			/* SRC is a reg. */
223062306a36Sopenharmony_ci			reg = radeon_get_ib_value(p, idx+1) << 2;
223162306a36Sopenharmony_ci			if (!r600_is_safe_reg(p, reg, idx+1))
223262306a36Sopenharmony_ci				return -EINVAL;
223362306a36Sopenharmony_ci		}
223462306a36Sopenharmony_ci		if (idx_value & 0x2) {
223562306a36Sopenharmony_ci			u64 offset;
223662306a36Sopenharmony_ci			/* DST is memory. */
223762306a36Sopenharmony_ci			r = radeon_cs_packet_next_reloc(p, &reloc, r600_nomm);
223862306a36Sopenharmony_ci			if (r) {
223962306a36Sopenharmony_ci				DRM_ERROR("bad COPY_DW (missing dst reloc)\n");
224062306a36Sopenharmony_ci				return -EINVAL;
224162306a36Sopenharmony_ci			}
224262306a36Sopenharmony_ci			offset = radeon_get_ib_value(p, idx+3);
224362306a36Sopenharmony_ci			offset += ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32;
224462306a36Sopenharmony_ci			if ((offset + 4) > radeon_bo_size(reloc->robj)) {
224562306a36Sopenharmony_ci				DRM_ERROR("bad COPY_DW dst bo too small: 0x%llx, 0x%lx\n",
224662306a36Sopenharmony_ci					  offset + 4, radeon_bo_size(reloc->robj));
224762306a36Sopenharmony_ci				return -EINVAL;
224862306a36Sopenharmony_ci			}
224962306a36Sopenharmony_ci			offset += reloc->gpu_offset;
225062306a36Sopenharmony_ci			ib[idx+3] = offset;
225162306a36Sopenharmony_ci			ib[idx+4] = upper_32_bits(offset) & 0xff;
225262306a36Sopenharmony_ci		} else {
225362306a36Sopenharmony_ci			/* DST is a reg. */
225462306a36Sopenharmony_ci			reg = radeon_get_ib_value(p, idx+3) << 2;
225562306a36Sopenharmony_ci			if (!r600_is_safe_reg(p, reg, idx+3))
225662306a36Sopenharmony_ci				return -EINVAL;
225762306a36Sopenharmony_ci		}
225862306a36Sopenharmony_ci		break;
225962306a36Sopenharmony_ci	case PACKET3_NOP:
226062306a36Sopenharmony_ci		break;
226162306a36Sopenharmony_ci	default:
226262306a36Sopenharmony_ci		DRM_ERROR("Packet3 opcode %x not supported\n", pkt->opcode);
226362306a36Sopenharmony_ci		return -EINVAL;
226462306a36Sopenharmony_ci	}
226562306a36Sopenharmony_ci	return 0;
226662306a36Sopenharmony_ci}
226762306a36Sopenharmony_ci
226862306a36Sopenharmony_ciint r600_cs_parse(struct radeon_cs_parser *p)
226962306a36Sopenharmony_ci{
227062306a36Sopenharmony_ci	struct radeon_cs_packet pkt;
227162306a36Sopenharmony_ci	struct r600_cs_track *track;
227262306a36Sopenharmony_ci	int r;
227362306a36Sopenharmony_ci
227462306a36Sopenharmony_ci	if (p->track == NULL) {
227562306a36Sopenharmony_ci		/* initialize tracker, we are in kms */
227662306a36Sopenharmony_ci		track = kzalloc(sizeof(*track), GFP_KERNEL);
227762306a36Sopenharmony_ci		if (track == NULL)
227862306a36Sopenharmony_ci			return -ENOMEM;
227962306a36Sopenharmony_ci		r600_cs_track_init(track);
228062306a36Sopenharmony_ci		if (p->rdev->family < CHIP_RV770) {
228162306a36Sopenharmony_ci			track->npipes = p->rdev->config.r600.tiling_npipes;
228262306a36Sopenharmony_ci			track->nbanks = p->rdev->config.r600.tiling_nbanks;
228362306a36Sopenharmony_ci			track->group_size = p->rdev->config.r600.tiling_group_size;
228462306a36Sopenharmony_ci		} else if (p->rdev->family <= CHIP_RV740) {
228562306a36Sopenharmony_ci			track->npipes = p->rdev->config.rv770.tiling_npipes;
228662306a36Sopenharmony_ci			track->nbanks = p->rdev->config.rv770.tiling_nbanks;
228762306a36Sopenharmony_ci			track->group_size = p->rdev->config.rv770.tiling_group_size;
228862306a36Sopenharmony_ci		}
228962306a36Sopenharmony_ci		p->track = track;
229062306a36Sopenharmony_ci	}
229162306a36Sopenharmony_ci	do {
229262306a36Sopenharmony_ci		r = radeon_cs_packet_parse(p, &pkt, p->idx);
229362306a36Sopenharmony_ci		if (r) {
229462306a36Sopenharmony_ci			kfree(p->track);
229562306a36Sopenharmony_ci			p->track = NULL;
229662306a36Sopenharmony_ci			return r;
229762306a36Sopenharmony_ci		}
229862306a36Sopenharmony_ci		p->idx += pkt.count + 2;
229962306a36Sopenharmony_ci		switch (pkt.type) {
230062306a36Sopenharmony_ci		case RADEON_PACKET_TYPE0:
230162306a36Sopenharmony_ci			r = r600_cs_parse_packet0(p, &pkt);
230262306a36Sopenharmony_ci			break;
230362306a36Sopenharmony_ci		case RADEON_PACKET_TYPE2:
230462306a36Sopenharmony_ci			break;
230562306a36Sopenharmony_ci		case RADEON_PACKET_TYPE3:
230662306a36Sopenharmony_ci			r = r600_packet3_check(p, &pkt);
230762306a36Sopenharmony_ci			break;
230862306a36Sopenharmony_ci		default:
230962306a36Sopenharmony_ci			DRM_ERROR("Unknown packet type %d !\n", pkt.type);
231062306a36Sopenharmony_ci			kfree(p->track);
231162306a36Sopenharmony_ci			p->track = NULL;
231262306a36Sopenharmony_ci			return -EINVAL;
231362306a36Sopenharmony_ci		}
231462306a36Sopenharmony_ci		if (r) {
231562306a36Sopenharmony_ci			kfree(p->track);
231662306a36Sopenharmony_ci			p->track = NULL;
231762306a36Sopenharmony_ci			return r;
231862306a36Sopenharmony_ci		}
231962306a36Sopenharmony_ci	} while (p->idx < p->chunk_ib->length_dw);
232062306a36Sopenharmony_ci#if 0
232162306a36Sopenharmony_ci	for (r = 0; r < p->ib.length_dw; r++) {
232262306a36Sopenharmony_ci		pr_info("%05d  0x%08X\n", r, p->ib.ptr[r]);
232362306a36Sopenharmony_ci		mdelay(1);
232462306a36Sopenharmony_ci	}
232562306a36Sopenharmony_ci#endif
232662306a36Sopenharmony_ci	kfree(p->track);
232762306a36Sopenharmony_ci	p->track = NULL;
232862306a36Sopenharmony_ci	return 0;
232962306a36Sopenharmony_ci}
233062306a36Sopenharmony_ci
233162306a36Sopenharmony_ci/*
233262306a36Sopenharmony_ci *  DMA
233362306a36Sopenharmony_ci */
233462306a36Sopenharmony_ci/**
233562306a36Sopenharmony_ci * r600_dma_cs_next_reloc() - parse next reloc
233662306a36Sopenharmony_ci * @p:		parser structure holding parsing context.
233762306a36Sopenharmony_ci * @cs_reloc:		reloc information
233862306a36Sopenharmony_ci *
233962306a36Sopenharmony_ci * Return the next reloc, do bo validation and compute
234062306a36Sopenharmony_ci * GPU offset using the provided start.
234162306a36Sopenharmony_ci **/
234262306a36Sopenharmony_ciint r600_dma_cs_next_reloc(struct radeon_cs_parser *p,
234362306a36Sopenharmony_ci			   struct radeon_bo_list **cs_reloc)
234462306a36Sopenharmony_ci{
234562306a36Sopenharmony_ci	unsigned idx;
234662306a36Sopenharmony_ci
234762306a36Sopenharmony_ci	*cs_reloc = NULL;
234862306a36Sopenharmony_ci	if (p->chunk_relocs == NULL) {
234962306a36Sopenharmony_ci		DRM_ERROR("No relocation chunk !\n");
235062306a36Sopenharmony_ci		return -EINVAL;
235162306a36Sopenharmony_ci	}
235262306a36Sopenharmony_ci	idx = p->dma_reloc_idx;
235362306a36Sopenharmony_ci	if (idx >= p->nrelocs) {
235462306a36Sopenharmony_ci		DRM_ERROR("Relocs at %d after relocations chunk end %d !\n",
235562306a36Sopenharmony_ci			  idx, p->nrelocs);
235662306a36Sopenharmony_ci		return -EINVAL;
235762306a36Sopenharmony_ci	}
235862306a36Sopenharmony_ci	*cs_reloc = &p->relocs[idx];
235962306a36Sopenharmony_ci	p->dma_reloc_idx++;
236062306a36Sopenharmony_ci	return 0;
236162306a36Sopenharmony_ci}
236262306a36Sopenharmony_ci
236362306a36Sopenharmony_ci#define GET_DMA_CMD(h) (((h) & 0xf0000000) >> 28)
236462306a36Sopenharmony_ci#define GET_DMA_COUNT(h) ((h) & 0x0000ffff)
236562306a36Sopenharmony_ci#define GET_DMA_T(h) (((h) & 0x00800000) >> 23)
236662306a36Sopenharmony_ci
236762306a36Sopenharmony_ci/**
236862306a36Sopenharmony_ci * r600_dma_cs_parse() - parse the DMA IB
236962306a36Sopenharmony_ci * @p:		parser structure holding parsing context.
237062306a36Sopenharmony_ci *
237162306a36Sopenharmony_ci * Parses the DMA IB from the CS ioctl and updates
237262306a36Sopenharmony_ci * the GPU addresses based on the reloc information and
237362306a36Sopenharmony_ci * checks for errors. (R6xx-R7xx)
237462306a36Sopenharmony_ci * Returns 0 for success and an error on failure.
237562306a36Sopenharmony_ci **/
237662306a36Sopenharmony_ciint r600_dma_cs_parse(struct radeon_cs_parser *p)
237762306a36Sopenharmony_ci{
237862306a36Sopenharmony_ci	struct radeon_cs_chunk *ib_chunk = p->chunk_ib;
237962306a36Sopenharmony_ci	struct radeon_bo_list *src_reloc, *dst_reloc;
238062306a36Sopenharmony_ci	u32 header, cmd, count, tiled;
238162306a36Sopenharmony_ci	volatile u32 *ib = p->ib.ptr;
238262306a36Sopenharmony_ci	u32 idx, idx_value;
238362306a36Sopenharmony_ci	u64 src_offset, dst_offset;
238462306a36Sopenharmony_ci	int r;
238562306a36Sopenharmony_ci
238662306a36Sopenharmony_ci	do {
238762306a36Sopenharmony_ci		if (p->idx >= ib_chunk->length_dw) {
238862306a36Sopenharmony_ci			DRM_ERROR("Can not parse packet at %d after CS end %d !\n",
238962306a36Sopenharmony_ci				  p->idx, ib_chunk->length_dw);
239062306a36Sopenharmony_ci			return -EINVAL;
239162306a36Sopenharmony_ci		}
239262306a36Sopenharmony_ci		idx = p->idx;
239362306a36Sopenharmony_ci		header = radeon_get_ib_value(p, idx);
239462306a36Sopenharmony_ci		cmd = GET_DMA_CMD(header);
239562306a36Sopenharmony_ci		count = GET_DMA_COUNT(header);
239662306a36Sopenharmony_ci		tiled = GET_DMA_T(header);
239762306a36Sopenharmony_ci
239862306a36Sopenharmony_ci		switch (cmd) {
239962306a36Sopenharmony_ci		case DMA_PACKET_WRITE:
240062306a36Sopenharmony_ci			r = r600_dma_cs_next_reloc(p, &dst_reloc);
240162306a36Sopenharmony_ci			if (r) {
240262306a36Sopenharmony_ci				DRM_ERROR("bad DMA_PACKET_WRITE\n");
240362306a36Sopenharmony_ci				return -EINVAL;
240462306a36Sopenharmony_ci			}
240562306a36Sopenharmony_ci			if (tiled) {
240662306a36Sopenharmony_ci				dst_offset = radeon_get_ib_value(p, idx+1);
240762306a36Sopenharmony_ci				dst_offset <<= 8;
240862306a36Sopenharmony_ci
240962306a36Sopenharmony_ci				ib[idx+1] += (u32)(dst_reloc->gpu_offset >> 8);
241062306a36Sopenharmony_ci				p->idx += count + 5;
241162306a36Sopenharmony_ci			} else {
241262306a36Sopenharmony_ci				dst_offset = radeon_get_ib_value(p, idx+1);
241362306a36Sopenharmony_ci				dst_offset |= ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32;
241462306a36Sopenharmony_ci
241562306a36Sopenharmony_ci				ib[idx+1] += (u32)(dst_reloc->gpu_offset & 0xfffffffc);
241662306a36Sopenharmony_ci				ib[idx+2] += upper_32_bits(dst_reloc->gpu_offset) & 0xff;
241762306a36Sopenharmony_ci				p->idx += count + 3;
241862306a36Sopenharmony_ci			}
241962306a36Sopenharmony_ci			if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
242062306a36Sopenharmony_ci				dev_warn(p->dev, "DMA write buffer too small (%llu %lu)\n",
242162306a36Sopenharmony_ci					 dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
242262306a36Sopenharmony_ci				return -EINVAL;
242362306a36Sopenharmony_ci			}
242462306a36Sopenharmony_ci			break;
242562306a36Sopenharmony_ci		case DMA_PACKET_COPY:
242662306a36Sopenharmony_ci			r = r600_dma_cs_next_reloc(p, &src_reloc);
242762306a36Sopenharmony_ci			if (r) {
242862306a36Sopenharmony_ci				DRM_ERROR("bad DMA_PACKET_COPY\n");
242962306a36Sopenharmony_ci				return -EINVAL;
243062306a36Sopenharmony_ci			}
243162306a36Sopenharmony_ci			r = r600_dma_cs_next_reloc(p, &dst_reloc);
243262306a36Sopenharmony_ci			if (r) {
243362306a36Sopenharmony_ci				DRM_ERROR("bad DMA_PACKET_COPY\n");
243462306a36Sopenharmony_ci				return -EINVAL;
243562306a36Sopenharmony_ci			}
243662306a36Sopenharmony_ci			if (tiled) {
243762306a36Sopenharmony_ci				idx_value = radeon_get_ib_value(p, idx + 2);
243862306a36Sopenharmony_ci				/* detile bit */
243962306a36Sopenharmony_ci				if (idx_value & (1 << 31)) {
244062306a36Sopenharmony_ci					/* tiled src, linear dst */
244162306a36Sopenharmony_ci					src_offset = radeon_get_ib_value(p, idx+1);
244262306a36Sopenharmony_ci					src_offset <<= 8;
244362306a36Sopenharmony_ci					ib[idx+1] += (u32)(src_reloc->gpu_offset >> 8);
244462306a36Sopenharmony_ci
244562306a36Sopenharmony_ci					dst_offset = radeon_get_ib_value(p, idx+5);
244662306a36Sopenharmony_ci					dst_offset |= ((u64)(radeon_get_ib_value(p, idx+6) & 0xff)) << 32;
244762306a36Sopenharmony_ci					ib[idx+5] += (u32)(dst_reloc->gpu_offset & 0xfffffffc);
244862306a36Sopenharmony_ci					ib[idx+6] += upper_32_bits(dst_reloc->gpu_offset) & 0xff;
244962306a36Sopenharmony_ci				} else {
245062306a36Sopenharmony_ci					/* linear src, tiled dst */
245162306a36Sopenharmony_ci					src_offset = radeon_get_ib_value(p, idx+5);
245262306a36Sopenharmony_ci					src_offset |= ((u64)(radeon_get_ib_value(p, idx+6) & 0xff)) << 32;
245362306a36Sopenharmony_ci					ib[idx+5] += (u32)(src_reloc->gpu_offset & 0xfffffffc);
245462306a36Sopenharmony_ci					ib[idx+6] += upper_32_bits(src_reloc->gpu_offset) & 0xff;
245562306a36Sopenharmony_ci
245662306a36Sopenharmony_ci					dst_offset = radeon_get_ib_value(p, idx+1);
245762306a36Sopenharmony_ci					dst_offset <<= 8;
245862306a36Sopenharmony_ci					ib[idx+1] += (u32)(dst_reloc->gpu_offset >> 8);
245962306a36Sopenharmony_ci				}
246062306a36Sopenharmony_ci				p->idx += 7;
246162306a36Sopenharmony_ci			} else {
246262306a36Sopenharmony_ci				if (p->family >= CHIP_RV770) {
246362306a36Sopenharmony_ci					src_offset = radeon_get_ib_value(p, idx+2);
246462306a36Sopenharmony_ci					src_offset |= ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32;
246562306a36Sopenharmony_ci					dst_offset = radeon_get_ib_value(p, idx+1);
246662306a36Sopenharmony_ci					dst_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0xff)) << 32;
246762306a36Sopenharmony_ci
246862306a36Sopenharmony_ci					ib[idx+1] += (u32)(dst_reloc->gpu_offset & 0xfffffffc);
246962306a36Sopenharmony_ci					ib[idx+2] += (u32)(src_reloc->gpu_offset & 0xfffffffc);
247062306a36Sopenharmony_ci					ib[idx+3] += upper_32_bits(dst_reloc->gpu_offset) & 0xff;
247162306a36Sopenharmony_ci					ib[idx+4] += upper_32_bits(src_reloc->gpu_offset) & 0xff;
247262306a36Sopenharmony_ci					p->idx += 5;
247362306a36Sopenharmony_ci				} else {
247462306a36Sopenharmony_ci					src_offset = radeon_get_ib_value(p, idx+2);
247562306a36Sopenharmony_ci					src_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0xff)) << 32;
247662306a36Sopenharmony_ci					dst_offset = radeon_get_ib_value(p, idx+1);
247762306a36Sopenharmony_ci					dst_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0xff0000)) << 16;
247862306a36Sopenharmony_ci
247962306a36Sopenharmony_ci					ib[idx+1] += (u32)(dst_reloc->gpu_offset & 0xfffffffc);
248062306a36Sopenharmony_ci					ib[idx+2] += (u32)(src_reloc->gpu_offset & 0xfffffffc);
248162306a36Sopenharmony_ci					ib[idx+3] += upper_32_bits(src_reloc->gpu_offset) & 0xff;
248262306a36Sopenharmony_ci					ib[idx+3] += (upper_32_bits(dst_reloc->gpu_offset) & 0xff) << 16;
248362306a36Sopenharmony_ci					p->idx += 4;
248462306a36Sopenharmony_ci				}
248562306a36Sopenharmony_ci			}
248662306a36Sopenharmony_ci			if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) {
248762306a36Sopenharmony_ci				dev_warn(p->dev, "DMA copy src buffer too small (%llu %lu)\n",
248862306a36Sopenharmony_ci					 src_offset + (count * 4), radeon_bo_size(src_reloc->robj));
248962306a36Sopenharmony_ci				return -EINVAL;
249062306a36Sopenharmony_ci			}
249162306a36Sopenharmony_ci			if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
249262306a36Sopenharmony_ci				dev_warn(p->dev, "DMA write dst buffer too small (%llu %lu)\n",
249362306a36Sopenharmony_ci					 dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
249462306a36Sopenharmony_ci				return -EINVAL;
249562306a36Sopenharmony_ci			}
249662306a36Sopenharmony_ci			break;
249762306a36Sopenharmony_ci		case DMA_PACKET_CONSTANT_FILL:
249862306a36Sopenharmony_ci			if (p->family < CHIP_RV770) {
249962306a36Sopenharmony_ci				DRM_ERROR("Constant Fill is 7xx only !\n");
250062306a36Sopenharmony_ci				return -EINVAL;
250162306a36Sopenharmony_ci			}
250262306a36Sopenharmony_ci			r = r600_dma_cs_next_reloc(p, &dst_reloc);
250362306a36Sopenharmony_ci			if (r) {
250462306a36Sopenharmony_ci				DRM_ERROR("bad DMA_PACKET_WRITE\n");
250562306a36Sopenharmony_ci				return -EINVAL;
250662306a36Sopenharmony_ci			}
250762306a36Sopenharmony_ci			dst_offset = radeon_get_ib_value(p, idx+1);
250862306a36Sopenharmony_ci			dst_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0x00ff0000)) << 16;
250962306a36Sopenharmony_ci			if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) {
251062306a36Sopenharmony_ci				dev_warn(p->dev, "DMA constant fill buffer too small (%llu %lu)\n",
251162306a36Sopenharmony_ci					 dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj));
251262306a36Sopenharmony_ci				return -EINVAL;
251362306a36Sopenharmony_ci			}
251462306a36Sopenharmony_ci			ib[idx+1] += (u32)(dst_reloc->gpu_offset & 0xfffffffc);
251562306a36Sopenharmony_ci			ib[idx+3] += (upper_32_bits(dst_reloc->gpu_offset) << 16) & 0x00ff0000;
251662306a36Sopenharmony_ci			p->idx += 4;
251762306a36Sopenharmony_ci			break;
251862306a36Sopenharmony_ci		case DMA_PACKET_NOP:
251962306a36Sopenharmony_ci			p->idx += 1;
252062306a36Sopenharmony_ci			break;
252162306a36Sopenharmony_ci		default:
252262306a36Sopenharmony_ci			DRM_ERROR("Unknown packet type %d at %d !\n", cmd, idx);
252362306a36Sopenharmony_ci			return -EINVAL;
252462306a36Sopenharmony_ci		}
252562306a36Sopenharmony_ci	} while (p->idx < p->chunk_ib->length_dw);
252662306a36Sopenharmony_ci#if 0
252762306a36Sopenharmony_ci	for (r = 0; r < p->ib->length_dw; r++) {
252862306a36Sopenharmony_ci		pr_info("%05d  0x%08X\n", r, p->ib.ptr[r]);
252962306a36Sopenharmony_ci		mdelay(1);
253062306a36Sopenharmony_ci	}
253162306a36Sopenharmony_ci#endif
253262306a36Sopenharmony_ci	return 0;
253362306a36Sopenharmony_ci}
2534