162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * Copyright 2010 Advanced Micro Devices, Inc. 362306a36Sopenharmony_ci * Copyright 2008 Red Hat Inc. 462306a36Sopenharmony_ci * Copyright 2009 Jerome Glisse. 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 762306a36Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 862306a36Sopenharmony_ci * to deal in the Software without restriction, including without limitation 962306a36Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 1062306a36Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 1162306a36Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 1262306a36Sopenharmony_ci * 1362306a36Sopenharmony_ci * The above copyright notice and this permission notice shall be included in 1462306a36Sopenharmony_ci * all copies or substantial portions of the Software. 1562306a36Sopenharmony_ci * 1662306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1762306a36Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1862306a36Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1962306a36Sopenharmony_ci * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 2062306a36Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 2162306a36Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 2262306a36Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE. 2362306a36Sopenharmony_ci * 2462306a36Sopenharmony_ci * Authors: Dave Airlie 2562306a36Sopenharmony_ci * Alex Deucher 2662306a36Sopenharmony_ci * Jerome Glisse 2762306a36Sopenharmony_ci */ 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci#include "radeon.h" 3062306a36Sopenharmony_ci#include "radeon_asic.h" 3162306a36Sopenharmony_ci#include "r600.h" 3262306a36Sopenharmony_ci#include "evergreend.h" 3362306a36Sopenharmony_ci#include "evergreen_reg_safe.h" 3462306a36Sopenharmony_ci#include "cayman_reg_safe.h" 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci#define MAX(a,b) (((a)>(b))?(a):(b)) 3762306a36Sopenharmony_ci#define MIN(a,b) (((a)<(b))?(a):(b)) 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci#define REG_SAFE_BM_SIZE ARRAY_SIZE(evergreen_reg_safe_bm) 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_cistruct evergreen_cs_track { 4262306a36Sopenharmony_ci u32 group_size; 4362306a36Sopenharmony_ci u32 nbanks; 4462306a36Sopenharmony_ci u32 npipes; 4562306a36Sopenharmony_ci u32 row_size; 4662306a36Sopenharmony_ci /* value we track */ 4762306a36Sopenharmony_ci u32 nsamples; /* unused */ 4862306a36Sopenharmony_ci struct radeon_bo *cb_color_bo[12]; 4962306a36Sopenharmony_ci u32 cb_color_bo_offset[12]; 5062306a36Sopenharmony_ci struct radeon_bo *cb_color_fmask_bo[8]; /* unused */ 5162306a36Sopenharmony_ci struct radeon_bo *cb_color_cmask_bo[8]; /* unused */ 5262306a36Sopenharmony_ci u32 cb_color_info[12]; 5362306a36Sopenharmony_ci u32 cb_color_view[12]; 5462306a36Sopenharmony_ci u32 cb_color_pitch[12]; 5562306a36Sopenharmony_ci u32 cb_color_slice[12]; 5662306a36Sopenharmony_ci u32 cb_color_slice_idx[12]; 5762306a36Sopenharmony_ci u32 cb_color_attrib[12]; 5862306a36Sopenharmony_ci u32 cb_color_cmask_slice[8];/* unused */ 5962306a36Sopenharmony_ci u32 cb_color_fmask_slice[8];/* unused */ 6062306a36Sopenharmony_ci u32 cb_target_mask; 6162306a36Sopenharmony_ci u32 cb_shader_mask; /* unused */ 6262306a36Sopenharmony_ci u32 vgt_strmout_config; 6362306a36Sopenharmony_ci u32 vgt_strmout_buffer_config; 6462306a36Sopenharmony_ci struct radeon_bo *vgt_strmout_bo[4]; 6562306a36Sopenharmony_ci u32 vgt_strmout_bo_offset[4]; 6662306a36Sopenharmony_ci u32 vgt_strmout_size[4]; 6762306a36Sopenharmony_ci u32 db_depth_control; 6862306a36Sopenharmony_ci u32 db_depth_view; 6962306a36Sopenharmony_ci u32 db_depth_slice; 7062306a36Sopenharmony_ci u32 db_depth_size; 7162306a36Sopenharmony_ci u32 db_z_info; 7262306a36Sopenharmony_ci u32 db_z_read_offset; 7362306a36Sopenharmony_ci u32 db_z_write_offset; 7462306a36Sopenharmony_ci struct radeon_bo *db_z_read_bo; 7562306a36Sopenharmony_ci struct radeon_bo *db_z_write_bo; 7662306a36Sopenharmony_ci u32 db_s_info; 7762306a36Sopenharmony_ci u32 db_s_read_offset; 7862306a36Sopenharmony_ci u32 db_s_write_offset; 7962306a36Sopenharmony_ci struct radeon_bo *db_s_read_bo; 8062306a36Sopenharmony_ci struct radeon_bo *db_s_write_bo; 8162306a36Sopenharmony_ci bool sx_misc_kill_all_prims; 8262306a36Sopenharmony_ci bool cb_dirty; 8362306a36Sopenharmony_ci bool db_dirty; 8462306a36Sopenharmony_ci bool streamout_dirty; 8562306a36Sopenharmony_ci u32 htile_offset; 8662306a36Sopenharmony_ci u32 htile_surface; 8762306a36Sopenharmony_ci struct radeon_bo *htile_bo; 8862306a36Sopenharmony_ci unsigned long indirect_draw_buffer_size; 8962306a36Sopenharmony_ci const unsigned *reg_safe_bm; 9062306a36Sopenharmony_ci}; 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_cistatic u32 evergreen_cs_get_aray_mode(u32 tiling_flags) 9362306a36Sopenharmony_ci{ 9462306a36Sopenharmony_ci if (tiling_flags & RADEON_TILING_MACRO) 9562306a36Sopenharmony_ci return ARRAY_2D_TILED_THIN1; 9662306a36Sopenharmony_ci else if (tiling_flags & RADEON_TILING_MICRO) 9762306a36Sopenharmony_ci return ARRAY_1D_TILED_THIN1; 9862306a36Sopenharmony_ci else 9962306a36Sopenharmony_ci return ARRAY_LINEAR_GENERAL; 10062306a36Sopenharmony_ci} 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_cistatic u32 evergreen_cs_get_num_banks(u32 nbanks) 10362306a36Sopenharmony_ci{ 10462306a36Sopenharmony_ci switch (nbanks) { 10562306a36Sopenharmony_ci case 2: 10662306a36Sopenharmony_ci return ADDR_SURF_2_BANK; 10762306a36Sopenharmony_ci case 4: 10862306a36Sopenharmony_ci return ADDR_SURF_4_BANK; 10962306a36Sopenharmony_ci case 8: 11062306a36Sopenharmony_ci default: 11162306a36Sopenharmony_ci return ADDR_SURF_8_BANK; 11262306a36Sopenharmony_ci case 16: 11362306a36Sopenharmony_ci return ADDR_SURF_16_BANK; 11462306a36Sopenharmony_ci } 11562306a36Sopenharmony_ci} 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_cistatic void evergreen_cs_track_init(struct evergreen_cs_track *track) 11862306a36Sopenharmony_ci{ 11962306a36Sopenharmony_ci int i; 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci for (i = 0; i < 8; i++) { 12262306a36Sopenharmony_ci track->cb_color_fmask_bo[i] = NULL; 12362306a36Sopenharmony_ci track->cb_color_cmask_bo[i] = NULL; 12462306a36Sopenharmony_ci track->cb_color_cmask_slice[i] = 0; 12562306a36Sopenharmony_ci track->cb_color_fmask_slice[i] = 0; 12662306a36Sopenharmony_ci } 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci for (i = 0; i < 12; i++) { 12962306a36Sopenharmony_ci track->cb_color_bo[i] = NULL; 13062306a36Sopenharmony_ci track->cb_color_bo_offset[i] = 0xFFFFFFFF; 13162306a36Sopenharmony_ci track->cb_color_info[i] = 0; 13262306a36Sopenharmony_ci track->cb_color_view[i] = 0xFFFFFFFF; 13362306a36Sopenharmony_ci track->cb_color_pitch[i] = 0; 13462306a36Sopenharmony_ci track->cb_color_slice[i] = 0xfffffff; 13562306a36Sopenharmony_ci track->cb_color_slice_idx[i] = 0; 13662306a36Sopenharmony_ci } 13762306a36Sopenharmony_ci track->cb_target_mask = 0xFFFFFFFF; 13862306a36Sopenharmony_ci track->cb_shader_mask = 0xFFFFFFFF; 13962306a36Sopenharmony_ci track->cb_dirty = true; 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_ci track->db_depth_slice = 0xffffffff; 14262306a36Sopenharmony_ci track->db_depth_view = 0xFFFFC000; 14362306a36Sopenharmony_ci track->db_depth_size = 0xFFFFFFFF; 14462306a36Sopenharmony_ci track->db_depth_control = 0xFFFFFFFF; 14562306a36Sopenharmony_ci track->db_z_info = 0xFFFFFFFF; 14662306a36Sopenharmony_ci track->db_z_read_offset = 0xFFFFFFFF; 14762306a36Sopenharmony_ci track->db_z_write_offset = 0xFFFFFFFF; 14862306a36Sopenharmony_ci track->db_z_read_bo = NULL; 14962306a36Sopenharmony_ci track->db_z_write_bo = NULL; 15062306a36Sopenharmony_ci track->db_s_info = 0xFFFFFFFF; 15162306a36Sopenharmony_ci track->db_s_read_offset = 0xFFFFFFFF; 15262306a36Sopenharmony_ci track->db_s_write_offset = 0xFFFFFFFF; 15362306a36Sopenharmony_ci track->db_s_read_bo = NULL; 15462306a36Sopenharmony_ci track->db_s_write_bo = NULL; 15562306a36Sopenharmony_ci track->db_dirty = true; 15662306a36Sopenharmony_ci track->htile_bo = NULL; 15762306a36Sopenharmony_ci track->htile_offset = 0xFFFFFFFF; 15862306a36Sopenharmony_ci track->htile_surface = 0; 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci for (i = 0; i < 4; i++) { 16162306a36Sopenharmony_ci track->vgt_strmout_size[i] = 0; 16262306a36Sopenharmony_ci track->vgt_strmout_bo[i] = NULL; 16362306a36Sopenharmony_ci track->vgt_strmout_bo_offset[i] = 0xFFFFFFFF; 16462306a36Sopenharmony_ci } 16562306a36Sopenharmony_ci track->streamout_dirty = true; 16662306a36Sopenharmony_ci track->sx_misc_kill_all_prims = false; 16762306a36Sopenharmony_ci} 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_cistruct eg_surface { 17062306a36Sopenharmony_ci /* value gathered from cs */ 17162306a36Sopenharmony_ci unsigned nbx; 17262306a36Sopenharmony_ci unsigned nby; 17362306a36Sopenharmony_ci unsigned format; 17462306a36Sopenharmony_ci unsigned mode; 17562306a36Sopenharmony_ci unsigned nbanks; 17662306a36Sopenharmony_ci unsigned bankw; 17762306a36Sopenharmony_ci unsigned bankh; 17862306a36Sopenharmony_ci unsigned tsplit; 17962306a36Sopenharmony_ci unsigned mtilea; 18062306a36Sopenharmony_ci unsigned nsamples; 18162306a36Sopenharmony_ci /* output value */ 18262306a36Sopenharmony_ci unsigned bpe; 18362306a36Sopenharmony_ci unsigned layer_size; 18462306a36Sopenharmony_ci unsigned palign; 18562306a36Sopenharmony_ci unsigned halign; 18662306a36Sopenharmony_ci unsigned long base_align; 18762306a36Sopenharmony_ci}; 18862306a36Sopenharmony_ci 18962306a36Sopenharmony_cistatic int evergreen_surface_check_linear(struct radeon_cs_parser *p, 19062306a36Sopenharmony_ci struct eg_surface *surf, 19162306a36Sopenharmony_ci const char *prefix) 19262306a36Sopenharmony_ci{ 19362306a36Sopenharmony_ci surf->layer_size = surf->nbx * surf->nby * surf->bpe * surf->nsamples; 19462306a36Sopenharmony_ci surf->base_align = surf->bpe; 19562306a36Sopenharmony_ci surf->palign = 1; 19662306a36Sopenharmony_ci surf->halign = 1; 19762306a36Sopenharmony_ci return 0; 19862306a36Sopenharmony_ci} 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_cistatic int evergreen_surface_check_linear_aligned(struct radeon_cs_parser *p, 20162306a36Sopenharmony_ci struct eg_surface *surf, 20262306a36Sopenharmony_ci const char *prefix) 20362306a36Sopenharmony_ci{ 20462306a36Sopenharmony_ci struct evergreen_cs_track *track = p->track; 20562306a36Sopenharmony_ci unsigned palign; 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci palign = MAX(64, track->group_size / surf->bpe); 20862306a36Sopenharmony_ci surf->layer_size = surf->nbx * surf->nby * surf->bpe * surf->nsamples; 20962306a36Sopenharmony_ci surf->base_align = track->group_size; 21062306a36Sopenharmony_ci surf->palign = palign; 21162306a36Sopenharmony_ci surf->halign = 1; 21262306a36Sopenharmony_ci if (surf->nbx & (palign - 1)) { 21362306a36Sopenharmony_ci if (prefix) { 21462306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d %s pitch %d invalid must be aligned with %d\n", 21562306a36Sopenharmony_ci __func__, __LINE__, prefix, surf->nbx, palign); 21662306a36Sopenharmony_ci } 21762306a36Sopenharmony_ci return -EINVAL; 21862306a36Sopenharmony_ci } 21962306a36Sopenharmony_ci return 0; 22062306a36Sopenharmony_ci} 22162306a36Sopenharmony_ci 22262306a36Sopenharmony_cistatic int evergreen_surface_check_1d(struct radeon_cs_parser *p, 22362306a36Sopenharmony_ci struct eg_surface *surf, 22462306a36Sopenharmony_ci const char *prefix) 22562306a36Sopenharmony_ci{ 22662306a36Sopenharmony_ci struct evergreen_cs_track *track = p->track; 22762306a36Sopenharmony_ci unsigned palign; 22862306a36Sopenharmony_ci 22962306a36Sopenharmony_ci palign = track->group_size / (8 * surf->bpe * surf->nsamples); 23062306a36Sopenharmony_ci palign = MAX(8, palign); 23162306a36Sopenharmony_ci surf->layer_size = surf->nbx * surf->nby * surf->bpe; 23262306a36Sopenharmony_ci surf->base_align = track->group_size; 23362306a36Sopenharmony_ci surf->palign = palign; 23462306a36Sopenharmony_ci surf->halign = 8; 23562306a36Sopenharmony_ci if ((surf->nbx & (palign - 1))) { 23662306a36Sopenharmony_ci if (prefix) { 23762306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d %s pitch %d invalid must be aligned with %d (%d %d %d)\n", 23862306a36Sopenharmony_ci __func__, __LINE__, prefix, surf->nbx, palign, 23962306a36Sopenharmony_ci track->group_size, surf->bpe, surf->nsamples); 24062306a36Sopenharmony_ci } 24162306a36Sopenharmony_ci return -EINVAL; 24262306a36Sopenharmony_ci } 24362306a36Sopenharmony_ci if ((surf->nby & (8 - 1))) { 24462306a36Sopenharmony_ci if (prefix) { 24562306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d %s height %d invalid must be aligned with 8\n", 24662306a36Sopenharmony_ci __func__, __LINE__, prefix, surf->nby); 24762306a36Sopenharmony_ci } 24862306a36Sopenharmony_ci return -EINVAL; 24962306a36Sopenharmony_ci } 25062306a36Sopenharmony_ci return 0; 25162306a36Sopenharmony_ci} 25262306a36Sopenharmony_ci 25362306a36Sopenharmony_cistatic int evergreen_surface_check_2d(struct radeon_cs_parser *p, 25462306a36Sopenharmony_ci struct eg_surface *surf, 25562306a36Sopenharmony_ci const char *prefix) 25662306a36Sopenharmony_ci{ 25762306a36Sopenharmony_ci struct evergreen_cs_track *track = p->track; 25862306a36Sopenharmony_ci unsigned palign, halign, tileb, slice_pt; 25962306a36Sopenharmony_ci unsigned mtile_pr, mtile_ps, mtileb; 26062306a36Sopenharmony_ci 26162306a36Sopenharmony_ci tileb = 64 * surf->bpe * surf->nsamples; 26262306a36Sopenharmony_ci slice_pt = 1; 26362306a36Sopenharmony_ci if (tileb > surf->tsplit) { 26462306a36Sopenharmony_ci slice_pt = tileb / surf->tsplit; 26562306a36Sopenharmony_ci } 26662306a36Sopenharmony_ci tileb = tileb / slice_pt; 26762306a36Sopenharmony_ci /* macro tile width & height */ 26862306a36Sopenharmony_ci palign = (8 * surf->bankw * track->npipes) * surf->mtilea; 26962306a36Sopenharmony_ci halign = (8 * surf->bankh * surf->nbanks) / surf->mtilea; 27062306a36Sopenharmony_ci mtileb = (palign / 8) * (halign / 8) * tileb; 27162306a36Sopenharmony_ci mtile_pr = surf->nbx / palign; 27262306a36Sopenharmony_ci mtile_ps = (mtile_pr * surf->nby) / halign; 27362306a36Sopenharmony_ci surf->layer_size = mtile_ps * mtileb * slice_pt; 27462306a36Sopenharmony_ci surf->base_align = (palign / 8) * (halign / 8) * tileb; 27562306a36Sopenharmony_ci surf->palign = palign; 27662306a36Sopenharmony_ci surf->halign = halign; 27762306a36Sopenharmony_ci 27862306a36Sopenharmony_ci if ((surf->nbx & (palign - 1))) { 27962306a36Sopenharmony_ci if (prefix) { 28062306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d %s pitch %d invalid must be aligned with %d\n", 28162306a36Sopenharmony_ci __func__, __LINE__, prefix, surf->nbx, palign); 28262306a36Sopenharmony_ci } 28362306a36Sopenharmony_ci return -EINVAL; 28462306a36Sopenharmony_ci } 28562306a36Sopenharmony_ci if ((surf->nby & (halign - 1))) { 28662306a36Sopenharmony_ci if (prefix) { 28762306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d %s height %d invalid must be aligned with %d\n", 28862306a36Sopenharmony_ci __func__, __LINE__, prefix, surf->nby, halign); 28962306a36Sopenharmony_ci } 29062306a36Sopenharmony_ci return -EINVAL; 29162306a36Sopenharmony_ci } 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci return 0; 29462306a36Sopenharmony_ci} 29562306a36Sopenharmony_ci 29662306a36Sopenharmony_cistatic int evergreen_surface_check(struct radeon_cs_parser *p, 29762306a36Sopenharmony_ci struct eg_surface *surf, 29862306a36Sopenharmony_ci const char *prefix) 29962306a36Sopenharmony_ci{ 30062306a36Sopenharmony_ci /* some common value computed here */ 30162306a36Sopenharmony_ci surf->bpe = r600_fmt_get_blocksize(surf->format); 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci switch (surf->mode) { 30462306a36Sopenharmony_ci case ARRAY_LINEAR_GENERAL: 30562306a36Sopenharmony_ci return evergreen_surface_check_linear(p, surf, prefix); 30662306a36Sopenharmony_ci case ARRAY_LINEAR_ALIGNED: 30762306a36Sopenharmony_ci return evergreen_surface_check_linear_aligned(p, surf, prefix); 30862306a36Sopenharmony_ci case ARRAY_1D_TILED_THIN1: 30962306a36Sopenharmony_ci return evergreen_surface_check_1d(p, surf, prefix); 31062306a36Sopenharmony_ci case ARRAY_2D_TILED_THIN1: 31162306a36Sopenharmony_ci return evergreen_surface_check_2d(p, surf, prefix); 31262306a36Sopenharmony_ci default: 31362306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d %s invalid array mode %d\n", 31462306a36Sopenharmony_ci __func__, __LINE__, prefix, surf->mode); 31562306a36Sopenharmony_ci return -EINVAL; 31662306a36Sopenharmony_ci } 31762306a36Sopenharmony_ci return -EINVAL; 31862306a36Sopenharmony_ci} 31962306a36Sopenharmony_ci 32062306a36Sopenharmony_cistatic int evergreen_surface_value_conv_check(struct radeon_cs_parser *p, 32162306a36Sopenharmony_ci struct eg_surface *surf, 32262306a36Sopenharmony_ci const char *prefix) 32362306a36Sopenharmony_ci{ 32462306a36Sopenharmony_ci switch (surf->mode) { 32562306a36Sopenharmony_ci case ARRAY_2D_TILED_THIN1: 32662306a36Sopenharmony_ci break; 32762306a36Sopenharmony_ci case ARRAY_LINEAR_GENERAL: 32862306a36Sopenharmony_ci case ARRAY_LINEAR_ALIGNED: 32962306a36Sopenharmony_ci case ARRAY_1D_TILED_THIN1: 33062306a36Sopenharmony_ci return 0; 33162306a36Sopenharmony_ci default: 33262306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d %s invalid array mode %d\n", 33362306a36Sopenharmony_ci __func__, __LINE__, prefix, surf->mode); 33462306a36Sopenharmony_ci return -EINVAL; 33562306a36Sopenharmony_ci } 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci switch (surf->nbanks) { 33862306a36Sopenharmony_ci case 0: surf->nbanks = 2; break; 33962306a36Sopenharmony_ci case 1: surf->nbanks = 4; break; 34062306a36Sopenharmony_ci case 2: surf->nbanks = 8; break; 34162306a36Sopenharmony_ci case 3: surf->nbanks = 16; break; 34262306a36Sopenharmony_ci default: 34362306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d %s invalid number of banks %d\n", 34462306a36Sopenharmony_ci __func__, __LINE__, prefix, surf->nbanks); 34562306a36Sopenharmony_ci return -EINVAL; 34662306a36Sopenharmony_ci } 34762306a36Sopenharmony_ci switch (surf->bankw) { 34862306a36Sopenharmony_ci case 0: surf->bankw = 1; break; 34962306a36Sopenharmony_ci case 1: surf->bankw = 2; break; 35062306a36Sopenharmony_ci case 2: surf->bankw = 4; break; 35162306a36Sopenharmony_ci case 3: surf->bankw = 8; break; 35262306a36Sopenharmony_ci default: 35362306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d %s invalid bankw %d\n", 35462306a36Sopenharmony_ci __func__, __LINE__, prefix, surf->bankw); 35562306a36Sopenharmony_ci return -EINVAL; 35662306a36Sopenharmony_ci } 35762306a36Sopenharmony_ci switch (surf->bankh) { 35862306a36Sopenharmony_ci case 0: surf->bankh = 1; break; 35962306a36Sopenharmony_ci case 1: surf->bankh = 2; break; 36062306a36Sopenharmony_ci case 2: surf->bankh = 4; break; 36162306a36Sopenharmony_ci case 3: surf->bankh = 8; break; 36262306a36Sopenharmony_ci default: 36362306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d %s invalid bankh %d\n", 36462306a36Sopenharmony_ci __func__, __LINE__, prefix, surf->bankh); 36562306a36Sopenharmony_ci return -EINVAL; 36662306a36Sopenharmony_ci } 36762306a36Sopenharmony_ci switch (surf->mtilea) { 36862306a36Sopenharmony_ci case 0: surf->mtilea = 1; break; 36962306a36Sopenharmony_ci case 1: surf->mtilea = 2; break; 37062306a36Sopenharmony_ci case 2: surf->mtilea = 4; break; 37162306a36Sopenharmony_ci case 3: surf->mtilea = 8; break; 37262306a36Sopenharmony_ci default: 37362306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d %s invalid macro tile aspect %d\n", 37462306a36Sopenharmony_ci __func__, __LINE__, prefix, surf->mtilea); 37562306a36Sopenharmony_ci return -EINVAL; 37662306a36Sopenharmony_ci } 37762306a36Sopenharmony_ci switch (surf->tsplit) { 37862306a36Sopenharmony_ci case 0: surf->tsplit = 64; break; 37962306a36Sopenharmony_ci case 1: surf->tsplit = 128; break; 38062306a36Sopenharmony_ci case 2: surf->tsplit = 256; break; 38162306a36Sopenharmony_ci case 3: surf->tsplit = 512; break; 38262306a36Sopenharmony_ci case 4: surf->tsplit = 1024; break; 38362306a36Sopenharmony_ci case 5: surf->tsplit = 2048; break; 38462306a36Sopenharmony_ci case 6: surf->tsplit = 4096; break; 38562306a36Sopenharmony_ci default: 38662306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d %s invalid tile split %d\n", 38762306a36Sopenharmony_ci __func__, __LINE__, prefix, surf->tsplit); 38862306a36Sopenharmony_ci return -EINVAL; 38962306a36Sopenharmony_ci } 39062306a36Sopenharmony_ci return 0; 39162306a36Sopenharmony_ci} 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_cistatic int evergreen_cs_track_validate_cb(struct radeon_cs_parser *p, unsigned id) 39462306a36Sopenharmony_ci{ 39562306a36Sopenharmony_ci struct evergreen_cs_track *track = p->track; 39662306a36Sopenharmony_ci struct eg_surface surf; 39762306a36Sopenharmony_ci unsigned pitch, slice, mslice; 39862306a36Sopenharmony_ci unsigned long offset; 39962306a36Sopenharmony_ci int r; 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci mslice = G_028C6C_SLICE_MAX(track->cb_color_view[id]) + 1; 40262306a36Sopenharmony_ci pitch = track->cb_color_pitch[id]; 40362306a36Sopenharmony_ci slice = track->cb_color_slice[id]; 40462306a36Sopenharmony_ci surf.nbx = (pitch + 1) * 8; 40562306a36Sopenharmony_ci surf.nby = ((slice + 1) * 64) / surf.nbx; 40662306a36Sopenharmony_ci surf.mode = G_028C70_ARRAY_MODE(track->cb_color_info[id]); 40762306a36Sopenharmony_ci surf.format = G_028C70_FORMAT(track->cb_color_info[id]); 40862306a36Sopenharmony_ci surf.tsplit = G_028C74_TILE_SPLIT(track->cb_color_attrib[id]); 40962306a36Sopenharmony_ci surf.nbanks = G_028C74_NUM_BANKS(track->cb_color_attrib[id]); 41062306a36Sopenharmony_ci surf.bankw = G_028C74_BANK_WIDTH(track->cb_color_attrib[id]); 41162306a36Sopenharmony_ci surf.bankh = G_028C74_BANK_HEIGHT(track->cb_color_attrib[id]); 41262306a36Sopenharmony_ci surf.mtilea = G_028C74_MACRO_TILE_ASPECT(track->cb_color_attrib[id]); 41362306a36Sopenharmony_ci surf.nsamples = 1; 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_ci if (!r600_fmt_is_valid_color(surf.format)) { 41662306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d cb invalid format %d for %d (0x%08x)\n", 41762306a36Sopenharmony_ci __func__, __LINE__, surf.format, 41862306a36Sopenharmony_ci id, track->cb_color_info[id]); 41962306a36Sopenharmony_ci return -EINVAL; 42062306a36Sopenharmony_ci } 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci r = evergreen_surface_value_conv_check(p, &surf, "cb"); 42362306a36Sopenharmony_ci if (r) { 42462306a36Sopenharmony_ci return r; 42562306a36Sopenharmony_ci } 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_ci r = evergreen_surface_check(p, &surf, "cb"); 42862306a36Sopenharmony_ci if (r) { 42962306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d cb[%d] invalid (0x%08x 0x%08x 0x%08x 0x%08x)\n", 43062306a36Sopenharmony_ci __func__, __LINE__, id, track->cb_color_pitch[id], 43162306a36Sopenharmony_ci track->cb_color_slice[id], track->cb_color_attrib[id], 43262306a36Sopenharmony_ci track->cb_color_info[id]); 43362306a36Sopenharmony_ci return r; 43462306a36Sopenharmony_ci } 43562306a36Sopenharmony_ci 43662306a36Sopenharmony_ci offset = track->cb_color_bo_offset[id] << 8; 43762306a36Sopenharmony_ci if (offset & (surf.base_align - 1)) { 43862306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d cb[%d] bo base %ld not aligned with %ld\n", 43962306a36Sopenharmony_ci __func__, __LINE__, id, offset, surf.base_align); 44062306a36Sopenharmony_ci return -EINVAL; 44162306a36Sopenharmony_ci } 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci offset += surf.layer_size * mslice; 44462306a36Sopenharmony_ci if (offset > radeon_bo_size(track->cb_color_bo[id])) { 44562306a36Sopenharmony_ci /* old ddx are broken they allocate bo with w*h*bpp but 44662306a36Sopenharmony_ci * program slice with ALIGN(h, 8), catch this and patch 44762306a36Sopenharmony_ci * command stream. 44862306a36Sopenharmony_ci */ 44962306a36Sopenharmony_ci if (!surf.mode) { 45062306a36Sopenharmony_ci uint32_t *ib = p->ib.ptr; 45162306a36Sopenharmony_ci unsigned long tmp, nby, bsize, size, min = 0; 45262306a36Sopenharmony_ci 45362306a36Sopenharmony_ci /* find the height the ddx wants */ 45462306a36Sopenharmony_ci if (surf.nby > 8) { 45562306a36Sopenharmony_ci min = surf.nby - 8; 45662306a36Sopenharmony_ci } 45762306a36Sopenharmony_ci bsize = radeon_bo_size(track->cb_color_bo[id]); 45862306a36Sopenharmony_ci tmp = track->cb_color_bo_offset[id] << 8; 45962306a36Sopenharmony_ci for (nby = surf.nby; nby > min; nby--) { 46062306a36Sopenharmony_ci size = nby * surf.nbx * surf.bpe * surf.nsamples; 46162306a36Sopenharmony_ci if ((tmp + size * mslice) <= bsize) { 46262306a36Sopenharmony_ci break; 46362306a36Sopenharmony_ci } 46462306a36Sopenharmony_ci } 46562306a36Sopenharmony_ci if (nby > min) { 46662306a36Sopenharmony_ci surf.nby = nby; 46762306a36Sopenharmony_ci slice = ((nby * surf.nbx) / 64) - 1; 46862306a36Sopenharmony_ci if (!evergreen_surface_check(p, &surf, "cb")) { 46962306a36Sopenharmony_ci /* check if this one works */ 47062306a36Sopenharmony_ci tmp += surf.layer_size * mslice; 47162306a36Sopenharmony_ci if (tmp <= bsize) { 47262306a36Sopenharmony_ci ib[track->cb_color_slice_idx[id]] = slice; 47362306a36Sopenharmony_ci goto old_ddx_ok; 47462306a36Sopenharmony_ci } 47562306a36Sopenharmony_ci } 47662306a36Sopenharmony_ci } 47762306a36Sopenharmony_ci } 47862306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d cb[%d] bo too small (layer size %d, " 47962306a36Sopenharmony_ci "offset %d, max layer %d, bo size %ld, slice %d)\n", 48062306a36Sopenharmony_ci __func__, __LINE__, id, surf.layer_size, 48162306a36Sopenharmony_ci track->cb_color_bo_offset[id] << 8, mslice, 48262306a36Sopenharmony_ci radeon_bo_size(track->cb_color_bo[id]), slice); 48362306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d problematic surf: (%d %d) (%d %d %d %d %d %d %d)\n", 48462306a36Sopenharmony_ci __func__, __LINE__, surf.nbx, surf.nby, 48562306a36Sopenharmony_ci surf.mode, surf.bpe, surf.nsamples, 48662306a36Sopenharmony_ci surf.bankw, surf.bankh, 48762306a36Sopenharmony_ci surf.tsplit, surf.mtilea); 48862306a36Sopenharmony_ci return -EINVAL; 48962306a36Sopenharmony_ci } 49062306a36Sopenharmony_ciold_ddx_ok: 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci return 0; 49362306a36Sopenharmony_ci} 49462306a36Sopenharmony_ci 49562306a36Sopenharmony_cistatic int evergreen_cs_track_validate_htile(struct radeon_cs_parser *p, 49662306a36Sopenharmony_ci unsigned nbx, unsigned nby) 49762306a36Sopenharmony_ci{ 49862306a36Sopenharmony_ci struct evergreen_cs_track *track = p->track; 49962306a36Sopenharmony_ci unsigned long size; 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_ci if (track->htile_bo == NULL) { 50262306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d htile enabled without htile surface 0x%08x\n", 50362306a36Sopenharmony_ci __func__, __LINE__, track->db_z_info); 50462306a36Sopenharmony_ci return -EINVAL; 50562306a36Sopenharmony_ci } 50662306a36Sopenharmony_ci 50762306a36Sopenharmony_ci if (G_028ABC_LINEAR(track->htile_surface)) { 50862306a36Sopenharmony_ci /* pitch must be 16 htiles aligned == 16 * 8 pixel aligned */ 50962306a36Sopenharmony_ci nbx = round_up(nbx, 16 * 8); 51062306a36Sopenharmony_ci /* height is npipes htiles aligned == npipes * 8 pixel aligned */ 51162306a36Sopenharmony_ci nby = round_up(nby, track->npipes * 8); 51262306a36Sopenharmony_ci } else { 51362306a36Sopenharmony_ci /* always assume 8x8 htile */ 51462306a36Sopenharmony_ci /* align is htile align * 8, htile align vary according to 51562306a36Sopenharmony_ci * number of pipe and tile width and nby 51662306a36Sopenharmony_ci */ 51762306a36Sopenharmony_ci switch (track->npipes) { 51862306a36Sopenharmony_ci case 8: 51962306a36Sopenharmony_ci /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/ 52062306a36Sopenharmony_ci nbx = round_up(nbx, 64 * 8); 52162306a36Sopenharmony_ci nby = round_up(nby, 64 * 8); 52262306a36Sopenharmony_ci break; 52362306a36Sopenharmony_ci case 4: 52462306a36Sopenharmony_ci /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/ 52562306a36Sopenharmony_ci nbx = round_up(nbx, 64 * 8); 52662306a36Sopenharmony_ci nby = round_up(nby, 32 * 8); 52762306a36Sopenharmony_ci break; 52862306a36Sopenharmony_ci case 2: 52962306a36Sopenharmony_ci /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/ 53062306a36Sopenharmony_ci nbx = round_up(nbx, 32 * 8); 53162306a36Sopenharmony_ci nby = round_up(nby, 32 * 8); 53262306a36Sopenharmony_ci break; 53362306a36Sopenharmony_ci case 1: 53462306a36Sopenharmony_ci /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/ 53562306a36Sopenharmony_ci nbx = round_up(nbx, 32 * 8); 53662306a36Sopenharmony_ci nby = round_up(nby, 16 * 8); 53762306a36Sopenharmony_ci break; 53862306a36Sopenharmony_ci default: 53962306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d invalid num pipes %d\n", 54062306a36Sopenharmony_ci __func__, __LINE__, track->npipes); 54162306a36Sopenharmony_ci return -EINVAL; 54262306a36Sopenharmony_ci } 54362306a36Sopenharmony_ci } 54462306a36Sopenharmony_ci /* compute number of htile */ 54562306a36Sopenharmony_ci nbx = nbx >> 3; 54662306a36Sopenharmony_ci nby = nby >> 3; 54762306a36Sopenharmony_ci /* size must be aligned on npipes * 2K boundary */ 54862306a36Sopenharmony_ci size = roundup(nbx * nby * 4, track->npipes * (2 << 10)); 54962306a36Sopenharmony_ci size += track->htile_offset; 55062306a36Sopenharmony_ci 55162306a36Sopenharmony_ci if (size > radeon_bo_size(track->htile_bo)) { 55262306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d htile surface too small %ld for %ld (%d %d)\n", 55362306a36Sopenharmony_ci __func__, __LINE__, radeon_bo_size(track->htile_bo), 55462306a36Sopenharmony_ci size, nbx, nby); 55562306a36Sopenharmony_ci return -EINVAL; 55662306a36Sopenharmony_ci } 55762306a36Sopenharmony_ci return 0; 55862306a36Sopenharmony_ci} 55962306a36Sopenharmony_ci 56062306a36Sopenharmony_cistatic int evergreen_cs_track_validate_stencil(struct radeon_cs_parser *p) 56162306a36Sopenharmony_ci{ 56262306a36Sopenharmony_ci struct evergreen_cs_track *track = p->track; 56362306a36Sopenharmony_ci struct eg_surface surf; 56462306a36Sopenharmony_ci unsigned pitch, slice, mslice; 56562306a36Sopenharmony_ci unsigned long offset; 56662306a36Sopenharmony_ci int r; 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_ci mslice = G_028008_SLICE_MAX(track->db_depth_view) + 1; 56962306a36Sopenharmony_ci pitch = G_028058_PITCH_TILE_MAX(track->db_depth_size); 57062306a36Sopenharmony_ci slice = track->db_depth_slice; 57162306a36Sopenharmony_ci surf.nbx = (pitch + 1) * 8; 57262306a36Sopenharmony_ci surf.nby = ((slice + 1) * 64) / surf.nbx; 57362306a36Sopenharmony_ci surf.mode = G_028040_ARRAY_MODE(track->db_z_info); 57462306a36Sopenharmony_ci surf.format = G_028044_FORMAT(track->db_s_info); 57562306a36Sopenharmony_ci surf.tsplit = G_028044_TILE_SPLIT(track->db_s_info); 57662306a36Sopenharmony_ci surf.nbanks = G_028040_NUM_BANKS(track->db_z_info); 57762306a36Sopenharmony_ci surf.bankw = G_028040_BANK_WIDTH(track->db_z_info); 57862306a36Sopenharmony_ci surf.bankh = G_028040_BANK_HEIGHT(track->db_z_info); 57962306a36Sopenharmony_ci surf.mtilea = G_028040_MACRO_TILE_ASPECT(track->db_z_info); 58062306a36Sopenharmony_ci surf.nsamples = 1; 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ci if (surf.format != 1) { 58362306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d stencil invalid format %d\n", 58462306a36Sopenharmony_ci __func__, __LINE__, surf.format); 58562306a36Sopenharmony_ci return -EINVAL; 58662306a36Sopenharmony_ci } 58762306a36Sopenharmony_ci /* replace by color format so we can use same code */ 58862306a36Sopenharmony_ci surf.format = V_028C70_COLOR_8; 58962306a36Sopenharmony_ci 59062306a36Sopenharmony_ci r = evergreen_surface_value_conv_check(p, &surf, "stencil"); 59162306a36Sopenharmony_ci if (r) { 59262306a36Sopenharmony_ci return r; 59362306a36Sopenharmony_ci } 59462306a36Sopenharmony_ci 59562306a36Sopenharmony_ci r = evergreen_surface_check(p, &surf, NULL); 59662306a36Sopenharmony_ci if (r) { 59762306a36Sopenharmony_ci /* old userspace doesn't compute proper depth/stencil alignment 59862306a36Sopenharmony_ci * check that alignment against a bigger byte per elements and 59962306a36Sopenharmony_ci * only report if that alignment is wrong too. 60062306a36Sopenharmony_ci */ 60162306a36Sopenharmony_ci surf.format = V_028C70_COLOR_8_8_8_8; 60262306a36Sopenharmony_ci r = evergreen_surface_check(p, &surf, "stencil"); 60362306a36Sopenharmony_ci if (r) { 60462306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d stencil invalid (0x%08x 0x%08x 0x%08x 0x%08x)\n", 60562306a36Sopenharmony_ci __func__, __LINE__, track->db_depth_size, 60662306a36Sopenharmony_ci track->db_depth_slice, track->db_s_info, track->db_z_info); 60762306a36Sopenharmony_ci } 60862306a36Sopenharmony_ci return r; 60962306a36Sopenharmony_ci } 61062306a36Sopenharmony_ci 61162306a36Sopenharmony_ci offset = track->db_s_read_offset << 8; 61262306a36Sopenharmony_ci if (offset & (surf.base_align - 1)) { 61362306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d stencil read bo base %ld not aligned with %ld\n", 61462306a36Sopenharmony_ci __func__, __LINE__, offset, surf.base_align); 61562306a36Sopenharmony_ci return -EINVAL; 61662306a36Sopenharmony_ci } 61762306a36Sopenharmony_ci offset += surf.layer_size * mslice; 61862306a36Sopenharmony_ci if (offset > radeon_bo_size(track->db_s_read_bo)) { 61962306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d stencil read bo too small (layer size %d, " 62062306a36Sopenharmony_ci "offset %ld, max layer %d, bo size %ld)\n", 62162306a36Sopenharmony_ci __func__, __LINE__, surf.layer_size, 62262306a36Sopenharmony_ci (unsigned long)track->db_s_read_offset << 8, mslice, 62362306a36Sopenharmony_ci radeon_bo_size(track->db_s_read_bo)); 62462306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d stencil invalid (0x%08x 0x%08x 0x%08x 0x%08x)\n", 62562306a36Sopenharmony_ci __func__, __LINE__, track->db_depth_size, 62662306a36Sopenharmony_ci track->db_depth_slice, track->db_s_info, track->db_z_info); 62762306a36Sopenharmony_ci return -EINVAL; 62862306a36Sopenharmony_ci } 62962306a36Sopenharmony_ci 63062306a36Sopenharmony_ci offset = track->db_s_write_offset << 8; 63162306a36Sopenharmony_ci if (offset & (surf.base_align - 1)) { 63262306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d stencil write bo base %ld not aligned with %ld\n", 63362306a36Sopenharmony_ci __func__, __LINE__, offset, surf.base_align); 63462306a36Sopenharmony_ci return -EINVAL; 63562306a36Sopenharmony_ci } 63662306a36Sopenharmony_ci offset += surf.layer_size * mslice; 63762306a36Sopenharmony_ci if (offset > radeon_bo_size(track->db_s_write_bo)) { 63862306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d stencil write bo too small (layer size %d, " 63962306a36Sopenharmony_ci "offset %ld, max layer %d, bo size %ld)\n", 64062306a36Sopenharmony_ci __func__, __LINE__, surf.layer_size, 64162306a36Sopenharmony_ci (unsigned long)track->db_s_write_offset << 8, mslice, 64262306a36Sopenharmony_ci radeon_bo_size(track->db_s_write_bo)); 64362306a36Sopenharmony_ci return -EINVAL; 64462306a36Sopenharmony_ci } 64562306a36Sopenharmony_ci 64662306a36Sopenharmony_ci /* hyperz */ 64762306a36Sopenharmony_ci if (G_028040_TILE_SURFACE_ENABLE(track->db_z_info)) { 64862306a36Sopenharmony_ci r = evergreen_cs_track_validate_htile(p, surf.nbx, surf.nby); 64962306a36Sopenharmony_ci if (r) { 65062306a36Sopenharmony_ci return r; 65162306a36Sopenharmony_ci } 65262306a36Sopenharmony_ci } 65362306a36Sopenharmony_ci 65462306a36Sopenharmony_ci return 0; 65562306a36Sopenharmony_ci} 65662306a36Sopenharmony_ci 65762306a36Sopenharmony_cistatic int evergreen_cs_track_validate_depth(struct radeon_cs_parser *p) 65862306a36Sopenharmony_ci{ 65962306a36Sopenharmony_ci struct evergreen_cs_track *track = p->track; 66062306a36Sopenharmony_ci struct eg_surface surf; 66162306a36Sopenharmony_ci unsigned pitch, slice, mslice; 66262306a36Sopenharmony_ci unsigned long offset; 66362306a36Sopenharmony_ci int r; 66462306a36Sopenharmony_ci 66562306a36Sopenharmony_ci mslice = G_028008_SLICE_MAX(track->db_depth_view) + 1; 66662306a36Sopenharmony_ci pitch = G_028058_PITCH_TILE_MAX(track->db_depth_size); 66762306a36Sopenharmony_ci slice = track->db_depth_slice; 66862306a36Sopenharmony_ci surf.nbx = (pitch + 1) * 8; 66962306a36Sopenharmony_ci surf.nby = ((slice + 1) * 64) / surf.nbx; 67062306a36Sopenharmony_ci surf.mode = G_028040_ARRAY_MODE(track->db_z_info); 67162306a36Sopenharmony_ci surf.format = G_028040_FORMAT(track->db_z_info); 67262306a36Sopenharmony_ci surf.tsplit = G_028040_TILE_SPLIT(track->db_z_info); 67362306a36Sopenharmony_ci surf.nbanks = G_028040_NUM_BANKS(track->db_z_info); 67462306a36Sopenharmony_ci surf.bankw = G_028040_BANK_WIDTH(track->db_z_info); 67562306a36Sopenharmony_ci surf.bankh = G_028040_BANK_HEIGHT(track->db_z_info); 67662306a36Sopenharmony_ci surf.mtilea = G_028040_MACRO_TILE_ASPECT(track->db_z_info); 67762306a36Sopenharmony_ci surf.nsamples = 1; 67862306a36Sopenharmony_ci 67962306a36Sopenharmony_ci switch (surf.format) { 68062306a36Sopenharmony_ci case V_028040_Z_16: 68162306a36Sopenharmony_ci surf.format = V_028C70_COLOR_16; 68262306a36Sopenharmony_ci break; 68362306a36Sopenharmony_ci case V_028040_Z_24: 68462306a36Sopenharmony_ci case V_028040_Z_32_FLOAT: 68562306a36Sopenharmony_ci surf.format = V_028C70_COLOR_8_8_8_8; 68662306a36Sopenharmony_ci break; 68762306a36Sopenharmony_ci default: 68862306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d depth invalid format %d\n", 68962306a36Sopenharmony_ci __func__, __LINE__, surf.format); 69062306a36Sopenharmony_ci return -EINVAL; 69162306a36Sopenharmony_ci } 69262306a36Sopenharmony_ci 69362306a36Sopenharmony_ci r = evergreen_surface_value_conv_check(p, &surf, "depth"); 69462306a36Sopenharmony_ci if (r) { 69562306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d depth invalid (0x%08x 0x%08x 0x%08x)\n", 69662306a36Sopenharmony_ci __func__, __LINE__, track->db_depth_size, 69762306a36Sopenharmony_ci track->db_depth_slice, track->db_z_info); 69862306a36Sopenharmony_ci return r; 69962306a36Sopenharmony_ci } 70062306a36Sopenharmony_ci 70162306a36Sopenharmony_ci r = evergreen_surface_check(p, &surf, "depth"); 70262306a36Sopenharmony_ci if (r) { 70362306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d depth invalid (0x%08x 0x%08x 0x%08x)\n", 70462306a36Sopenharmony_ci __func__, __LINE__, track->db_depth_size, 70562306a36Sopenharmony_ci track->db_depth_slice, track->db_z_info); 70662306a36Sopenharmony_ci return r; 70762306a36Sopenharmony_ci } 70862306a36Sopenharmony_ci 70962306a36Sopenharmony_ci offset = track->db_z_read_offset << 8; 71062306a36Sopenharmony_ci if (offset & (surf.base_align - 1)) { 71162306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d stencil read bo base %ld not aligned with %ld\n", 71262306a36Sopenharmony_ci __func__, __LINE__, offset, surf.base_align); 71362306a36Sopenharmony_ci return -EINVAL; 71462306a36Sopenharmony_ci } 71562306a36Sopenharmony_ci offset += surf.layer_size * mslice; 71662306a36Sopenharmony_ci if (offset > radeon_bo_size(track->db_z_read_bo)) { 71762306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d depth read bo too small (layer size %d, " 71862306a36Sopenharmony_ci "offset %ld, max layer %d, bo size %ld)\n", 71962306a36Sopenharmony_ci __func__, __LINE__, surf.layer_size, 72062306a36Sopenharmony_ci (unsigned long)track->db_z_read_offset << 8, mslice, 72162306a36Sopenharmony_ci radeon_bo_size(track->db_z_read_bo)); 72262306a36Sopenharmony_ci return -EINVAL; 72362306a36Sopenharmony_ci } 72462306a36Sopenharmony_ci 72562306a36Sopenharmony_ci offset = track->db_z_write_offset << 8; 72662306a36Sopenharmony_ci if (offset & (surf.base_align - 1)) { 72762306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d stencil write bo base %ld not aligned with %ld\n", 72862306a36Sopenharmony_ci __func__, __LINE__, offset, surf.base_align); 72962306a36Sopenharmony_ci return -EINVAL; 73062306a36Sopenharmony_ci } 73162306a36Sopenharmony_ci offset += surf.layer_size * mslice; 73262306a36Sopenharmony_ci if (offset > radeon_bo_size(track->db_z_write_bo)) { 73362306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d depth write bo too small (layer size %d, " 73462306a36Sopenharmony_ci "offset %ld, max layer %d, bo size %ld)\n", 73562306a36Sopenharmony_ci __func__, __LINE__, surf.layer_size, 73662306a36Sopenharmony_ci (unsigned long)track->db_z_write_offset << 8, mslice, 73762306a36Sopenharmony_ci radeon_bo_size(track->db_z_write_bo)); 73862306a36Sopenharmony_ci return -EINVAL; 73962306a36Sopenharmony_ci } 74062306a36Sopenharmony_ci 74162306a36Sopenharmony_ci /* hyperz */ 74262306a36Sopenharmony_ci if (G_028040_TILE_SURFACE_ENABLE(track->db_z_info)) { 74362306a36Sopenharmony_ci r = evergreen_cs_track_validate_htile(p, surf.nbx, surf.nby); 74462306a36Sopenharmony_ci if (r) { 74562306a36Sopenharmony_ci return r; 74662306a36Sopenharmony_ci } 74762306a36Sopenharmony_ci } 74862306a36Sopenharmony_ci 74962306a36Sopenharmony_ci return 0; 75062306a36Sopenharmony_ci} 75162306a36Sopenharmony_ci 75262306a36Sopenharmony_cistatic int evergreen_cs_track_validate_texture(struct radeon_cs_parser *p, 75362306a36Sopenharmony_ci struct radeon_bo *texture, 75462306a36Sopenharmony_ci struct radeon_bo *mipmap, 75562306a36Sopenharmony_ci unsigned idx) 75662306a36Sopenharmony_ci{ 75762306a36Sopenharmony_ci struct eg_surface surf; 75862306a36Sopenharmony_ci unsigned long toffset, moffset; 75962306a36Sopenharmony_ci unsigned dim, llevel, mslice, width, height, depth, i; 76062306a36Sopenharmony_ci u32 texdw[8]; 76162306a36Sopenharmony_ci int r; 76262306a36Sopenharmony_ci 76362306a36Sopenharmony_ci texdw[0] = radeon_get_ib_value(p, idx + 0); 76462306a36Sopenharmony_ci texdw[1] = radeon_get_ib_value(p, idx + 1); 76562306a36Sopenharmony_ci texdw[2] = radeon_get_ib_value(p, idx + 2); 76662306a36Sopenharmony_ci texdw[3] = radeon_get_ib_value(p, idx + 3); 76762306a36Sopenharmony_ci texdw[4] = radeon_get_ib_value(p, idx + 4); 76862306a36Sopenharmony_ci texdw[5] = radeon_get_ib_value(p, idx + 5); 76962306a36Sopenharmony_ci texdw[6] = radeon_get_ib_value(p, idx + 6); 77062306a36Sopenharmony_ci texdw[7] = radeon_get_ib_value(p, idx + 7); 77162306a36Sopenharmony_ci dim = G_030000_DIM(texdw[0]); 77262306a36Sopenharmony_ci llevel = G_030014_LAST_LEVEL(texdw[5]); 77362306a36Sopenharmony_ci mslice = G_030014_LAST_ARRAY(texdw[5]) + 1; 77462306a36Sopenharmony_ci width = G_030000_TEX_WIDTH(texdw[0]) + 1; 77562306a36Sopenharmony_ci height = G_030004_TEX_HEIGHT(texdw[1]) + 1; 77662306a36Sopenharmony_ci depth = G_030004_TEX_DEPTH(texdw[1]) + 1; 77762306a36Sopenharmony_ci surf.format = G_03001C_DATA_FORMAT(texdw[7]); 77862306a36Sopenharmony_ci surf.nbx = (G_030000_PITCH(texdw[0]) + 1) * 8; 77962306a36Sopenharmony_ci surf.nbx = r600_fmt_get_nblocksx(surf.format, surf.nbx); 78062306a36Sopenharmony_ci surf.nby = r600_fmt_get_nblocksy(surf.format, height); 78162306a36Sopenharmony_ci surf.mode = G_030004_ARRAY_MODE(texdw[1]); 78262306a36Sopenharmony_ci surf.tsplit = G_030018_TILE_SPLIT(texdw[6]); 78362306a36Sopenharmony_ci surf.nbanks = G_03001C_NUM_BANKS(texdw[7]); 78462306a36Sopenharmony_ci surf.bankw = G_03001C_BANK_WIDTH(texdw[7]); 78562306a36Sopenharmony_ci surf.bankh = G_03001C_BANK_HEIGHT(texdw[7]); 78662306a36Sopenharmony_ci surf.mtilea = G_03001C_MACRO_TILE_ASPECT(texdw[7]); 78762306a36Sopenharmony_ci surf.nsamples = 1; 78862306a36Sopenharmony_ci toffset = texdw[2] << 8; 78962306a36Sopenharmony_ci moffset = texdw[3] << 8; 79062306a36Sopenharmony_ci 79162306a36Sopenharmony_ci if (!r600_fmt_is_valid_texture(surf.format, p->family)) { 79262306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d texture invalid format %d\n", 79362306a36Sopenharmony_ci __func__, __LINE__, surf.format); 79462306a36Sopenharmony_ci return -EINVAL; 79562306a36Sopenharmony_ci } 79662306a36Sopenharmony_ci switch (dim) { 79762306a36Sopenharmony_ci case V_030000_SQ_TEX_DIM_1D: 79862306a36Sopenharmony_ci case V_030000_SQ_TEX_DIM_2D: 79962306a36Sopenharmony_ci case V_030000_SQ_TEX_DIM_CUBEMAP: 80062306a36Sopenharmony_ci case V_030000_SQ_TEX_DIM_1D_ARRAY: 80162306a36Sopenharmony_ci case V_030000_SQ_TEX_DIM_2D_ARRAY: 80262306a36Sopenharmony_ci depth = 1; 80362306a36Sopenharmony_ci break; 80462306a36Sopenharmony_ci case V_030000_SQ_TEX_DIM_2D_MSAA: 80562306a36Sopenharmony_ci case V_030000_SQ_TEX_DIM_2D_ARRAY_MSAA: 80662306a36Sopenharmony_ci surf.nsamples = 1 << llevel; 80762306a36Sopenharmony_ci llevel = 0; 80862306a36Sopenharmony_ci depth = 1; 80962306a36Sopenharmony_ci break; 81062306a36Sopenharmony_ci case V_030000_SQ_TEX_DIM_3D: 81162306a36Sopenharmony_ci break; 81262306a36Sopenharmony_ci default: 81362306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d texture invalid dimension %d\n", 81462306a36Sopenharmony_ci __func__, __LINE__, dim); 81562306a36Sopenharmony_ci return -EINVAL; 81662306a36Sopenharmony_ci } 81762306a36Sopenharmony_ci 81862306a36Sopenharmony_ci r = evergreen_surface_value_conv_check(p, &surf, "texture"); 81962306a36Sopenharmony_ci if (r) { 82062306a36Sopenharmony_ci return r; 82162306a36Sopenharmony_ci } 82262306a36Sopenharmony_ci 82362306a36Sopenharmony_ci /* align height */ 82462306a36Sopenharmony_ci evergreen_surface_check(p, &surf, NULL); 82562306a36Sopenharmony_ci surf.nby = ALIGN(surf.nby, surf.halign); 82662306a36Sopenharmony_ci 82762306a36Sopenharmony_ci r = evergreen_surface_check(p, &surf, "texture"); 82862306a36Sopenharmony_ci if (r) { 82962306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d texture invalid 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", 83062306a36Sopenharmony_ci __func__, __LINE__, texdw[0], texdw[1], texdw[4], 83162306a36Sopenharmony_ci texdw[5], texdw[6], texdw[7]); 83262306a36Sopenharmony_ci return r; 83362306a36Sopenharmony_ci } 83462306a36Sopenharmony_ci 83562306a36Sopenharmony_ci /* check texture size */ 83662306a36Sopenharmony_ci if (toffset & (surf.base_align - 1)) { 83762306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d texture bo base %ld not aligned with %ld\n", 83862306a36Sopenharmony_ci __func__, __LINE__, toffset, surf.base_align); 83962306a36Sopenharmony_ci return -EINVAL; 84062306a36Sopenharmony_ci } 84162306a36Sopenharmony_ci if (surf.nsamples <= 1 && moffset & (surf.base_align - 1)) { 84262306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d mipmap bo base %ld not aligned with %ld\n", 84362306a36Sopenharmony_ci __func__, __LINE__, moffset, surf.base_align); 84462306a36Sopenharmony_ci return -EINVAL; 84562306a36Sopenharmony_ci } 84662306a36Sopenharmony_ci if (dim == SQ_TEX_DIM_3D) { 84762306a36Sopenharmony_ci toffset += surf.layer_size * depth; 84862306a36Sopenharmony_ci } else { 84962306a36Sopenharmony_ci toffset += surf.layer_size * mslice; 85062306a36Sopenharmony_ci } 85162306a36Sopenharmony_ci if (toffset > radeon_bo_size(texture)) { 85262306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d texture bo too small (layer size %d, " 85362306a36Sopenharmony_ci "offset %ld, max layer %d, depth %d, bo size %ld) (%d %d)\n", 85462306a36Sopenharmony_ci __func__, __LINE__, surf.layer_size, 85562306a36Sopenharmony_ci (unsigned long)texdw[2] << 8, mslice, 85662306a36Sopenharmony_ci depth, radeon_bo_size(texture), 85762306a36Sopenharmony_ci surf.nbx, surf.nby); 85862306a36Sopenharmony_ci return -EINVAL; 85962306a36Sopenharmony_ci } 86062306a36Sopenharmony_ci 86162306a36Sopenharmony_ci if (!mipmap) { 86262306a36Sopenharmony_ci if (llevel) { 86362306a36Sopenharmony_ci dev_warn(p->dev, "%s:%i got NULL MIP_ADDRESS relocation\n", 86462306a36Sopenharmony_ci __func__, __LINE__); 86562306a36Sopenharmony_ci return -EINVAL; 86662306a36Sopenharmony_ci } else { 86762306a36Sopenharmony_ci return 0; /* everything's ok */ 86862306a36Sopenharmony_ci } 86962306a36Sopenharmony_ci } 87062306a36Sopenharmony_ci 87162306a36Sopenharmony_ci /* check mipmap size */ 87262306a36Sopenharmony_ci for (i = 1; i <= llevel; i++) { 87362306a36Sopenharmony_ci unsigned w, h, d; 87462306a36Sopenharmony_ci 87562306a36Sopenharmony_ci w = r600_mip_minify(width, i); 87662306a36Sopenharmony_ci h = r600_mip_minify(height, i); 87762306a36Sopenharmony_ci d = r600_mip_minify(depth, i); 87862306a36Sopenharmony_ci surf.nbx = r600_fmt_get_nblocksx(surf.format, w); 87962306a36Sopenharmony_ci surf.nby = r600_fmt_get_nblocksy(surf.format, h); 88062306a36Sopenharmony_ci 88162306a36Sopenharmony_ci switch (surf.mode) { 88262306a36Sopenharmony_ci case ARRAY_2D_TILED_THIN1: 88362306a36Sopenharmony_ci if (surf.nbx < surf.palign || surf.nby < surf.halign) { 88462306a36Sopenharmony_ci surf.mode = ARRAY_1D_TILED_THIN1; 88562306a36Sopenharmony_ci } 88662306a36Sopenharmony_ci /* recompute alignment */ 88762306a36Sopenharmony_ci evergreen_surface_check(p, &surf, NULL); 88862306a36Sopenharmony_ci break; 88962306a36Sopenharmony_ci case ARRAY_LINEAR_GENERAL: 89062306a36Sopenharmony_ci case ARRAY_LINEAR_ALIGNED: 89162306a36Sopenharmony_ci case ARRAY_1D_TILED_THIN1: 89262306a36Sopenharmony_ci break; 89362306a36Sopenharmony_ci default: 89462306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d invalid array mode %d\n", 89562306a36Sopenharmony_ci __func__, __LINE__, surf.mode); 89662306a36Sopenharmony_ci return -EINVAL; 89762306a36Sopenharmony_ci } 89862306a36Sopenharmony_ci surf.nbx = ALIGN(surf.nbx, surf.palign); 89962306a36Sopenharmony_ci surf.nby = ALIGN(surf.nby, surf.halign); 90062306a36Sopenharmony_ci 90162306a36Sopenharmony_ci r = evergreen_surface_check(p, &surf, "mipmap"); 90262306a36Sopenharmony_ci if (r) { 90362306a36Sopenharmony_ci return r; 90462306a36Sopenharmony_ci } 90562306a36Sopenharmony_ci 90662306a36Sopenharmony_ci if (dim == SQ_TEX_DIM_3D) { 90762306a36Sopenharmony_ci moffset += surf.layer_size * d; 90862306a36Sopenharmony_ci } else { 90962306a36Sopenharmony_ci moffset += surf.layer_size * mslice; 91062306a36Sopenharmony_ci } 91162306a36Sopenharmony_ci if (moffset > radeon_bo_size(mipmap)) { 91262306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d mipmap [%d] bo too small (layer size %d, " 91362306a36Sopenharmony_ci "offset %ld, coffset %ld, max layer %d, depth %d, " 91462306a36Sopenharmony_ci "bo size %ld) level0 (%d %d %d)\n", 91562306a36Sopenharmony_ci __func__, __LINE__, i, surf.layer_size, 91662306a36Sopenharmony_ci (unsigned long)texdw[3] << 8, moffset, mslice, 91762306a36Sopenharmony_ci d, radeon_bo_size(mipmap), 91862306a36Sopenharmony_ci width, height, depth); 91962306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d problematic surf: (%d %d) (%d %d %d %d %d %d %d)\n", 92062306a36Sopenharmony_ci __func__, __LINE__, surf.nbx, surf.nby, 92162306a36Sopenharmony_ci surf.mode, surf.bpe, surf.nsamples, 92262306a36Sopenharmony_ci surf.bankw, surf.bankh, 92362306a36Sopenharmony_ci surf.tsplit, surf.mtilea); 92462306a36Sopenharmony_ci return -EINVAL; 92562306a36Sopenharmony_ci } 92662306a36Sopenharmony_ci } 92762306a36Sopenharmony_ci 92862306a36Sopenharmony_ci return 0; 92962306a36Sopenharmony_ci} 93062306a36Sopenharmony_ci 93162306a36Sopenharmony_cistatic int evergreen_cs_track_check(struct radeon_cs_parser *p) 93262306a36Sopenharmony_ci{ 93362306a36Sopenharmony_ci struct evergreen_cs_track *track = p->track; 93462306a36Sopenharmony_ci unsigned tmp, i; 93562306a36Sopenharmony_ci int r; 93662306a36Sopenharmony_ci unsigned buffer_mask = 0; 93762306a36Sopenharmony_ci 93862306a36Sopenharmony_ci /* check streamout */ 93962306a36Sopenharmony_ci if (track->streamout_dirty && track->vgt_strmout_config) { 94062306a36Sopenharmony_ci for (i = 0; i < 4; i++) { 94162306a36Sopenharmony_ci if (track->vgt_strmout_config & (1 << i)) { 94262306a36Sopenharmony_ci buffer_mask |= (track->vgt_strmout_buffer_config >> (i * 4)) & 0xf; 94362306a36Sopenharmony_ci } 94462306a36Sopenharmony_ci } 94562306a36Sopenharmony_ci 94662306a36Sopenharmony_ci for (i = 0; i < 4; i++) { 94762306a36Sopenharmony_ci if (buffer_mask & (1 << i)) { 94862306a36Sopenharmony_ci if (track->vgt_strmout_bo[i]) { 94962306a36Sopenharmony_ci u64 offset = (u64)track->vgt_strmout_bo_offset[i] + 95062306a36Sopenharmony_ci (u64)track->vgt_strmout_size[i]; 95162306a36Sopenharmony_ci if (offset > radeon_bo_size(track->vgt_strmout_bo[i])) { 95262306a36Sopenharmony_ci DRM_ERROR("streamout %d bo too small: 0x%llx, 0x%lx\n", 95362306a36Sopenharmony_ci i, offset, 95462306a36Sopenharmony_ci radeon_bo_size(track->vgt_strmout_bo[i])); 95562306a36Sopenharmony_ci return -EINVAL; 95662306a36Sopenharmony_ci } 95762306a36Sopenharmony_ci } else { 95862306a36Sopenharmony_ci dev_warn(p->dev, "No buffer for streamout %d\n", i); 95962306a36Sopenharmony_ci return -EINVAL; 96062306a36Sopenharmony_ci } 96162306a36Sopenharmony_ci } 96262306a36Sopenharmony_ci } 96362306a36Sopenharmony_ci track->streamout_dirty = false; 96462306a36Sopenharmony_ci } 96562306a36Sopenharmony_ci 96662306a36Sopenharmony_ci if (track->sx_misc_kill_all_prims) 96762306a36Sopenharmony_ci return 0; 96862306a36Sopenharmony_ci 96962306a36Sopenharmony_ci /* check that we have a cb for each enabled target 97062306a36Sopenharmony_ci */ 97162306a36Sopenharmony_ci if (track->cb_dirty) { 97262306a36Sopenharmony_ci tmp = track->cb_target_mask; 97362306a36Sopenharmony_ci for (i = 0; i < 8; i++) { 97462306a36Sopenharmony_ci u32 format = G_028C70_FORMAT(track->cb_color_info[i]); 97562306a36Sopenharmony_ci 97662306a36Sopenharmony_ci if (format != V_028C70_COLOR_INVALID && 97762306a36Sopenharmony_ci (tmp >> (i * 4)) & 0xF) { 97862306a36Sopenharmony_ci /* at least one component is enabled */ 97962306a36Sopenharmony_ci if (track->cb_color_bo[i] == NULL) { 98062306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d mask 0x%08X | 0x%08X no cb for %d\n", 98162306a36Sopenharmony_ci __func__, __LINE__, track->cb_target_mask, track->cb_shader_mask, i); 98262306a36Sopenharmony_ci return -EINVAL; 98362306a36Sopenharmony_ci } 98462306a36Sopenharmony_ci /* check cb */ 98562306a36Sopenharmony_ci r = evergreen_cs_track_validate_cb(p, i); 98662306a36Sopenharmony_ci if (r) { 98762306a36Sopenharmony_ci return r; 98862306a36Sopenharmony_ci } 98962306a36Sopenharmony_ci } 99062306a36Sopenharmony_ci } 99162306a36Sopenharmony_ci track->cb_dirty = false; 99262306a36Sopenharmony_ci } 99362306a36Sopenharmony_ci 99462306a36Sopenharmony_ci if (track->db_dirty) { 99562306a36Sopenharmony_ci /* Check stencil buffer */ 99662306a36Sopenharmony_ci if (G_028044_FORMAT(track->db_s_info) != V_028044_STENCIL_INVALID && 99762306a36Sopenharmony_ci G_028800_STENCIL_ENABLE(track->db_depth_control)) { 99862306a36Sopenharmony_ci r = evergreen_cs_track_validate_stencil(p); 99962306a36Sopenharmony_ci if (r) 100062306a36Sopenharmony_ci return r; 100162306a36Sopenharmony_ci } 100262306a36Sopenharmony_ci /* Check depth buffer */ 100362306a36Sopenharmony_ci if (G_028040_FORMAT(track->db_z_info) != V_028040_Z_INVALID && 100462306a36Sopenharmony_ci G_028800_Z_ENABLE(track->db_depth_control)) { 100562306a36Sopenharmony_ci r = evergreen_cs_track_validate_depth(p); 100662306a36Sopenharmony_ci if (r) 100762306a36Sopenharmony_ci return r; 100862306a36Sopenharmony_ci } 100962306a36Sopenharmony_ci track->db_dirty = false; 101062306a36Sopenharmony_ci } 101162306a36Sopenharmony_ci 101262306a36Sopenharmony_ci return 0; 101362306a36Sopenharmony_ci} 101462306a36Sopenharmony_ci 101562306a36Sopenharmony_ci/** 101662306a36Sopenharmony_ci * evergreen_cs_packet_parse_vline() - parse userspace VLINE packet 101762306a36Sopenharmony_ci * @p: parser structure holding parsing context. 101862306a36Sopenharmony_ci * 101962306a36Sopenharmony_ci * This is an Evergreen(+)-specific function for parsing VLINE packets. 102062306a36Sopenharmony_ci * Real work is done by r600_cs_common_vline_parse function. 102162306a36Sopenharmony_ci * Here we just set up ASIC-specific register table and call 102262306a36Sopenharmony_ci * the common implementation function. 102362306a36Sopenharmony_ci */ 102462306a36Sopenharmony_cistatic int evergreen_cs_packet_parse_vline(struct radeon_cs_parser *p) 102562306a36Sopenharmony_ci{ 102662306a36Sopenharmony_ci 102762306a36Sopenharmony_ci static uint32_t vline_start_end[6] = { 102862306a36Sopenharmony_ci EVERGREEN_VLINE_START_END + EVERGREEN_CRTC0_REGISTER_OFFSET, 102962306a36Sopenharmony_ci EVERGREEN_VLINE_START_END + EVERGREEN_CRTC1_REGISTER_OFFSET, 103062306a36Sopenharmony_ci EVERGREEN_VLINE_START_END + EVERGREEN_CRTC2_REGISTER_OFFSET, 103162306a36Sopenharmony_ci EVERGREEN_VLINE_START_END + EVERGREEN_CRTC3_REGISTER_OFFSET, 103262306a36Sopenharmony_ci EVERGREEN_VLINE_START_END + EVERGREEN_CRTC4_REGISTER_OFFSET, 103362306a36Sopenharmony_ci EVERGREEN_VLINE_START_END + EVERGREEN_CRTC5_REGISTER_OFFSET 103462306a36Sopenharmony_ci }; 103562306a36Sopenharmony_ci static uint32_t vline_status[6] = { 103662306a36Sopenharmony_ci EVERGREEN_VLINE_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, 103762306a36Sopenharmony_ci EVERGREEN_VLINE_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, 103862306a36Sopenharmony_ci EVERGREEN_VLINE_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, 103962306a36Sopenharmony_ci EVERGREEN_VLINE_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, 104062306a36Sopenharmony_ci EVERGREEN_VLINE_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, 104162306a36Sopenharmony_ci EVERGREEN_VLINE_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET 104262306a36Sopenharmony_ci }; 104362306a36Sopenharmony_ci 104462306a36Sopenharmony_ci return r600_cs_common_vline_parse(p, vline_start_end, vline_status); 104562306a36Sopenharmony_ci} 104662306a36Sopenharmony_ci 104762306a36Sopenharmony_cistatic int evergreen_packet0_check(struct radeon_cs_parser *p, 104862306a36Sopenharmony_ci struct radeon_cs_packet *pkt, 104962306a36Sopenharmony_ci unsigned idx, unsigned reg) 105062306a36Sopenharmony_ci{ 105162306a36Sopenharmony_ci int r; 105262306a36Sopenharmony_ci 105362306a36Sopenharmony_ci switch (reg) { 105462306a36Sopenharmony_ci case EVERGREEN_VLINE_START_END: 105562306a36Sopenharmony_ci r = evergreen_cs_packet_parse_vline(p); 105662306a36Sopenharmony_ci if (r) { 105762306a36Sopenharmony_ci DRM_ERROR("No reloc for ib[%d]=0x%04X\n", 105862306a36Sopenharmony_ci idx, reg); 105962306a36Sopenharmony_ci return r; 106062306a36Sopenharmony_ci } 106162306a36Sopenharmony_ci break; 106262306a36Sopenharmony_ci default: 106362306a36Sopenharmony_ci pr_err("Forbidden register 0x%04X in cs at %d\n", reg, idx); 106462306a36Sopenharmony_ci return -EINVAL; 106562306a36Sopenharmony_ci } 106662306a36Sopenharmony_ci return 0; 106762306a36Sopenharmony_ci} 106862306a36Sopenharmony_ci 106962306a36Sopenharmony_cistatic int evergreen_cs_parse_packet0(struct radeon_cs_parser *p, 107062306a36Sopenharmony_ci struct radeon_cs_packet *pkt) 107162306a36Sopenharmony_ci{ 107262306a36Sopenharmony_ci unsigned reg, i; 107362306a36Sopenharmony_ci unsigned idx; 107462306a36Sopenharmony_ci int r; 107562306a36Sopenharmony_ci 107662306a36Sopenharmony_ci idx = pkt->idx + 1; 107762306a36Sopenharmony_ci reg = pkt->reg; 107862306a36Sopenharmony_ci for (i = 0; i <= pkt->count; i++, idx++, reg += 4) { 107962306a36Sopenharmony_ci r = evergreen_packet0_check(p, pkt, idx, reg); 108062306a36Sopenharmony_ci if (r) { 108162306a36Sopenharmony_ci return r; 108262306a36Sopenharmony_ci } 108362306a36Sopenharmony_ci } 108462306a36Sopenharmony_ci return 0; 108562306a36Sopenharmony_ci} 108662306a36Sopenharmony_ci 108762306a36Sopenharmony_ci/** 108862306a36Sopenharmony_ci * evergreen_cs_handle_reg() - process registers that need special handling. 108962306a36Sopenharmony_ci * @p: parser structure holding parsing context 109062306a36Sopenharmony_ci * @reg: register we are testing 109162306a36Sopenharmony_ci * @idx: index into the cs buffer 109262306a36Sopenharmony_ci */ 109362306a36Sopenharmony_cistatic int evergreen_cs_handle_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) 109462306a36Sopenharmony_ci{ 109562306a36Sopenharmony_ci struct evergreen_cs_track *track = (struct evergreen_cs_track *)p->track; 109662306a36Sopenharmony_ci struct radeon_bo_list *reloc; 109762306a36Sopenharmony_ci u32 tmp, *ib; 109862306a36Sopenharmony_ci int r; 109962306a36Sopenharmony_ci 110062306a36Sopenharmony_ci ib = p->ib.ptr; 110162306a36Sopenharmony_ci switch (reg) { 110262306a36Sopenharmony_ci /* force following reg to 0 in an attempt to disable out buffer 110362306a36Sopenharmony_ci * which will need us to better understand how it works to perform 110462306a36Sopenharmony_ci * security check on it (Jerome) 110562306a36Sopenharmony_ci */ 110662306a36Sopenharmony_ci case SQ_ESGS_RING_SIZE: 110762306a36Sopenharmony_ci case SQ_GSVS_RING_SIZE: 110862306a36Sopenharmony_ci case SQ_ESTMP_RING_SIZE: 110962306a36Sopenharmony_ci case SQ_GSTMP_RING_SIZE: 111062306a36Sopenharmony_ci case SQ_HSTMP_RING_SIZE: 111162306a36Sopenharmony_ci case SQ_LSTMP_RING_SIZE: 111262306a36Sopenharmony_ci case SQ_PSTMP_RING_SIZE: 111362306a36Sopenharmony_ci case SQ_VSTMP_RING_SIZE: 111462306a36Sopenharmony_ci case SQ_ESGS_RING_ITEMSIZE: 111562306a36Sopenharmony_ci case SQ_ESTMP_RING_ITEMSIZE: 111662306a36Sopenharmony_ci case SQ_GSTMP_RING_ITEMSIZE: 111762306a36Sopenharmony_ci case SQ_GSVS_RING_ITEMSIZE: 111862306a36Sopenharmony_ci case SQ_GS_VERT_ITEMSIZE: 111962306a36Sopenharmony_ci case SQ_GS_VERT_ITEMSIZE_1: 112062306a36Sopenharmony_ci case SQ_GS_VERT_ITEMSIZE_2: 112162306a36Sopenharmony_ci case SQ_GS_VERT_ITEMSIZE_3: 112262306a36Sopenharmony_ci case SQ_GSVS_RING_OFFSET_1: 112362306a36Sopenharmony_ci case SQ_GSVS_RING_OFFSET_2: 112462306a36Sopenharmony_ci case SQ_GSVS_RING_OFFSET_3: 112562306a36Sopenharmony_ci case SQ_HSTMP_RING_ITEMSIZE: 112662306a36Sopenharmony_ci case SQ_LSTMP_RING_ITEMSIZE: 112762306a36Sopenharmony_ci case SQ_PSTMP_RING_ITEMSIZE: 112862306a36Sopenharmony_ci case SQ_VSTMP_RING_ITEMSIZE: 112962306a36Sopenharmony_ci case VGT_TF_RING_SIZE: 113062306a36Sopenharmony_ci /* get value to populate the IB don't remove */ 113162306a36Sopenharmony_ci /*tmp =radeon_get_ib_value(p, idx); 113262306a36Sopenharmony_ci ib[idx] = 0;*/ 113362306a36Sopenharmony_ci break; 113462306a36Sopenharmony_ci case SQ_ESGS_RING_BASE: 113562306a36Sopenharmony_ci case SQ_GSVS_RING_BASE: 113662306a36Sopenharmony_ci case SQ_ESTMP_RING_BASE: 113762306a36Sopenharmony_ci case SQ_GSTMP_RING_BASE: 113862306a36Sopenharmony_ci case SQ_HSTMP_RING_BASE: 113962306a36Sopenharmony_ci case SQ_LSTMP_RING_BASE: 114062306a36Sopenharmony_ci case SQ_PSTMP_RING_BASE: 114162306a36Sopenharmony_ci case SQ_VSTMP_RING_BASE: 114262306a36Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 114362306a36Sopenharmony_ci if (r) { 114462306a36Sopenharmony_ci dev_warn(p->dev, "bad SET_CONTEXT_REG " 114562306a36Sopenharmony_ci "0x%04X\n", reg); 114662306a36Sopenharmony_ci return -EINVAL; 114762306a36Sopenharmony_ci } 114862306a36Sopenharmony_ci ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff); 114962306a36Sopenharmony_ci break; 115062306a36Sopenharmony_ci case DB_DEPTH_CONTROL: 115162306a36Sopenharmony_ci track->db_depth_control = radeon_get_ib_value(p, idx); 115262306a36Sopenharmony_ci track->db_dirty = true; 115362306a36Sopenharmony_ci break; 115462306a36Sopenharmony_ci case CAYMAN_DB_EQAA: 115562306a36Sopenharmony_ci if (p->rdev->family < CHIP_CAYMAN) { 115662306a36Sopenharmony_ci dev_warn(p->dev, "bad SET_CONTEXT_REG " 115762306a36Sopenharmony_ci "0x%04X\n", reg); 115862306a36Sopenharmony_ci return -EINVAL; 115962306a36Sopenharmony_ci } 116062306a36Sopenharmony_ci break; 116162306a36Sopenharmony_ci case CAYMAN_DB_DEPTH_INFO: 116262306a36Sopenharmony_ci if (p->rdev->family < CHIP_CAYMAN) { 116362306a36Sopenharmony_ci dev_warn(p->dev, "bad SET_CONTEXT_REG " 116462306a36Sopenharmony_ci "0x%04X\n", reg); 116562306a36Sopenharmony_ci return -EINVAL; 116662306a36Sopenharmony_ci } 116762306a36Sopenharmony_ci break; 116862306a36Sopenharmony_ci case DB_Z_INFO: 116962306a36Sopenharmony_ci track->db_z_info = radeon_get_ib_value(p, idx); 117062306a36Sopenharmony_ci if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { 117162306a36Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 117262306a36Sopenharmony_ci if (r) { 117362306a36Sopenharmony_ci dev_warn(p->dev, "bad SET_CONTEXT_REG " 117462306a36Sopenharmony_ci "0x%04X\n", reg); 117562306a36Sopenharmony_ci return -EINVAL; 117662306a36Sopenharmony_ci } 117762306a36Sopenharmony_ci ib[idx] &= ~Z_ARRAY_MODE(0xf); 117862306a36Sopenharmony_ci track->db_z_info &= ~Z_ARRAY_MODE(0xf); 117962306a36Sopenharmony_ci ib[idx] |= Z_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->tiling_flags)); 118062306a36Sopenharmony_ci track->db_z_info |= Z_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->tiling_flags)); 118162306a36Sopenharmony_ci if (reloc->tiling_flags & RADEON_TILING_MACRO) { 118262306a36Sopenharmony_ci unsigned bankw, bankh, mtaspect, tile_split; 118362306a36Sopenharmony_ci 118462306a36Sopenharmony_ci evergreen_tiling_fields(reloc->tiling_flags, 118562306a36Sopenharmony_ci &bankw, &bankh, &mtaspect, 118662306a36Sopenharmony_ci &tile_split); 118762306a36Sopenharmony_ci ib[idx] |= DB_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks)); 118862306a36Sopenharmony_ci ib[idx] |= DB_TILE_SPLIT(tile_split) | 118962306a36Sopenharmony_ci DB_BANK_WIDTH(bankw) | 119062306a36Sopenharmony_ci DB_BANK_HEIGHT(bankh) | 119162306a36Sopenharmony_ci DB_MACRO_TILE_ASPECT(mtaspect); 119262306a36Sopenharmony_ci } 119362306a36Sopenharmony_ci } 119462306a36Sopenharmony_ci track->db_dirty = true; 119562306a36Sopenharmony_ci break; 119662306a36Sopenharmony_ci case DB_STENCIL_INFO: 119762306a36Sopenharmony_ci track->db_s_info = radeon_get_ib_value(p, idx); 119862306a36Sopenharmony_ci track->db_dirty = true; 119962306a36Sopenharmony_ci break; 120062306a36Sopenharmony_ci case DB_DEPTH_VIEW: 120162306a36Sopenharmony_ci track->db_depth_view = radeon_get_ib_value(p, idx); 120262306a36Sopenharmony_ci track->db_dirty = true; 120362306a36Sopenharmony_ci break; 120462306a36Sopenharmony_ci case DB_DEPTH_SIZE: 120562306a36Sopenharmony_ci track->db_depth_size = radeon_get_ib_value(p, idx); 120662306a36Sopenharmony_ci track->db_dirty = true; 120762306a36Sopenharmony_ci break; 120862306a36Sopenharmony_ci case R_02805C_DB_DEPTH_SLICE: 120962306a36Sopenharmony_ci track->db_depth_slice = radeon_get_ib_value(p, idx); 121062306a36Sopenharmony_ci track->db_dirty = true; 121162306a36Sopenharmony_ci break; 121262306a36Sopenharmony_ci case DB_Z_READ_BASE: 121362306a36Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 121462306a36Sopenharmony_ci if (r) { 121562306a36Sopenharmony_ci dev_warn(p->dev, "bad SET_CONTEXT_REG " 121662306a36Sopenharmony_ci "0x%04X\n", reg); 121762306a36Sopenharmony_ci return -EINVAL; 121862306a36Sopenharmony_ci } 121962306a36Sopenharmony_ci track->db_z_read_offset = radeon_get_ib_value(p, idx); 122062306a36Sopenharmony_ci ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff); 122162306a36Sopenharmony_ci track->db_z_read_bo = reloc->robj; 122262306a36Sopenharmony_ci track->db_dirty = true; 122362306a36Sopenharmony_ci break; 122462306a36Sopenharmony_ci case DB_Z_WRITE_BASE: 122562306a36Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 122662306a36Sopenharmony_ci if (r) { 122762306a36Sopenharmony_ci dev_warn(p->dev, "bad SET_CONTEXT_REG " 122862306a36Sopenharmony_ci "0x%04X\n", reg); 122962306a36Sopenharmony_ci return -EINVAL; 123062306a36Sopenharmony_ci } 123162306a36Sopenharmony_ci track->db_z_write_offset = radeon_get_ib_value(p, idx); 123262306a36Sopenharmony_ci ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff); 123362306a36Sopenharmony_ci track->db_z_write_bo = reloc->robj; 123462306a36Sopenharmony_ci track->db_dirty = true; 123562306a36Sopenharmony_ci break; 123662306a36Sopenharmony_ci case DB_STENCIL_READ_BASE: 123762306a36Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 123862306a36Sopenharmony_ci if (r) { 123962306a36Sopenharmony_ci dev_warn(p->dev, "bad SET_CONTEXT_REG " 124062306a36Sopenharmony_ci "0x%04X\n", reg); 124162306a36Sopenharmony_ci return -EINVAL; 124262306a36Sopenharmony_ci } 124362306a36Sopenharmony_ci track->db_s_read_offset = radeon_get_ib_value(p, idx); 124462306a36Sopenharmony_ci ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff); 124562306a36Sopenharmony_ci track->db_s_read_bo = reloc->robj; 124662306a36Sopenharmony_ci track->db_dirty = true; 124762306a36Sopenharmony_ci break; 124862306a36Sopenharmony_ci case DB_STENCIL_WRITE_BASE: 124962306a36Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 125062306a36Sopenharmony_ci if (r) { 125162306a36Sopenharmony_ci dev_warn(p->dev, "bad SET_CONTEXT_REG " 125262306a36Sopenharmony_ci "0x%04X\n", reg); 125362306a36Sopenharmony_ci return -EINVAL; 125462306a36Sopenharmony_ci } 125562306a36Sopenharmony_ci track->db_s_write_offset = radeon_get_ib_value(p, idx); 125662306a36Sopenharmony_ci ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff); 125762306a36Sopenharmony_ci track->db_s_write_bo = reloc->robj; 125862306a36Sopenharmony_ci track->db_dirty = true; 125962306a36Sopenharmony_ci break; 126062306a36Sopenharmony_ci case VGT_STRMOUT_CONFIG: 126162306a36Sopenharmony_ci track->vgt_strmout_config = radeon_get_ib_value(p, idx); 126262306a36Sopenharmony_ci track->streamout_dirty = true; 126362306a36Sopenharmony_ci break; 126462306a36Sopenharmony_ci case VGT_STRMOUT_BUFFER_CONFIG: 126562306a36Sopenharmony_ci track->vgt_strmout_buffer_config = radeon_get_ib_value(p, idx); 126662306a36Sopenharmony_ci track->streamout_dirty = true; 126762306a36Sopenharmony_ci break; 126862306a36Sopenharmony_ci case VGT_STRMOUT_BUFFER_BASE_0: 126962306a36Sopenharmony_ci case VGT_STRMOUT_BUFFER_BASE_1: 127062306a36Sopenharmony_ci case VGT_STRMOUT_BUFFER_BASE_2: 127162306a36Sopenharmony_ci case VGT_STRMOUT_BUFFER_BASE_3: 127262306a36Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 127362306a36Sopenharmony_ci if (r) { 127462306a36Sopenharmony_ci dev_warn(p->dev, "bad SET_CONTEXT_REG " 127562306a36Sopenharmony_ci "0x%04X\n", reg); 127662306a36Sopenharmony_ci return -EINVAL; 127762306a36Sopenharmony_ci } 127862306a36Sopenharmony_ci tmp = (reg - VGT_STRMOUT_BUFFER_BASE_0) / 16; 127962306a36Sopenharmony_ci track->vgt_strmout_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8; 128062306a36Sopenharmony_ci ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff); 128162306a36Sopenharmony_ci track->vgt_strmout_bo[tmp] = reloc->robj; 128262306a36Sopenharmony_ci track->streamout_dirty = true; 128362306a36Sopenharmony_ci break; 128462306a36Sopenharmony_ci case VGT_STRMOUT_BUFFER_SIZE_0: 128562306a36Sopenharmony_ci case VGT_STRMOUT_BUFFER_SIZE_1: 128662306a36Sopenharmony_ci case VGT_STRMOUT_BUFFER_SIZE_2: 128762306a36Sopenharmony_ci case VGT_STRMOUT_BUFFER_SIZE_3: 128862306a36Sopenharmony_ci tmp = (reg - VGT_STRMOUT_BUFFER_SIZE_0) / 16; 128962306a36Sopenharmony_ci /* size in register is DWs, convert to bytes */ 129062306a36Sopenharmony_ci track->vgt_strmout_size[tmp] = radeon_get_ib_value(p, idx) * 4; 129162306a36Sopenharmony_ci track->streamout_dirty = true; 129262306a36Sopenharmony_ci break; 129362306a36Sopenharmony_ci case CP_COHER_BASE: 129462306a36Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 129562306a36Sopenharmony_ci if (r) { 129662306a36Sopenharmony_ci dev_warn(p->dev, "missing reloc for CP_COHER_BASE " 129762306a36Sopenharmony_ci "0x%04X\n", reg); 129862306a36Sopenharmony_ci return -EINVAL; 129962306a36Sopenharmony_ci } 130062306a36Sopenharmony_ci ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff); 130162306a36Sopenharmony_ci break; 130262306a36Sopenharmony_ci case CB_TARGET_MASK: 130362306a36Sopenharmony_ci track->cb_target_mask = radeon_get_ib_value(p, idx); 130462306a36Sopenharmony_ci track->cb_dirty = true; 130562306a36Sopenharmony_ci break; 130662306a36Sopenharmony_ci case CB_SHADER_MASK: 130762306a36Sopenharmony_ci track->cb_shader_mask = radeon_get_ib_value(p, idx); 130862306a36Sopenharmony_ci track->cb_dirty = true; 130962306a36Sopenharmony_ci break; 131062306a36Sopenharmony_ci case PA_SC_AA_CONFIG: 131162306a36Sopenharmony_ci if (p->rdev->family >= CHIP_CAYMAN) { 131262306a36Sopenharmony_ci dev_warn(p->dev, "bad SET_CONTEXT_REG " 131362306a36Sopenharmony_ci "0x%04X\n", reg); 131462306a36Sopenharmony_ci return -EINVAL; 131562306a36Sopenharmony_ci } 131662306a36Sopenharmony_ci tmp = radeon_get_ib_value(p, idx) & MSAA_NUM_SAMPLES_MASK; 131762306a36Sopenharmony_ci track->nsamples = 1 << tmp; 131862306a36Sopenharmony_ci break; 131962306a36Sopenharmony_ci case CAYMAN_PA_SC_AA_CONFIG: 132062306a36Sopenharmony_ci if (p->rdev->family < CHIP_CAYMAN) { 132162306a36Sopenharmony_ci dev_warn(p->dev, "bad SET_CONTEXT_REG " 132262306a36Sopenharmony_ci "0x%04X\n", reg); 132362306a36Sopenharmony_ci return -EINVAL; 132462306a36Sopenharmony_ci } 132562306a36Sopenharmony_ci tmp = radeon_get_ib_value(p, idx) & CAYMAN_MSAA_NUM_SAMPLES_MASK; 132662306a36Sopenharmony_ci track->nsamples = 1 << tmp; 132762306a36Sopenharmony_ci break; 132862306a36Sopenharmony_ci case CB_COLOR0_VIEW: 132962306a36Sopenharmony_ci case CB_COLOR1_VIEW: 133062306a36Sopenharmony_ci case CB_COLOR2_VIEW: 133162306a36Sopenharmony_ci case CB_COLOR3_VIEW: 133262306a36Sopenharmony_ci case CB_COLOR4_VIEW: 133362306a36Sopenharmony_ci case CB_COLOR5_VIEW: 133462306a36Sopenharmony_ci case CB_COLOR6_VIEW: 133562306a36Sopenharmony_ci case CB_COLOR7_VIEW: 133662306a36Sopenharmony_ci tmp = (reg - CB_COLOR0_VIEW) / 0x3c; 133762306a36Sopenharmony_ci track->cb_color_view[tmp] = radeon_get_ib_value(p, idx); 133862306a36Sopenharmony_ci track->cb_dirty = true; 133962306a36Sopenharmony_ci break; 134062306a36Sopenharmony_ci case CB_COLOR8_VIEW: 134162306a36Sopenharmony_ci case CB_COLOR9_VIEW: 134262306a36Sopenharmony_ci case CB_COLOR10_VIEW: 134362306a36Sopenharmony_ci case CB_COLOR11_VIEW: 134462306a36Sopenharmony_ci tmp = ((reg - CB_COLOR8_VIEW) / 0x1c) + 8; 134562306a36Sopenharmony_ci track->cb_color_view[tmp] = radeon_get_ib_value(p, idx); 134662306a36Sopenharmony_ci track->cb_dirty = true; 134762306a36Sopenharmony_ci break; 134862306a36Sopenharmony_ci case CB_COLOR0_INFO: 134962306a36Sopenharmony_ci case CB_COLOR1_INFO: 135062306a36Sopenharmony_ci case CB_COLOR2_INFO: 135162306a36Sopenharmony_ci case CB_COLOR3_INFO: 135262306a36Sopenharmony_ci case CB_COLOR4_INFO: 135362306a36Sopenharmony_ci case CB_COLOR5_INFO: 135462306a36Sopenharmony_ci case CB_COLOR6_INFO: 135562306a36Sopenharmony_ci case CB_COLOR7_INFO: 135662306a36Sopenharmony_ci tmp = (reg - CB_COLOR0_INFO) / 0x3c; 135762306a36Sopenharmony_ci track->cb_color_info[tmp] = radeon_get_ib_value(p, idx); 135862306a36Sopenharmony_ci if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { 135962306a36Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 136062306a36Sopenharmony_ci if (r) { 136162306a36Sopenharmony_ci dev_warn(p->dev, "bad SET_CONTEXT_REG " 136262306a36Sopenharmony_ci "0x%04X\n", reg); 136362306a36Sopenharmony_ci return -EINVAL; 136462306a36Sopenharmony_ci } 136562306a36Sopenharmony_ci ib[idx] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->tiling_flags)); 136662306a36Sopenharmony_ci track->cb_color_info[tmp] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->tiling_flags)); 136762306a36Sopenharmony_ci } 136862306a36Sopenharmony_ci track->cb_dirty = true; 136962306a36Sopenharmony_ci break; 137062306a36Sopenharmony_ci case CB_COLOR8_INFO: 137162306a36Sopenharmony_ci case CB_COLOR9_INFO: 137262306a36Sopenharmony_ci case CB_COLOR10_INFO: 137362306a36Sopenharmony_ci case CB_COLOR11_INFO: 137462306a36Sopenharmony_ci tmp = ((reg - CB_COLOR8_INFO) / 0x1c) + 8; 137562306a36Sopenharmony_ci track->cb_color_info[tmp] = radeon_get_ib_value(p, idx); 137662306a36Sopenharmony_ci if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { 137762306a36Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 137862306a36Sopenharmony_ci if (r) { 137962306a36Sopenharmony_ci dev_warn(p->dev, "bad SET_CONTEXT_REG " 138062306a36Sopenharmony_ci "0x%04X\n", reg); 138162306a36Sopenharmony_ci return -EINVAL; 138262306a36Sopenharmony_ci } 138362306a36Sopenharmony_ci ib[idx] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->tiling_flags)); 138462306a36Sopenharmony_ci track->cb_color_info[tmp] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->tiling_flags)); 138562306a36Sopenharmony_ci } 138662306a36Sopenharmony_ci track->cb_dirty = true; 138762306a36Sopenharmony_ci break; 138862306a36Sopenharmony_ci case CB_COLOR0_PITCH: 138962306a36Sopenharmony_ci case CB_COLOR1_PITCH: 139062306a36Sopenharmony_ci case CB_COLOR2_PITCH: 139162306a36Sopenharmony_ci case CB_COLOR3_PITCH: 139262306a36Sopenharmony_ci case CB_COLOR4_PITCH: 139362306a36Sopenharmony_ci case CB_COLOR5_PITCH: 139462306a36Sopenharmony_ci case CB_COLOR6_PITCH: 139562306a36Sopenharmony_ci case CB_COLOR7_PITCH: 139662306a36Sopenharmony_ci tmp = (reg - CB_COLOR0_PITCH) / 0x3c; 139762306a36Sopenharmony_ci track->cb_color_pitch[tmp] = radeon_get_ib_value(p, idx); 139862306a36Sopenharmony_ci track->cb_dirty = true; 139962306a36Sopenharmony_ci break; 140062306a36Sopenharmony_ci case CB_COLOR8_PITCH: 140162306a36Sopenharmony_ci case CB_COLOR9_PITCH: 140262306a36Sopenharmony_ci case CB_COLOR10_PITCH: 140362306a36Sopenharmony_ci case CB_COLOR11_PITCH: 140462306a36Sopenharmony_ci tmp = ((reg - CB_COLOR8_PITCH) / 0x1c) + 8; 140562306a36Sopenharmony_ci track->cb_color_pitch[tmp] = radeon_get_ib_value(p, idx); 140662306a36Sopenharmony_ci track->cb_dirty = true; 140762306a36Sopenharmony_ci break; 140862306a36Sopenharmony_ci case CB_COLOR0_SLICE: 140962306a36Sopenharmony_ci case CB_COLOR1_SLICE: 141062306a36Sopenharmony_ci case CB_COLOR2_SLICE: 141162306a36Sopenharmony_ci case CB_COLOR3_SLICE: 141262306a36Sopenharmony_ci case CB_COLOR4_SLICE: 141362306a36Sopenharmony_ci case CB_COLOR5_SLICE: 141462306a36Sopenharmony_ci case CB_COLOR6_SLICE: 141562306a36Sopenharmony_ci case CB_COLOR7_SLICE: 141662306a36Sopenharmony_ci tmp = (reg - CB_COLOR0_SLICE) / 0x3c; 141762306a36Sopenharmony_ci track->cb_color_slice[tmp] = radeon_get_ib_value(p, idx); 141862306a36Sopenharmony_ci track->cb_color_slice_idx[tmp] = idx; 141962306a36Sopenharmony_ci track->cb_dirty = true; 142062306a36Sopenharmony_ci break; 142162306a36Sopenharmony_ci case CB_COLOR8_SLICE: 142262306a36Sopenharmony_ci case CB_COLOR9_SLICE: 142362306a36Sopenharmony_ci case CB_COLOR10_SLICE: 142462306a36Sopenharmony_ci case CB_COLOR11_SLICE: 142562306a36Sopenharmony_ci tmp = ((reg - CB_COLOR8_SLICE) / 0x1c) + 8; 142662306a36Sopenharmony_ci track->cb_color_slice[tmp] = radeon_get_ib_value(p, idx); 142762306a36Sopenharmony_ci track->cb_color_slice_idx[tmp] = idx; 142862306a36Sopenharmony_ci track->cb_dirty = true; 142962306a36Sopenharmony_ci break; 143062306a36Sopenharmony_ci case CB_COLOR0_ATTRIB: 143162306a36Sopenharmony_ci case CB_COLOR1_ATTRIB: 143262306a36Sopenharmony_ci case CB_COLOR2_ATTRIB: 143362306a36Sopenharmony_ci case CB_COLOR3_ATTRIB: 143462306a36Sopenharmony_ci case CB_COLOR4_ATTRIB: 143562306a36Sopenharmony_ci case CB_COLOR5_ATTRIB: 143662306a36Sopenharmony_ci case CB_COLOR6_ATTRIB: 143762306a36Sopenharmony_ci case CB_COLOR7_ATTRIB: 143862306a36Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 143962306a36Sopenharmony_ci if (r) { 144062306a36Sopenharmony_ci dev_warn(p->dev, "bad SET_CONTEXT_REG " 144162306a36Sopenharmony_ci "0x%04X\n", reg); 144262306a36Sopenharmony_ci return -EINVAL; 144362306a36Sopenharmony_ci } 144462306a36Sopenharmony_ci if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { 144562306a36Sopenharmony_ci if (reloc->tiling_flags & RADEON_TILING_MACRO) { 144662306a36Sopenharmony_ci unsigned bankw, bankh, mtaspect, tile_split; 144762306a36Sopenharmony_ci 144862306a36Sopenharmony_ci evergreen_tiling_fields(reloc->tiling_flags, 144962306a36Sopenharmony_ci &bankw, &bankh, &mtaspect, 145062306a36Sopenharmony_ci &tile_split); 145162306a36Sopenharmony_ci ib[idx] |= CB_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks)); 145262306a36Sopenharmony_ci ib[idx] |= CB_TILE_SPLIT(tile_split) | 145362306a36Sopenharmony_ci CB_BANK_WIDTH(bankw) | 145462306a36Sopenharmony_ci CB_BANK_HEIGHT(bankh) | 145562306a36Sopenharmony_ci CB_MACRO_TILE_ASPECT(mtaspect); 145662306a36Sopenharmony_ci } 145762306a36Sopenharmony_ci } 145862306a36Sopenharmony_ci tmp = ((reg - CB_COLOR0_ATTRIB) / 0x3c); 145962306a36Sopenharmony_ci track->cb_color_attrib[tmp] = ib[idx]; 146062306a36Sopenharmony_ci track->cb_dirty = true; 146162306a36Sopenharmony_ci break; 146262306a36Sopenharmony_ci case CB_COLOR8_ATTRIB: 146362306a36Sopenharmony_ci case CB_COLOR9_ATTRIB: 146462306a36Sopenharmony_ci case CB_COLOR10_ATTRIB: 146562306a36Sopenharmony_ci case CB_COLOR11_ATTRIB: 146662306a36Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 146762306a36Sopenharmony_ci if (r) { 146862306a36Sopenharmony_ci dev_warn(p->dev, "bad SET_CONTEXT_REG " 146962306a36Sopenharmony_ci "0x%04X\n", reg); 147062306a36Sopenharmony_ci return -EINVAL; 147162306a36Sopenharmony_ci } 147262306a36Sopenharmony_ci if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { 147362306a36Sopenharmony_ci if (reloc->tiling_flags & RADEON_TILING_MACRO) { 147462306a36Sopenharmony_ci unsigned bankw, bankh, mtaspect, tile_split; 147562306a36Sopenharmony_ci 147662306a36Sopenharmony_ci evergreen_tiling_fields(reloc->tiling_flags, 147762306a36Sopenharmony_ci &bankw, &bankh, &mtaspect, 147862306a36Sopenharmony_ci &tile_split); 147962306a36Sopenharmony_ci ib[idx] |= CB_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks)); 148062306a36Sopenharmony_ci ib[idx] |= CB_TILE_SPLIT(tile_split) | 148162306a36Sopenharmony_ci CB_BANK_WIDTH(bankw) | 148262306a36Sopenharmony_ci CB_BANK_HEIGHT(bankh) | 148362306a36Sopenharmony_ci CB_MACRO_TILE_ASPECT(mtaspect); 148462306a36Sopenharmony_ci } 148562306a36Sopenharmony_ci } 148662306a36Sopenharmony_ci tmp = ((reg - CB_COLOR8_ATTRIB) / 0x1c) + 8; 148762306a36Sopenharmony_ci track->cb_color_attrib[tmp] = ib[idx]; 148862306a36Sopenharmony_ci track->cb_dirty = true; 148962306a36Sopenharmony_ci break; 149062306a36Sopenharmony_ci case CB_COLOR0_FMASK: 149162306a36Sopenharmony_ci case CB_COLOR1_FMASK: 149262306a36Sopenharmony_ci case CB_COLOR2_FMASK: 149362306a36Sopenharmony_ci case CB_COLOR3_FMASK: 149462306a36Sopenharmony_ci case CB_COLOR4_FMASK: 149562306a36Sopenharmony_ci case CB_COLOR5_FMASK: 149662306a36Sopenharmony_ci case CB_COLOR6_FMASK: 149762306a36Sopenharmony_ci case CB_COLOR7_FMASK: 149862306a36Sopenharmony_ci tmp = (reg - CB_COLOR0_FMASK) / 0x3c; 149962306a36Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 150062306a36Sopenharmony_ci if (r) { 150162306a36Sopenharmony_ci dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg); 150262306a36Sopenharmony_ci return -EINVAL; 150362306a36Sopenharmony_ci } 150462306a36Sopenharmony_ci ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff); 150562306a36Sopenharmony_ci track->cb_color_fmask_bo[tmp] = reloc->robj; 150662306a36Sopenharmony_ci break; 150762306a36Sopenharmony_ci case CB_COLOR0_CMASK: 150862306a36Sopenharmony_ci case CB_COLOR1_CMASK: 150962306a36Sopenharmony_ci case CB_COLOR2_CMASK: 151062306a36Sopenharmony_ci case CB_COLOR3_CMASK: 151162306a36Sopenharmony_ci case CB_COLOR4_CMASK: 151262306a36Sopenharmony_ci case CB_COLOR5_CMASK: 151362306a36Sopenharmony_ci case CB_COLOR6_CMASK: 151462306a36Sopenharmony_ci case CB_COLOR7_CMASK: 151562306a36Sopenharmony_ci tmp = (reg - CB_COLOR0_CMASK) / 0x3c; 151662306a36Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 151762306a36Sopenharmony_ci if (r) { 151862306a36Sopenharmony_ci dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg); 151962306a36Sopenharmony_ci return -EINVAL; 152062306a36Sopenharmony_ci } 152162306a36Sopenharmony_ci ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff); 152262306a36Sopenharmony_ci track->cb_color_cmask_bo[tmp] = reloc->robj; 152362306a36Sopenharmony_ci break; 152462306a36Sopenharmony_ci case CB_COLOR0_FMASK_SLICE: 152562306a36Sopenharmony_ci case CB_COLOR1_FMASK_SLICE: 152662306a36Sopenharmony_ci case CB_COLOR2_FMASK_SLICE: 152762306a36Sopenharmony_ci case CB_COLOR3_FMASK_SLICE: 152862306a36Sopenharmony_ci case CB_COLOR4_FMASK_SLICE: 152962306a36Sopenharmony_ci case CB_COLOR5_FMASK_SLICE: 153062306a36Sopenharmony_ci case CB_COLOR6_FMASK_SLICE: 153162306a36Sopenharmony_ci case CB_COLOR7_FMASK_SLICE: 153262306a36Sopenharmony_ci tmp = (reg - CB_COLOR0_FMASK_SLICE) / 0x3c; 153362306a36Sopenharmony_ci track->cb_color_fmask_slice[tmp] = radeon_get_ib_value(p, idx); 153462306a36Sopenharmony_ci break; 153562306a36Sopenharmony_ci case CB_COLOR0_CMASK_SLICE: 153662306a36Sopenharmony_ci case CB_COLOR1_CMASK_SLICE: 153762306a36Sopenharmony_ci case CB_COLOR2_CMASK_SLICE: 153862306a36Sopenharmony_ci case CB_COLOR3_CMASK_SLICE: 153962306a36Sopenharmony_ci case CB_COLOR4_CMASK_SLICE: 154062306a36Sopenharmony_ci case CB_COLOR5_CMASK_SLICE: 154162306a36Sopenharmony_ci case CB_COLOR6_CMASK_SLICE: 154262306a36Sopenharmony_ci case CB_COLOR7_CMASK_SLICE: 154362306a36Sopenharmony_ci tmp = (reg - CB_COLOR0_CMASK_SLICE) / 0x3c; 154462306a36Sopenharmony_ci track->cb_color_cmask_slice[tmp] = radeon_get_ib_value(p, idx); 154562306a36Sopenharmony_ci break; 154662306a36Sopenharmony_ci case CB_COLOR0_BASE: 154762306a36Sopenharmony_ci case CB_COLOR1_BASE: 154862306a36Sopenharmony_ci case CB_COLOR2_BASE: 154962306a36Sopenharmony_ci case CB_COLOR3_BASE: 155062306a36Sopenharmony_ci case CB_COLOR4_BASE: 155162306a36Sopenharmony_ci case CB_COLOR5_BASE: 155262306a36Sopenharmony_ci case CB_COLOR6_BASE: 155362306a36Sopenharmony_ci case CB_COLOR7_BASE: 155462306a36Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 155562306a36Sopenharmony_ci if (r) { 155662306a36Sopenharmony_ci dev_warn(p->dev, "bad SET_CONTEXT_REG " 155762306a36Sopenharmony_ci "0x%04X\n", reg); 155862306a36Sopenharmony_ci return -EINVAL; 155962306a36Sopenharmony_ci } 156062306a36Sopenharmony_ci tmp = (reg - CB_COLOR0_BASE) / 0x3c; 156162306a36Sopenharmony_ci track->cb_color_bo_offset[tmp] = radeon_get_ib_value(p, idx); 156262306a36Sopenharmony_ci ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff); 156362306a36Sopenharmony_ci track->cb_color_bo[tmp] = reloc->robj; 156462306a36Sopenharmony_ci track->cb_dirty = true; 156562306a36Sopenharmony_ci break; 156662306a36Sopenharmony_ci case CB_COLOR8_BASE: 156762306a36Sopenharmony_ci case CB_COLOR9_BASE: 156862306a36Sopenharmony_ci case CB_COLOR10_BASE: 156962306a36Sopenharmony_ci case CB_COLOR11_BASE: 157062306a36Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 157162306a36Sopenharmony_ci if (r) { 157262306a36Sopenharmony_ci dev_warn(p->dev, "bad SET_CONTEXT_REG " 157362306a36Sopenharmony_ci "0x%04X\n", reg); 157462306a36Sopenharmony_ci return -EINVAL; 157562306a36Sopenharmony_ci } 157662306a36Sopenharmony_ci tmp = ((reg - CB_COLOR8_BASE) / 0x1c) + 8; 157762306a36Sopenharmony_ci track->cb_color_bo_offset[tmp] = radeon_get_ib_value(p, idx); 157862306a36Sopenharmony_ci ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff); 157962306a36Sopenharmony_ci track->cb_color_bo[tmp] = reloc->robj; 158062306a36Sopenharmony_ci track->cb_dirty = true; 158162306a36Sopenharmony_ci break; 158262306a36Sopenharmony_ci case DB_HTILE_DATA_BASE: 158362306a36Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 158462306a36Sopenharmony_ci if (r) { 158562306a36Sopenharmony_ci dev_warn(p->dev, "bad SET_CONTEXT_REG " 158662306a36Sopenharmony_ci "0x%04X\n", reg); 158762306a36Sopenharmony_ci return -EINVAL; 158862306a36Sopenharmony_ci } 158962306a36Sopenharmony_ci track->htile_offset = radeon_get_ib_value(p, idx); 159062306a36Sopenharmony_ci ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff); 159162306a36Sopenharmony_ci track->htile_bo = reloc->robj; 159262306a36Sopenharmony_ci track->db_dirty = true; 159362306a36Sopenharmony_ci break; 159462306a36Sopenharmony_ci case DB_HTILE_SURFACE: 159562306a36Sopenharmony_ci /* 8x8 only */ 159662306a36Sopenharmony_ci track->htile_surface = radeon_get_ib_value(p, idx); 159762306a36Sopenharmony_ci /* force 8x8 htile width and height */ 159862306a36Sopenharmony_ci ib[idx] |= 3; 159962306a36Sopenharmony_ci track->db_dirty = true; 160062306a36Sopenharmony_ci break; 160162306a36Sopenharmony_ci case CB_IMMED0_BASE: 160262306a36Sopenharmony_ci case CB_IMMED1_BASE: 160362306a36Sopenharmony_ci case CB_IMMED2_BASE: 160462306a36Sopenharmony_ci case CB_IMMED3_BASE: 160562306a36Sopenharmony_ci case CB_IMMED4_BASE: 160662306a36Sopenharmony_ci case CB_IMMED5_BASE: 160762306a36Sopenharmony_ci case CB_IMMED6_BASE: 160862306a36Sopenharmony_ci case CB_IMMED7_BASE: 160962306a36Sopenharmony_ci case CB_IMMED8_BASE: 161062306a36Sopenharmony_ci case CB_IMMED9_BASE: 161162306a36Sopenharmony_ci case CB_IMMED10_BASE: 161262306a36Sopenharmony_ci case CB_IMMED11_BASE: 161362306a36Sopenharmony_ci case SQ_PGM_START_FS: 161462306a36Sopenharmony_ci case SQ_PGM_START_ES: 161562306a36Sopenharmony_ci case SQ_PGM_START_VS: 161662306a36Sopenharmony_ci case SQ_PGM_START_GS: 161762306a36Sopenharmony_ci case SQ_PGM_START_PS: 161862306a36Sopenharmony_ci case SQ_PGM_START_HS: 161962306a36Sopenharmony_ci case SQ_PGM_START_LS: 162062306a36Sopenharmony_ci case SQ_CONST_MEM_BASE: 162162306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_GS_0: 162262306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_GS_1: 162362306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_GS_2: 162462306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_GS_3: 162562306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_GS_4: 162662306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_GS_5: 162762306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_GS_6: 162862306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_GS_7: 162962306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_GS_8: 163062306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_GS_9: 163162306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_GS_10: 163262306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_GS_11: 163362306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_GS_12: 163462306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_GS_13: 163562306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_GS_14: 163662306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_GS_15: 163762306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_PS_0: 163862306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_PS_1: 163962306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_PS_2: 164062306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_PS_3: 164162306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_PS_4: 164262306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_PS_5: 164362306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_PS_6: 164462306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_PS_7: 164562306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_PS_8: 164662306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_PS_9: 164762306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_PS_10: 164862306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_PS_11: 164962306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_PS_12: 165062306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_PS_13: 165162306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_PS_14: 165262306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_PS_15: 165362306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_VS_0: 165462306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_VS_1: 165562306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_VS_2: 165662306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_VS_3: 165762306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_VS_4: 165862306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_VS_5: 165962306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_VS_6: 166062306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_VS_7: 166162306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_VS_8: 166262306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_VS_9: 166362306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_VS_10: 166462306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_VS_11: 166562306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_VS_12: 166662306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_VS_13: 166762306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_VS_14: 166862306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_VS_15: 166962306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_HS_0: 167062306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_HS_1: 167162306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_HS_2: 167262306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_HS_3: 167362306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_HS_4: 167462306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_HS_5: 167562306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_HS_6: 167662306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_HS_7: 167762306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_HS_8: 167862306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_HS_9: 167962306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_HS_10: 168062306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_HS_11: 168162306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_HS_12: 168262306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_HS_13: 168362306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_HS_14: 168462306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_HS_15: 168562306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_LS_0: 168662306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_LS_1: 168762306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_LS_2: 168862306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_LS_3: 168962306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_LS_4: 169062306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_LS_5: 169162306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_LS_6: 169262306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_LS_7: 169362306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_LS_8: 169462306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_LS_9: 169562306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_LS_10: 169662306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_LS_11: 169762306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_LS_12: 169862306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_LS_13: 169962306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_LS_14: 170062306a36Sopenharmony_ci case SQ_ALU_CONST_CACHE_LS_15: 170162306a36Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 170262306a36Sopenharmony_ci if (r) { 170362306a36Sopenharmony_ci dev_warn(p->dev, "bad SET_CONTEXT_REG " 170462306a36Sopenharmony_ci "0x%04X\n", reg); 170562306a36Sopenharmony_ci return -EINVAL; 170662306a36Sopenharmony_ci } 170762306a36Sopenharmony_ci ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff); 170862306a36Sopenharmony_ci break; 170962306a36Sopenharmony_ci case SX_MEMORY_EXPORT_BASE: 171062306a36Sopenharmony_ci if (p->rdev->family >= CHIP_CAYMAN) { 171162306a36Sopenharmony_ci dev_warn(p->dev, "bad SET_CONFIG_REG " 171262306a36Sopenharmony_ci "0x%04X\n", reg); 171362306a36Sopenharmony_ci return -EINVAL; 171462306a36Sopenharmony_ci } 171562306a36Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 171662306a36Sopenharmony_ci if (r) { 171762306a36Sopenharmony_ci dev_warn(p->dev, "bad SET_CONFIG_REG " 171862306a36Sopenharmony_ci "0x%04X\n", reg); 171962306a36Sopenharmony_ci return -EINVAL; 172062306a36Sopenharmony_ci } 172162306a36Sopenharmony_ci ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff); 172262306a36Sopenharmony_ci break; 172362306a36Sopenharmony_ci case CAYMAN_SX_SCATTER_EXPORT_BASE: 172462306a36Sopenharmony_ci if (p->rdev->family < CHIP_CAYMAN) { 172562306a36Sopenharmony_ci dev_warn(p->dev, "bad SET_CONTEXT_REG " 172662306a36Sopenharmony_ci "0x%04X\n", reg); 172762306a36Sopenharmony_ci return -EINVAL; 172862306a36Sopenharmony_ci } 172962306a36Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 173062306a36Sopenharmony_ci if (r) { 173162306a36Sopenharmony_ci dev_warn(p->dev, "bad SET_CONTEXT_REG " 173262306a36Sopenharmony_ci "0x%04X\n", reg); 173362306a36Sopenharmony_ci return -EINVAL; 173462306a36Sopenharmony_ci } 173562306a36Sopenharmony_ci ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff); 173662306a36Sopenharmony_ci break; 173762306a36Sopenharmony_ci case SX_MISC: 173862306a36Sopenharmony_ci track->sx_misc_kill_all_prims = (radeon_get_ib_value(p, idx) & 0x1) != 0; 173962306a36Sopenharmony_ci break; 174062306a36Sopenharmony_ci default: 174162306a36Sopenharmony_ci dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx); 174262306a36Sopenharmony_ci return -EINVAL; 174362306a36Sopenharmony_ci } 174462306a36Sopenharmony_ci return 0; 174562306a36Sopenharmony_ci} 174662306a36Sopenharmony_ci 174762306a36Sopenharmony_ci/** 174862306a36Sopenharmony_ci * evergreen_is_safe_reg() - check if register is authorized or not 174962306a36Sopenharmony_ci * @p: parser structure holding parsing context 175062306a36Sopenharmony_ci * @reg: register we are testing 175162306a36Sopenharmony_ci * 175262306a36Sopenharmony_ci * This function will test against reg_safe_bm and return true 175362306a36Sopenharmony_ci * if register is safe or false otherwise. 175462306a36Sopenharmony_ci */ 175562306a36Sopenharmony_cistatic inline bool evergreen_is_safe_reg(struct radeon_cs_parser *p, u32 reg) 175662306a36Sopenharmony_ci{ 175762306a36Sopenharmony_ci struct evergreen_cs_track *track = p->track; 175862306a36Sopenharmony_ci u32 m, i; 175962306a36Sopenharmony_ci 176062306a36Sopenharmony_ci i = (reg >> 7); 176162306a36Sopenharmony_ci if (unlikely(i >= REG_SAFE_BM_SIZE)) { 176262306a36Sopenharmony_ci return false; 176362306a36Sopenharmony_ci } 176462306a36Sopenharmony_ci m = 1 << ((reg >> 2) & 31); 176562306a36Sopenharmony_ci if (!(track->reg_safe_bm[i] & m)) 176662306a36Sopenharmony_ci return true; 176762306a36Sopenharmony_ci 176862306a36Sopenharmony_ci return false; 176962306a36Sopenharmony_ci} 177062306a36Sopenharmony_ci 177162306a36Sopenharmony_cistatic int evergreen_packet3_check(struct radeon_cs_parser *p, 177262306a36Sopenharmony_ci struct radeon_cs_packet *pkt) 177362306a36Sopenharmony_ci{ 177462306a36Sopenharmony_ci struct radeon_bo_list *reloc; 177562306a36Sopenharmony_ci struct evergreen_cs_track *track; 177662306a36Sopenharmony_ci uint32_t *ib; 177762306a36Sopenharmony_ci unsigned idx; 177862306a36Sopenharmony_ci unsigned i; 177962306a36Sopenharmony_ci unsigned start_reg, end_reg, reg; 178062306a36Sopenharmony_ci int r; 178162306a36Sopenharmony_ci u32 idx_value; 178262306a36Sopenharmony_ci 178362306a36Sopenharmony_ci track = (struct evergreen_cs_track *)p->track; 178462306a36Sopenharmony_ci ib = p->ib.ptr; 178562306a36Sopenharmony_ci idx = pkt->idx + 1; 178662306a36Sopenharmony_ci idx_value = radeon_get_ib_value(p, idx); 178762306a36Sopenharmony_ci 178862306a36Sopenharmony_ci switch (pkt->opcode) { 178962306a36Sopenharmony_ci case PACKET3_SET_PREDICATION: 179062306a36Sopenharmony_ci { 179162306a36Sopenharmony_ci int pred_op; 179262306a36Sopenharmony_ci int tmp; 179362306a36Sopenharmony_ci uint64_t offset; 179462306a36Sopenharmony_ci 179562306a36Sopenharmony_ci if (pkt->count != 1) { 179662306a36Sopenharmony_ci DRM_ERROR("bad SET PREDICATION\n"); 179762306a36Sopenharmony_ci return -EINVAL; 179862306a36Sopenharmony_ci } 179962306a36Sopenharmony_ci 180062306a36Sopenharmony_ci tmp = radeon_get_ib_value(p, idx + 1); 180162306a36Sopenharmony_ci pred_op = (tmp >> 16) & 0x7; 180262306a36Sopenharmony_ci 180362306a36Sopenharmony_ci /* for the clear predicate operation */ 180462306a36Sopenharmony_ci if (pred_op == 0) 180562306a36Sopenharmony_ci return 0; 180662306a36Sopenharmony_ci 180762306a36Sopenharmony_ci if (pred_op > 2) { 180862306a36Sopenharmony_ci DRM_ERROR("bad SET PREDICATION operation %d\n", pred_op); 180962306a36Sopenharmony_ci return -EINVAL; 181062306a36Sopenharmony_ci } 181162306a36Sopenharmony_ci 181262306a36Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 181362306a36Sopenharmony_ci if (r) { 181462306a36Sopenharmony_ci DRM_ERROR("bad SET PREDICATION\n"); 181562306a36Sopenharmony_ci return -EINVAL; 181662306a36Sopenharmony_ci } 181762306a36Sopenharmony_ci 181862306a36Sopenharmony_ci offset = reloc->gpu_offset + 181962306a36Sopenharmony_ci (idx_value & 0xfffffff0) + 182062306a36Sopenharmony_ci ((u64)(tmp & 0xff) << 32); 182162306a36Sopenharmony_ci 182262306a36Sopenharmony_ci ib[idx + 0] = offset; 182362306a36Sopenharmony_ci ib[idx + 1] = (tmp & 0xffffff00) | (upper_32_bits(offset) & 0xff); 182462306a36Sopenharmony_ci } 182562306a36Sopenharmony_ci break; 182662306a36Sopenharmony_ci case PACKET3_CONTEXT_CONTROL: 182762306a36Sopenharmony_ci if (pkt->count != 1) { 182862306a36Sopenharmony_ci DRM_ERROR("bad CONTEXT_CONTROL\n"); 182962306a36Sopenharmony_ci return -EINVAL; 183062306a36Sopenharmony_ci } 183162306a36Sopenharmony_ci break; 183262306a36Sopenharmony_ci case PACKET3_INDEX_TYPE: 183362306a36Sopenharmony_ci case PACKET3_NUM_INSTANCES: 183462306a36Sopenharmony_ci case PACKET3_CLEAR_STATE: 183562306a36Sopenharmony_ci if (pkt->count) { 183662306a36Sopenharmony_ci DRM_ERROR("bad INDEX_TYPE/NUM_INSTANCES/CLEAR_STATE\n"); 183762306a36Sopenharmony_ci return -EINVAL; 183862306a36Sopenharmony_ci } 183962306a36Sopenharmony_ci break; 184062306a36Sopenharmony_ci case CAYMAN_PACKET3_DEALLOC_STATE: 184162306a36Sopenharmony_ci if (p->rdev->family < CHIP_CAYMAN) { 184262306a36Sopenharmony_ci DRM_ERROR("bad PACKET3_DEALLOC_STATE\n"); 184362306a36Sopenharmony_ci return -EINVAL; 184462306a36Sopenharmony_ci } 184562306a36Sopenharmony_ci if (pkt->count) { 184662306a36Sopenharmony_ci DRM_ERROR("bad INDEX_TYPE/NUM_INSTANCES/CLEAR_STATE\n"); 184762306a36Sopenharmony_ci return -EINVAL; 184862306a36Sopenharmony_ci } 184962306a36Sopenharmony_ci break; 185062306a36Sopenharmony_ci case PACKET3_INDEX_BASE: 185162306a36Sopenharmony_ci { 185262306a36Sopenharmony_ci uint64_t offset; 185362306a36Sopenharmony_ci 185462306a36Sopenharmony_ci if (pkt->count != 1) { 185562306a36Sopenharmony_ci DRM_ERROR("bad INDEX_BASE\n"); 185662306a36Sopenharmony_ci return -EINVAL; 185762306a36Sopenharmony_ci } 185862306a36Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 185962306a36Sopenharmony_ci if (r) { 186062306a36Sopenharmony_ci DRM_ERROR("bad INDEX_BASE\n"); 186162306a36Sopenharmony_ci return -EINVAL; 186262306a36Sopenharmony_ci } 186362306a36Sopenharmony_ci 186462306a36Sopenharmony_ci offset = reloc->gpu_offset + 186562306a36Sopenharmony_ci idx_value + 186662306a36Sopenharmony_ci ((u64)(radeon_get_ib_value(p, idx+1) & 0xff) << 32); 186762306a36Sopenharmony_ci 186862306a36Sopenharmony_ci ib[idx+0] = offset; 186962306a36Sopenharmony_ci ib[idx+1] = upper_32_bits(offset) & 0xff; 187062306a36Sopenharmony_ci 187162306a36Sopenharmony_ci r = evergreen_cs_track_check(p); 187262306a36Sopenharmony_ci if (r) { 187362306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__); 187462306a36Sopenharmony_ci return r; 187562306a36Sopenharmony_ci } 187662306a36Sopenharmony_ci break; 187762306a36Sopenharmony_ci } 187862306a36Sopenharmony_ci case PACKET3_INDEX_BUFFER_SIZE: 187962306a36Sopenharmony_ci { 188062306a36Sopenharmony_ci if (pkt->count != 0) { 188162306a36Sopenharmony_ci DRM_ERROR("bad INDEX_BUFFER_SIZE\n"); 188262306a36Sopenharmony_ci return -EINVAL; 188362306a36Sopenharmony_ci } 188462306a36Sopenharmony_ci break; 188562306a36Sopenharmony_ci } 188662306a36Sopenharmony_ci case PACKET3_DRAW_INDEX: 188762306a36Sopenharmony_ci { 188862306a36Sopenharmony_ci uint64_t offset; 188962306a36Sopenharmony_ci if (pkt->count != 3) { 189062306a36Sopenharmony_ci DRM_ERROR("bad DRAW_INDEX\n"); 189162306a36Sopenharmony_ci return -EINVAL; 189262306a36Sopenharmony_ci } 189362306a36Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 189462306a36Sopenharmony_ci if (r) { 189562306a36Sopenharmony_ci DRM_ERROR("bad DRAW_INDEX\n"); 189662306a36Sopenharmony_ci return -EINVAL; 189762306a36Sopenharmony_ci } 189862306a36Sopenharmony_ci 189962306a36Sopenharmony_ci offset = reloc->gpu_offset + 190062306a36Sopenharmony_ci idx_value + 190162306a36Sopenharmony_ci ((u64)(radeon_get_ib_value(p, idx+1) & 0xff) << 32); 190262306a36Sopenharmony_ci 190362306a36Sopenharmony_ci ib[idx+0] = offset; 190462306a36Sopenharmony_ci ib[idx+1] = upper_32_bits(offset) & 0xff; 190562306a36Sopenharmony_ci 190662306a36Sopenharmony_ci r = evergreen_cs_track_check(p); 190762306a36Sopenharmony_ci if (r) { 190862306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__); 190962306a36Sopenharmony_ci return r; 191062306a36Sopenharmony_ci } 191162306a36Sopenharmony_ci break; 191262306a36Sopenharmony_ci } 191362306a36Sopenharmony_ci case PACKET3_DRAW_INDEX_2: 191462306a36Sopenharmony_ci { 191562306a36Sopenharmony_ci uint64_t offset; 191662306a36Sopenharmony_ci 191762306a36Sopenharmony_ci if (pkt->count != 4) { 191862306a36Sopenharmony_ci DRM_ERROR("bad DRAW_INDEX_2\n"); 191962306a36Sopenharmony_ci return -EINVAL; 192062306a36Sopenharmony_ci } 192162306a36Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 192262306a36Sopenharmony_ci if (r) { 192362306a36Sopenharmony_ci DRM_ERROR("bad DRAW_INDEX_2\n"); 192462306a36Sopenharmony_ci return -EINVAL; 192562306a36Sopenharmony_ci } 192662306a36Sopenharmony_ci 192762306a36Sopenharmony_ci offset = reloc->gpu_offset + 192862306a36Sopenharmony_ci radeon_get_ib_value(p, idx+1) + 192962306a36Sopenharmony_ci ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32); 193062306a36Sopenharmony_ci 193162306a36Sopenharmony_ci ib[idx+1] = offset; 193262306a36Sopenharmony_ci ib[idx+2] = upper_32_bits(offset) & 0xff; 193362306a36Sopenharmony_ci 193462306a36Sopenharmony_ci r = evergreen_cs_track_check(p); 193562306a36Sopenharmony_ci if (r) { 193662306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__); 193762306a36Sopenharmony_ci return r; 193862306a36Sopenharmony_ci } 193962306a36Sopenharmony_ci break; 194062306a36Sopenharmony_ci } 194162306a36Sopenharmony_ci case PACKET3_DRAW_INDEX_AUTO: 194262306a36Sopenharmony_ci if (pkt->count != 1) { 194362306a36Sopenharmony_ci DRM_ERROR("bad DRAW_INDEX_AUTO\n"); 194462306a36Sopenharmony_ci return -EINVAL; 194562306a36Sopenharmony_ci } 194662306a36Sopenharmony_ci r = evergreen_cs_track_check(p); 194762306a36Sopenharmony_ci if (r) { 194862306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d invalid cmd stream %d\n", __func__, __LINE__, idx); 194962306a36Sopenharmony_ci return r; 195062306a36Sopenharmony_ci } 195162306a36Sopenharmony_ci break; 195262306a36Sopenharmony_ci case PACKET3_DRAW_INDEX_MULTI_AUTO: 195362306a36Sopenharmony_ci if (pkt->count != 2) { 195462306a36Sopenharmony_ci DRM_ERROR("bad DRAW_INDEX_MULTI_AUTO\n"); 195562306a36Sopenharmony_ci return -EINVAL; 195662306a36Sopenharmony_ci } 195762306a36Sopenharmony_ci r = evergreen_cs_track_check(p); 195862306a36Sopenharmony_ci if (r) { 195962306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d invalid cmd stream %d\n", __func__, __LINE__, idx); 196062306a36Sopenharmony_ci return r; 196162306a36Sopenharmony_ci } 196262306a36Sopenharmony_ci break; 196362306a36Sopenharmony_ci case PACKET3_DRAW_INDEX_IMMD: 196462306a36Sopenharmony_ci if (pkt->count < 2) { 196562306a36Sopenharmony_ci DRM_ERROR("bad DRAW_INDEX_IMMD\n"); 196662306a36Sopenharmony_ci return -EINVAL; 196762306a36Sopenharmony_ci } 196862306a36Sopenharmony_ci r = evergreen_cs_track_check(p); 196962306a36Sopenharmony_ci if (r) { 197062306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__); 197162306a36Sopenharmony_ci return r; 197262306a36Sopenharmony_ci } 197362306a36Sopenharmony_ci break; 197462306a36Sopenharmony_ci case PACKET3_DRAW_INDEX_OFFSET: 197562306a36Sopenharmony_ci if (pkt->count != 2) { 197662306a36Sopenharmony_ci DRM_ERROR("bad DRAW_INDEX_OFFSET\n"); 197762306a36Sopenharmony_ci return -EINVAL; 197862306a36Sopenharmony_ci } 197962306a36Sopenharmony_ci r = evergreen_cs_track_check(p); 198062306a36Sopenharmony_ci if (r) { 198162306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__); 198262306a36Sopenharmony_ci return r; 198362306a36Sopenharmony_ci } 198462306a36Sopenharmony_ci break; 198562306a36Sopenharmony_ci case PACKET3_DRAW_INDEX_OFFSET_2: 198662306a36Sopenharmony_ci if (pkt->count != 3) { 198762306a36Sopenharmony_ci DRM_ERROR("bad DRAW_INDEX_OFFSET_2\n"); 198862306a36Sopenharmony_ci return -EINVAL; 198962306a36Sopenharmony_ci } 199062306a36Sopenharmony_ci r = evergreen_cs_track_check(p); 199162306a36Sopenharmony_ci if (r) { 199262306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__); 199362306a36Sopenharmony_ci return r; 199462306a36Sopenharmony_ci } 199562306a36Sopenharmony_ci break; 199662306a36Sopenharmony_ci case PACKET3_SET_BASE: 199762306a36Sopenharmony_ci { 199862306a36Sopenharmony_ci /* 199962306a36Sopenharmony_ci DW 1 HEADER Header of the packet. Shader_Type in bit 1 of the Header will correspond to the shader type of the Load, see Type-3 Packet. 200062306a36Sopenharmony_ci 2 BASE_INDEX Bits [3:0] BASE_INDEX - Base Index specifies which base address is specified in the last two DWs. 200162306a36Sopenharmony_ci 0001: DX11 Draw_Index_Indirect Patch Table Base: Base address for Draw_Index_Indirect data. 200262306a36Sopenharmony_ci 3 ADDRESS_LO Bits [31:3] - Lower bits of QWORD-Aligned Address. Bits [2:0] - Reserved 200362306a36Sopenharmony_ci 4 ADDRESS_HI Bits [31:8] - Reserved. Bits [7:0] - Upper bits of Address [47:32] 200462306a36Sopenharmony_ci */ 200562306a36Sopenharmony_ci if (pkt->count != 2) { 200662306a36Sopenharmony_ci DRM_ERROR("bad SET_BASE\n"); 200762306a36Sopenharmony_ci return -EINVAL; 200862306a36Sopenharmony_ci } 200962306a36Sopenharmony_ci 201062306a36Sopenharmony_ci /* currently only supporting setting indirect draw buffer base address */ 201162306a36Sopenharmony_ci if (idx_value != 1) { 201262306a36Sopenharmony_ci DRM_ERROR("bad SET_BASE\n"); 201362306a36Sopenharmony_ci return -EINVAL; 201462306a36Sopenharmony_ci } 201562306a36Sopenharmony_ci 201662306a36Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 201762306a36Sopenharmony_ci if (r) { 201862306a36Sopenharmony_ci DRM_ERROR("bad SET_BASE\n"); 201962306a36Sopenharmony_ci return -EINVAL; 202062306a36Sopenharmony_ci } 202162306a36Sopenharmony_ci 202262306a36Sopenharmony_ci track->indirect_draw_buffer_size = radeon_bo_size(reloc->robj); 202362306a36Sopenharmony_ci 202462306a36Sopenharmony_ci ib[idx+1] = reloc->gpu_offset; 202562306a36Sopenharmony_ci ib[idx+2] = upper_32_bits(reloc->gpu_offset) & 0xff; 202662306a36Sopenharmony_ci 202762306a36Sopenharmony_ci break; 202862306a36Sopenharmony_ci } 202962306a36Sopenharmony_ci case PACKET3_DRAW_INDIRECT: 203062306a36Sopenharmony_ci case PACKET3_DRAW_INDEX_INDIRECT: 203162306a36Sopenharmony_ci { 203262306a36Sopenharmony_ci u64 size = pkt->opcode == PACKET3_DRAW_INDIRECT ? 16 : 20; 203362306a36Sopenharmony_ci 203462306a36Sopenharmony_ci /* 203562306a36Sopenharmony_ci DW 1 HEADER 203662306a36Sopenharmony_ci 2 DATA_OFFSET Bits [31:0] + byte aligned offset where the required data structure starts. Bits 1:0 are zero 203762306a36Sopenharmony_ci 3 DRAW_INITIATOR Draw Initiator Register. Written to the VGT_DRAW_INITIATOR register for the assigned context 203862306a36Sopenharmony_ci */ 203962306a36Sopenharmony_ci if (pkt->count != 1) { 204062306a36Sopenharmony_ci DRM_ERROR("bad DRAW_INDIRECT\n"); 204162306a36Sopenharmony_ci return -EINVAL; 204262306a36Sopenharmony_ci } 204362306a36Sopenharmony_ci 204462306a36Sopenharmony_ci if (idx_value + size > track->indirect_draw_buffer_size) { 204562306a36Sopenharmony_ci dev_warn(p->dev, "DRAW_INDIRECT buffer too small %u + %llu > %lu\n", 204662306a36Sopenharmony_ci idx_value, size, track->indirect_draw_buffer_size); 204762306a36Sopenharmony_ci return -EINVAL; 204862306a36Sopenharmony_ci } 204962306a36Sopenharmony_ci 205062306a36Sopenharmony_ci r = evergreen_cs_track_check(p); 205162306a36Sopenharmony_ci if (r) { 205262306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__); 205362306a36Sopenharmony_ci return r; 205462306a36Sopenharmony_ci } 205562306a36Sopenharmony_ci break; 205662306a36Sopenharmony_ci } 205762306a36Sopenharmony_ci case PACKET3_DISPATCH_DIRECT: 205862306a36Sopenharmony_ci if (pkt->count != 3) { 205962306a36Sopenharmony_ci DRM_ERROR("bad DISPATCH_DIRECT\n"); 206062306a36Sopenharmony_ci return -EINVAL; 206162306a36Sopenharmony_ci } 206262306a36Sopenharmony_ci r = evergreen_cs_track_check(p); 206362306a36Sopenharmony_ci if (r) { 206462306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d invalid cmd stream %d\n", __func__, __LINE__, idx); 206562306a36Sopenharmony_ci return r; 206662306a36Sopenharmony_ci } 206762306a36Sopenharmony_ci break; 206862306a36Sopenharmony_ci case PACKET3_DISPATCH_INDIRECT: 206962306a36Sopenharmony_ci if (pkt->count != 1) { 207062306a36Sopenharmony_ci DRM_ERROR("bad DISPATCH_INDIRECT\n"); 207162306a36Sopenharmony_ci return -EINVAL; 207262306a36Sopenharmony_ci } 207362306a36Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 207462306a36Sopenharmony_ci if (r) { 207562306a36Sopenharmony_ci DRM_ERROR("bad DISPATCH_INDIRECT\n"); 207662306a36Sopenharmony_ci return -EINVAL; 207762306a36Sopenharmony_ci } 207862306a36Sopenharmony_ci ib[idx+0] = idx_value + (u32)(reloc->gpu_offset & 0xffffffff); 207962306a36Sopenharmony_ci r = evergreen_cs_track_check(p); 208062306a36Sopenharmony_ci if (r) { 208162306a36Sopenharmony_ci dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__); 208262306a36Sopenharmony_ci return r; 208362306a36Sopenharmony_ci } 208462306a36Sopenharmony_ci break; 208562306a36Sopenharmony_ci case PACKET3_WAIT_REG_MEM: 208662306a36Sopenharmony_ci if (pkt->count != 5) { 208762306a36Sopenharmony_ci DRM_ERROR("bad WAIT_REG_MEM\n"); 208862306a36Sopenharmony_ci return -EINVAL; 208962306a36Sopenharmony_ci } 209062306a36Sopenharmony_ci /* bit 4 is reg (0) or mem (1) */ 209162306a36Sopenharmony_ci if (idx_value & 0x10) { 209262306a36Sopenharmony_ci uint64_t offset; 209362306a36Sopenharmony_ci 209462306a36Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 209562306a36Sopenharmony_ci if (r) { 209662306a36Sopenharmony_ci DRM_ERROR("bad WAIT_REG_MEM\n"); 209762306a36Sopenharmony_ci return -EINVAL; 209862306a36Sopenharmony_ci } 209962306a36Sopenharmony_ci 210062306a36Sopenharmony_ci offset = reloc->gpu_offset + 210162306a36Sopenharmony_ci (radeon_get_ib_value(p, idx+1) & 0xfffffffc) + 210262306a36Sopenharmony_ci ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32); 210362306a36Sopenharmony_ci 210462306a36Sopenharmony_ci ib[idx+1] = (ib[idx+1] & 0x3) | (offset & 0xfffffffc); 210562306a36Sopenharmony_ci ib[idx+2] = upper_32_bits(offset) & 0xff; 210662306a36Sopenharmony_ci } else if (idx_value & 0x100) { 210762306a36Sopenharmony_ci DRM_ERROR("cannot use PFP on REG wait\n"); 210862306a36Sopenharmony_ci return -EINVAL; 210962306a36Sopenharmony_ci } 211062306a36Sopenharmony_ci break; 211162306a36Sopenharmony_ci case PACKET3_CP_DMA: 211262306a36Sopenharmony_ci { 211362306a36Sopenharmony_ci u32 command, size, info; 211462306a36Sopenharmony_ci u64 offset, tmp; 211562306a36Sopenharmony_ci if (pkt->count != 4) { 211662306a36Sopenharmony_ci DRM_ERROR("bad CP DMA\n"); 211762306a36Sopenharmony_ci return -EINVAL; 211862306a36Sopenharmony_ci } 211962306a36Sopenharmony_ci command = radeon_get_ib_value(p, idx+4); 212062306a36Sopenharmony_ci size = command & 0x1fffff; 212162306a36Sopenharmony_ci info = radeon_get_ib_value(p, idx+1); 212262306a36Sopenharmony_ci if ((((info & 0x60000000) >> 29) != 0) || /* src = GDS or DATA */ 212362306a36Sopenharmony_ci (((info & 0x00300000) >> 20) != 0) || /* dst = GDS */ 212462306a36Sopenharmony_ci ((((info & 0x00300000) >> 20) == 0) && 212562306a36Sopenharmony_ci (command & PACKET3_CP_DMA_CMD_DAS)) || /* dst = register */ 212662306a36Sopenharmony_ci ((((info & 0x60000000) >> 29) == 0) && 212762306a36Sopenharmony_ci (command & PACKET3_CP_DMA_CMD_SAS))) { /* src = register */ 212862306a36Sopenharmony_ci /* non mem to mem copies requires dw aligned count */ 212962306a36Sopenharmony_ci if (size % 4) { 213062306a36Sopenharmony_ci DRM_ERROR("CP DMA command requires dw count alignment\n"); 213162306a36Sopenharmony_ci return -EINVAL; 213262306a36Sopenharmony_ci } 213362306a36Sopenharmony_ci } 213462306a36Sopenharmony_ci if (command & PACKET3_CP_DMA_CMD_SAS) { 213562306a36Sopenharmony_ci /* src address space is register */ 213662306a36Sopenharmony_ci /* GDS is ok */ 213762306a36Sopenharmony_ci if (((info & 0x60000000) >> 29) != 1) { 213862306a36Sopenharmony_ci DRM_ERROR("CP DMA SAS not supported\n"); 213962306a36Sopenharmony_ci return -EINVAL; 214062306a36Sopenharmony_ci } 214162306a36Sopenharmony_ci } else { 214262306a36Sopenharmony_ci if (command & PACKET3_CP_DMA_CMD_SAIC) { 214362306a36Sopenharmony_ci DRM_ERROR("CP DMA SAIC only supported for registers\n"); 214462306a36Sopenharmony_ci return -EINVAL; 214562306a36Sopenharmony_ci } 214662306a36Sopenharmony_ci /* src address space is memory */ 214762306a36Sopenharmony_ci if (((info & 0x60000000) >> 29) == 0) { 214862306a36Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 214962306a36Sopenharmony_ci if (r) { 215062306a36Sopenharmony_ci DRM_ERROR("bad CP DMA SRC\n"); 215162306a36Sopenharmony_ci return -EINVAL; 215262306a36Sopenharmony_ci } 215362306a36Sopenharmony_ci 215462306a36Sopenharmony_ci tmp = radeon_get_ib_value(p, idx) + 215562306a36Sopenharmony_ci ((u64)(radeon_get_ib_value(p, idx+1) & 0xff) << 32); 215662306a36Sopenharmony_ci 215762306a36Sopenharmony_ci offset = reloc->gpu_offset + tmp; 215862306a36Sopenharmony_ci 215962306a36Sopenharmony_ci if ((tmp + size) > radeon_bo_size(reloc->robj)) { 216062306a36Sopenharmony_ci dev_warn(p->dev, "CP DMA src buffer too small (%llu %lu)\n", 216162306a36Sopenharmony_ci tmp + size, radeon_bo_size(reloc->robj)); 216262306a36Sopenharmony_ci return -EINVAL; 216362306a36Sopenharmony_ci } 216462306a36Sopenharmony_ci 216562306a36Sopenharmony_ci ib[idx] = offset; 216662306a36Sopenharmony_ci ib[idx+1] = (ib[idx+1] & 0xffffff00) | (upper_32_bits(offset) & 0xff); 216762306a36Sopenharmony_ci } else if (((info & 0x60000000) >> 29) != 2) { 216862306a36Sopenharmony_ci DRM_ERROR("bad CP DMA SRC_SEL\n"); 216962306a36Sopenharmony_ci return -EINVAL; 217062306a36Sopenharmony_ci } 217162306a36Sopenharmony_ci } 217262306a36Sopenharmony_ci if (command & PACKET3_CP_DMA_CMD_DAS) { 217362306a36Sopenharmony_ci /* dst address space is register */ 217462306a36Sopenharmony_ci /* GDS is ok */ 217562306a36Sopenharmony_ci if (((info & 0x00300000) >> 20) != 1) { 217662306a36Sopenharmony_ci DRM_ERROR("CP DMA DAS not supported\n"); 217762306a36Sopenharmony_ci return -EINVAL; 217862306a36Sopenharmony_ci } 217962306a36Sopenharmony_ci } else { 218062306a36Sopenharmony_ci /* dst address space is memory */ 218162306a36Sopenharmony_ci if (command & PACKET3_CP_DMA_CMD_DAIC) { 218262306a36Sopenharmony_ci DRM_ERROR("CP DMA DAIC only supported for registers\n"); 218362306a36Sopenharmony_ci return -EINVAL; 218462306a36Sopenharmony_ci } 218562306a36Sopenharmony_ci if (((info & 0x00300000) >> 20) == 0) { 218662306a36Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 218762306a36Sopenharmony_ci if (r) { 218862306a36Sopenharmony_ci DRM_ERROR("bad CP DMA DST\n"); 218962306a36Sopenharmony_ci return -EINVAL; 219062306a36Sopenharmony_ci } 219162306a36Sopenharmony_ci 219262306a36Sopenharmony_ci tmp = radeon_get_ib_value(p, idx+2) + 219362306a36Sopenharmony_ci ((u64)(radeon_get_ib_value(p, idx+3) & 0xff) << 32); 219462306a36Sopenharmony_ci 219562306a36Sopenharmony_ci offset = reloc->gpu_offset + tmp; 219662306a36Sopenharmony_ci 219762306a36Sopenharmony_ci if ((tmp + size) > radeon_bo_size(reloc->robj)) { 219862306a36Sopenharmony_ci dev_warn(p->dev, "CP DMA dst buffer too small (%llu %lu)\n", 219962306a36Sopenharmony_ci tmp + size, radeon_bo_size(reloc->robj)); 220062306a36Sopenharmony_ci return -EINVAL; 220162306a36Sopenharmony_ci } 220262306a36Sopenharmony_ci 220362306a36Sopenharmony_ci ib[idx+2] = offset; 220462306a36Sopenharmony_ci ib[idx+3] = upper_32_bits(offset) & 0xff; 220562306a36Sopenharmony_ci } else { 220662306a36Sopenharmony_ci DRM_ERROR("bad CP DMA DST_SEL\n"); 220762306a36Sopenharmony_ci return -EINVAL; 220862306a36Sopenharmony_ci } 220962306a36Sopenharmony_ci } 221062306a36Sopenharmony_ci break; 221162306a36Sopenharmony_ci } 221262306a36Sopenharmony_ci case PACKET3_PFP_SYNC_ME: 221362306a36Sopenharmony_ci if (pkt->count) { 221462306a36Sopenharmony_ci DRM_ERROR("bad PFP_SYNC_ME\n"); 221562306a36Sopenharmony_ci return -EINVAL; 221662306a36Sopenharmony_ci } 221762306a36Sopenharmony_ci break; 221862306a36Sopenharmony_ci case PACKET3_SURFACE_SYNC: 221962306a36Sopenharmony_ci if (pkt->count != 3) { 222062306a36Sopenharmony_ci DRM_ERROR("bad SURFACE_SYNC\n"); 222162306a36Sopenharmony_ci return -EINVAL; 222262306a36Sopenharmony_ci } 222362306a36Sopenharmony_ci /* 0xffffffff/0x0 is flush all cache flag */ 222462306a36Sopenharmony_ci if (radeon_get_ib_value(p, idx + 1) != 0xffffffff || 222562306a36Sopenharmony_ci radeon_get_ib_value(p, idx + 2) != 0) { 222662306a36Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 222762306a36Sopenharmony_ci if (r) { 222862306a36Sopenharmony_ci DRM_ERROR("bad SURFACE_SYNC\n"); 222962306a36Sopenharmony_ci return -EINVAL; 223062306a36Sopenharmony_ci } 223162306a36Sopenharmony_ci ib[idx+2] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff); 223262306a36Sopenharmony_ci } 223362306a36Sopenharmony_ci break; 223462306a36Sopenharmony_ci case PACKET3_EVENT_WRITE: 223562306a36Sopenharmony_ci if (pkt->count != 2 && pkt->count != 0) { 223662306a36Sopenharmony_ci DRM_ERROR("bad EVENT_WRITE\n"); 223762306a36Sopenharmony_ci return -EINVAL; 223862306a36Sopenharmony_ci } 223962306a36Sopenharmony_ci if (pkt->count) { 224062306a36Sopenharmony_ci uint64_t offset; 224162306a36Sopenharmony_ci 224262306a36Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 224362306a36Sopenharmony_ci if (r) { 224462306a36Sopenharmony_ci DRM_ERROR("bad EVENT_WRITE\n"); 224562306a36Sopenharmony_ci return -EINVAL; 224662306a36Sopenharmony_ci } 224762306a36Sopenharmony_ci offset = reloc->gpu_offset + 224862306a36Sopenharmony_ci (radeon_get_ib_value(p, idx+1) & 0xfffffff8) + 224962306a36Sopenharmony_ci ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32); 225062306a36Sopenharmony_ci 225162306a36Sopenharmony_ci ib[idx+1] = offset & 0xfffffff8; 225262306a36Sopenharmony_ci ib[idx+2] = upper_32_bits(offset) & 0xff; 225362306a36Sopenharmony_ci } 225462306a36Sopenharmony_ci break; 225562306a36Sopenharmony_ci case PACKET3_EVENT_WRITE_EOP: 225662306a36Sopenharmony_ci { 225762306a36Sopenharmony_ci uint64_t offset; 225862306a36Sopenharmony_ci 225962306a36Sopenharmony_ci if (pkt->count != 4) { 226062306a36Sopenharmony_ci DRM_ERROR("bad EVENT_WRITE_EOP\n"); 226162306a36Sopenharmony_ci return -EINVAL; 226262306a36Sopenharmony_ci } 226362306a36Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 226462306a36Sopenharmony_ci if (r) { 226562306a36Sopenharmony_ci DRM_ERROR("bad EVENT_WRITE_EOP\n"); 226662306a36Sopenharmony_ci return -EINVAL; 226762306a36Sopenharmony_ci } 226862306a36Sopenharmony_ci 226962306a36Sopenharmony_ci offset = reloc->gpu_offset + 227062306a36Sopenharmony_ci (radeon_get_ib_value(p, idx+1) & 0xfffffffc) + 227162306a36Sopenharmony_ci ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32); 227262306a36Sopenharmony_ci 227362306a36Sopenharmony_ci ib[idx+1] = offset & 0xfffffffc; 227462306a36Sopenharmony_ci ib[idx+2] = (ib[idx+2] & 0xffffff00) | (upper_32_bits(offset) & 0xff); 227562306a36Sopenharmony_ci break; 227662306a36Sopenharmony_ci } 227762306a36Sopenharmony_ci case PACKET3_EVENT_WRITE_EOS: 227862306a36Sopenharmony_ci { 227962306a36Sopenharmony_ci uint64_t offset; 228062306a36Sopenharmony_ci 228162306a36Sopenharmony_ci if (pkt->count != 3) { 228262306a36Sopenharmony_ci DRM_ERROR("bad EVENT_WRITE_EOS\n"); 228362306a36Sopenharmony_ci return -EINVAL; 228462306a36Sopenharmony_ci } 228562306a36Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 228662306a36Sopenharmony_ci if (r) { 228762306a36Sopenharmony_ci DRM_ERROR("bad EVENT_WRITE_EOS\n"); 228862306a36Sopenharmony_ci return -EINVAL; 228962306a36Sopenharmony_ci } 229062306a36Sopenharmony_ci 229162306a36Sopenharmony_ci offset = reloc->gpu_offset + 229262306a36Sopenharmony_ci (radeon_get_ib_value(p, idx+1) & 0xfffffffc) + 229362306a36Sopenharmony_ci ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32); 229462306a36Sopenharmony_ci 229562306a36Sopenharmony_ci ib[idx+1] = offset & 0xfffffffc; 229662306a36Sopenharmony_ci ib[idx+2] = (ib[idx+2] & 0xffffff00) | (upper_32_bits(offset) & 0xff); 229762306a36Sopenharmony_ci break; 229862306a36Sopenharmony_ci } 229962306a36Sopenharmony_ci case PACKET3_SET_CONFIG_REG: 230062306a36Sopenharmony_ci start_reg = (idx_value << 2) + PACKET3_SET_CONFIG_REG_START; 230162306a36Sopenharmony_ci end_reg = 4 * pkt->count + start_reg - 4; 230262306a36Sopenharmony_ci if ((start_reg < PACKET3_SET_CONFIG_REG_START) || 230362306a36Sopenharmony_ci (start_reg >= PACKET3_SET_CONFIG_REG_END) || 230462306a36Sopenharmony_ci (end_reg >= PACKET3_SET_CONFIG_REG_END)) { 230562306a36Sopenharmony_ci DRM_ERROR("bad PACKET3_SET_CONFIG_REG\n"); 230662306a36Sopenharmony_ci return -EINVAL; 230762306a36Sopenharmony_ci } 230862306a36Sopenharmony_ci for (reg = start_reg, idx++; reg <= end_reg; reg += 4, idx++) { 230962306a36Sopenharmony_ci if (evergreen_is_safe_reg(p, reg)) 231062306a36Sopenharmony_ci continue; 231162306a36Sopenharmony_ci r = evergreen_cs_handle_reg(p, reg, idx); 231262306a36Sopenharmony_ci if (r) 231362306a36Sopenharmony_ci return r; 231462306a36Sopenharmony_ci } 231562306a36Sopenharmony_ci break; 231662306a36Sopenharmony_ci case PACKET3_SET_CONTEXT_REG: 231762306a36Sopenharmony_ci start_reg = (idx_value << 2) + PACKET3_SET_CONTEXT_REG_START; 231862306a36Sopenharmony_ci end_reg = 4 * pkt->count + start_reg - 4; 231962306a36Sopenharmony_ci if ((start_reg < PACKET3_SET_CONTEXT_REG_START) || 232062306a36Sopenharmony_ci (start_reg >= PACKET3_SET_CONTEXT_REG_END) || 232162306a36Sopenharmony_ci (end_reg >= PACKET3_SET_CONTEXT_REG_END)) { 232262306a36Sopenharmony_ci DRM_ERROR("bad PACKET3_SET_CONTEXT_REG\n"); 232362306a36Sopenharmony_ci return -EINVAL; 232462306a36Sopenharmony_ci } 232562306a36Sopenharmony_ci for (reg = start_reg, idx++; reg <= end_reg; reg += 4, idx++) { 232662306a36Sopenharmony_ci if (evergreen_is_safe_reg(p, reg)) 232762306a36Sopenharmony_ci continue; 232862306a36Sopenharmony_ci r = evergreen_cs_handle_reg(p, reg, idx); 232962306a36Sopenharmony_ci if (r) 233062306a36Sopenharmony_ci return r; 233162306a36Sopenharmony_ci } 233262306a36Sopenharmony_ci break; 233362306a36Sopenharmony_ci case PACKET3_SET_RESOURCE: 233462306a36Sopenharmony_ci if (pkt->count % 8) { 233562306a36Sopenharmony_ci DRM_ERROR("bad SET_RESOURCE\n"); 233662306a36Sopenharmony_ci return -EINVAL; 233762306a36Sopenharmony_ci } 233862306a36Sopenharmony_ci start_reg = (idx_value << 2) + PACKET3_SET_RESOURCE_START; 233962306a36Sopenharmony_ci end_reg = 4 * pkt->count + start_reg - 4; 234062306a36Sopenharmony_ci if ((start_reg < PACKET3_SET_RESOURCE_START) || 234162306a36Sopenharmony_ci (start_reg >= PACKET3_SET_RESOURCE_END) || 234262306a36Sopenharmony_ci (end_reg >= PACKET3_SET_RESOURCE_END)) { 234362306a36Sopenharmony_ci DRM_ERROR("bad SET_RESOURCE\n"); 234462306a36Sopenharmony_ci return -EINVAL; 234562306a36Sopenharmony_ci } 234662306a36Sopenharmony_ci for (i = 0; i < (pkt->count / 8); i++) { 234762306a36Sopenharmony_ci struct radeon_bo *texture, *mipmap; 234862306a36Sopenharmony_ci u32 toffset, moffset; 234962306a36Sopenharmony_ci u32 size, offset, mip_address, tex_dim; 235062306a36Sopenharmony_ci 235162306a36Sopenharmony_ci switch (G__SQ_CONSTANT_TYPE(radeon_get_ib_value(p, idx+1+(i*8)+7))) { 235262306a36Sopenharmony_ci case SQ_TEX_VTX_VALID_TEXTURE: 235362306a36Sopenharmony_ci /* tex base */ 235462306a36Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 235562306a36Sopenharmony_ci if (r) { 235662306a36Sopenharmony_ci DRM_ERROR("bad SET_RESOURCE (tex)\n"); 235762306a36Sopenharmony_ci return -EINVAL; 235862306a36Sopenharmony_ci } 235962306a36Sopenharmony_ci if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { 236062306a36Sopenharmony_ci ib[idx+1+(i*8)+1] |= 236162306a36Sopenharmony_ci TEX_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->tiling_flags)); 236262306a36Sopenharmony_ci if (reloc->tiling_flags & RADEON_TILING_MACRO) { 236362306a36Sopenharmony_ci unsigned bankw, bankh, mtaspect, tile_split; 236462306a36Sopenharmony_ci 236562306a36Sopenharmony_ci evergreen_tiling_fields(reloc->tiling_flags, 236662306a36Sopenharmony_ci &bankw, &bankh, &mtaspect, 236762306a36Sopenharmony_ci &tile_split); 236862306a36Sopenharmony_ci ib[idx+1+(i*8)+6] |= TEX_TILE_SPLIT(tile_split); 236962306a36Sopenharmony_ci ib[idx+1+(i*8)+7] |= 237062306a36Sopenharmony_ci TEX_BANK_WIDTH(bankw) | 237162306a36Sopenharmony_ci TEX_BANK_HEIGHT(bankh) | 237262306a36Sopenharmony_ci MACRO_TILE_ASPECT(mtaspect) | 237362306a36Sopenharmony_ci TEX_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks)); 237462306a36Sopenharmony_ci } 237562306a36Sopenharmony_ci } 237662306a36Sopenharmony_ci texture = reloc->robj; 237762306a36Sopenharmony_ci toffset = (u32)((reloc->gpu_offset >> 8) & 0xffffffff); 237862306a36Sopenharmony_ci 237962306a36Sopenharmony_ci /* tex mip base */ 238062306a36Sopenharmony_ci tex_dim = ib[idx+1+(i*8)+0] & 0x7; 238162306a36Sopenharmony_ci mip_address = ib[idx+1+(i*8)+3]; 238262306a36Sopenharmony_ci 238362306a36Sopenharmony_ci if ((tex_dim == SQ_TEX_DIM_2D_MSAA || tex_dim == SQ_TEX_DIM_2D_ARRAY_MSAA) && 238462306a36Sopenharmony_ci !mip_address && 238562306a36Sopenharmony_ci !radeon_cs_packet_next_is_pkt3_nop(p)) { 238662306a36Sopenharmony_ci /* MIP_ADDRESS should point to FMASK for an MSAA texture. 238762306a36Sopenharmony_ci * It should be 0 if FMASK is disabled. */ 238862306a36Sopenharmony_ci moffset = 0; 238962306a36Sopenharmony_ci mipmap = NULL; 239062306a36Sopenharmony_ci } else { 239162306a36Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 239262306a36Sopenharmony_ci if (r) { 239362306a36Sopenharmony_ci DRM_ERROR("bad SET_RESOURCE (tex)\n"); 239462306a36Sopenharmony_ci return -EINVAL; 239562306a36Sopenharmony_ci } 239662306a36Sopenharmony_ci moffset = (u32)((reloc->gpu_offset >> 8) & 0xffffffff); 239762306a36Sopenharmony_ci mipmap = reloc->robj; 239862306a36Sopenharmony_ci } 239962306a36Sopenharmony_ci 240062306a36Sopenharmony_ci r = evergreen_cs_track_validate_texture(p, texture, mipmap, idx+1+(i*8)); 240162306a36Sopenharmony_ci if (r) 240262306a36Sopenharmony_ci return r; 240362306a36Sopenharmony_ci ib[idx+1+(i*8)+2] += toffset; 240462306a36Sopenharmony_ci ib[idx+1+(i*8)+3] += moffset; 240562306a36Sopenharmony_ci break; 240662306a36Sopenharmony_ci case SQ_TEX_VTX_VALID_BUFFER: 240762306a36Sopenharmony_ci { 240862306a36Sopenharmony_ci uint64_t offset64; 240962306a36Sopenharmony_ci /* vtx base */ 241062306a36Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 241162306a36Sopenharmony_ci if (r) { 241262306a36Sopenharmony_ci DRM_ERROR("bad SET_RESOURCE (vtx)\n"); 241362306a36Sopenharmony_ci return -EINVAL; 241462306a36Sopenharmony_ci } 241562306a36Sopenharmony_ci offset = radeon_get_ib_value(p, idx+1+(i*8)+0); 241662306a36Sopenharmony_ci size = radeon_get_ib_value(p, idx+1+(i*8)+1); 241762306a36Sopenharmony_ci if (p->rdev && (size + offset) > radeon_bo_size(reloc->robj)) { 241862306a36Sopenharmony_ci /* force size to size of the buffer */ 241962306a36Sopenharmony_ci dev_warn_ratelimited(p->dev, "vbo resource seems too big for the bo\n"); 242062306a36Sopenharmony_ci ib[idx+1+(i*8)+1] = radeon_bo_size(reloc->robj) - offset; 242162306a36Sopenharmony_ci } 242262306a36Sopenharmony_ci 242362306a36Sopenharmony_ci offset64 = reloc->gpu_offset + offset; 242462306a36Sopenharmony_ci ib[idx+1+(i*8)+0] = offset64; 242562306a36Sopenharmony_ci ib[idx+1+(i*8)+2] = (ib[idx+1+(i*8)+2] & 0xffffff00) | 242662306a36Sopenharmony_ci (upper_32_bits(offset64) & 0xff); 242762306a36Sopenharmony_ci break; 242862306a36Sopenharmony_ci } 242962306a36Sopenharmony_ci case SQ_TEX_VTX_INVALID_TEXTURE: 243062306a36Sopenharmony_ci case SQ_TEX_VTX_INVALID_BUFFER: 243162306a36Sopenharmony_ci default: 243262306a36Sopenharmony_ci DRM_ERROR("bad SET_RESOURCE\n"); 243362306a36Sopenharmony_ci return -EINVAL; 243462306a36Sopenharmony_ci } 243562306a36Sopenharmony_ci } 243662306a36Sopenharmony_ci break; 243762306a36Sopenharmony_ci case PACKET3_SET_ALU_CONST: 243862306a36Sopenharmony_ci /* XXX fix me ALU const buffers only */ 243962306a36Sopenharmony_ci break; 244062306a36Sopenharmony_ci case PACKET3_SET_BOOL_CONST: 244162306a36Sopenharmony_ci start_reg = (idx_value << 2) + PACKET3_SET_BOOL_CONST_START; 244262306a36Sopenharmony_ci end_reg = 4 * pkt->count + start_reg - 4; 244362306a36Sopenharmony_ci if ((start_reg < PACKET3_SET_BOOL_CONST_START) || 244462306a36Sopenharmony_ci (start_reg >= PACKET3_SET_BOOL_CONST_END) || 244562306a36Sopenharmony_ci (end_reg >= PACKET3_SET_BOOL_CONST_END)) { 244662306a36Sopenharmony_ci DRM_ERROR("bad SET_BOOL_CONST\n"); 244762306a36Sopenharmony_ci return -EINVAL; 244862306a36Sopenharmony_ci } 244962306a36Sopenharmony_ci break; 245062306a36Sopenharmony_ci case PACKET3_SET_LOOP_CONST: 245162306a36Sopenharmony_ci start_reg = (idx_value << 2) + PACKET3_SET_LOOP_CONST_START; 245262306a36Sopenharmony_ci end_reg = 4 * pkt->count + start_reg - 4; 245362306a36Sopenharmony_ci if ((start_reg < PACKET3_SET_LOOP_CONST_START) || 245462306a36Sopenharmony_ci (start_reg >= PACKET3_SET_LOOP_CONST_END) || 245562306a36Sopenharmony_ci (end_reg >= PACKET3_SET_LOOP_CONST_END)) { 245662306a36Sopenharmony_ci DRM_ERROR("bad SET_LOOP_CONST\n"); 245762306a36Sopenharmony_ci return -EINVAL; 245862306a36Sopenharmony_ci } 245962306a36Sopenharmony_ci break; 246062306a36Sopenharmony_ci case PACKET3_SET_CTL_CONST: 246162306a36Sopenharmony_ci start_reg = (idx_value << 2) + PACKET3_SET_CTL_CONST_START; 246262306a36Sopenharmony_ci end_reg = 4 * pkt->count + start_reg - 4; 246362306a36Sopenharmony_ci if ((start_reg < PACKET3_SET_CTL_CONST_START) || 246462306a36Sopenharmony_ci (start_reg >= PACKET3_SET_CTL_CONST_END) || 246562306a36Sopenharmony_ci (end_reg >= PACKET3_SET_CTL_CONST_END)) { 246662306a36Sopenharmony_ci DRM_ERROR("bad SET_CTL_CONST\n"); 246762306a36Sopenharmony_ci return -EINVAL; 246862306a36Sopenharmony_ci } 246962306a36Sopenharmony_ci break; 247062306a36Sopenharmony_ci case PACKET3_SET_SAMPLER: 247162306a36Sopenharmony_ci if (pkt->count % 3) { 247262306a36Sopenharmony_ci DRM_ERROR("bad SET_SAMPLER\n"); 247362306a36Sopenharmony_ci return -EINVAL; 247462306a36Sopenharmony_ci } 247562306a36Sopenharmony_ci start_reg = (idx_value << 2) + PACKET3_SET_SAMPLER_START; 247662306a36Sopenharmony_ci end_reg = 4 * pkt->count + start_reg - 4; 247762306a36Sopenharmony_ci if ((start_reg < PACKET3_SET_SAMPLER_START) || 247862306a36Sopenharmony_ci (start_reg >= PACKET3_SET_SAMPLER_END) || 247962306a36Sopenharmony_ci (end_reg >= PACKET3_SET_SAMPLER_END)) { 248062306a36Sopenharmony_ci DRM_ERROR("bad SET_SAMPLER\n"); 248162306a36Sopenharmony_ci return -EINVAL; 248262306a36Sopenharmony_ci } 248362306a36Sopenharmony_ci break; 248462306a36Sopenharmony_ci case PACKET3_STRMOUT_BUFFER_UPDATE: 248562306a36Sopenharmony_ci if (pkt->count != 4) { 248662306a36Sopenharmony_ci DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (invalid count)\n"); 248762306a36Sopenharmony_ci return -EINVAL; 248862306a36Sopenharmony_ci } 248962306a36Sopenharmony_ci /* Updating memory at DST_ADDRESS. */ 249062306a36Sopenharmony_ci if (idx_value & 0x1) { 249162306a36Sopenharmony_ci u64 offset; 249262306a36Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 249362306a36Sopenharmony_ci if (r) { 249462306a36Sopenharmony_ci DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing dst reloc)\n"); 249562306a36Sopenharmony_ci return -EINVAL; 249662306a36Sopenharmony_ci } 249762306a36Sopenharmony_ci offset = radeon_get_ib_value(p, idx+1); 249862306a36Sopenharmony_ci offset += ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32; 249962306a36Sopenharmony_ci if ((offset + 4) > radeon_bo_size(reloc->robj)) { 250062306a36Sopenharmony_ci DRM_ERROR("bad STRMOUT_BUFFER_UPDATE dst bo too small: 0x%llx, 0x%lx\n", 250162306a36Sopenharmony_ci offset + 4, radeon_bo_size(reloc->robj)); 250262306a36Sopenharmony_ci return -EINVAL; 250362306a36Sopenharmony_ci } 250462306a36Sopenharmony_ci offset += reloc->gpu_offset; 250562306a36Sopenharmony_ci ib[idx+1] = offset; 250662306a36Sopenharmony_ci ib[idx+2] = upper_32_bits(offset) & 0xff; 250762306a36Sopenharmony_ci } 250862306a36Sopenharmony_ci /* Reading data from SRC_ADDRESS. */ 250962306a36Sopenharmony_ci if (((idx_value >> 1) & 0x3) == 2) { 251062306a36Sopenharmony_ci u64 offset; 251162306a36Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 251262306a36Sopenharmony_ci if (r) { 251362306a36Sopenharmony_ci DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing src reloc)\n"); 251462306a36Sopenharmony_ci return -EINVAL; 251562306a36Sopenharmony_ci } 251662306a36Sopenharmony_ci offset = radeon_get_ib_value(p, idx+3); 251762306a36Sopenharmony_ci offset += ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32; 251862306a36Sopenharmony_ci if ((offset + 4) > radeon_bo_size(reloc->robj)) { 251962306a36Sopenharmony_ci DRM_ERROR("bad STRMOUT_BUFFER_UPDATE src bo too small: 0x%llx, 0x%lx\n", 252062306a36Sopenharmony_ci offset + 4, radeon_bo_size(reloc->robj)); 252162306a36Sopenharmony_ci return -EINVAL; 252262306a36Sopenharmony_ci } 252362306a36Sopenharmony_ci offset += reloc->gpu_offset; 252462306a36Sopenharmony_ci ib[idx+3] = offset; 252562306a36Sopenharmony_ci ib[idx+4] = upper_32_bits(offset) & 0xff; 252662306a36Sopenharmony_ci } 252762306a36Sopenharmony_ci break; 252862306a36Sopenharmony_ci case PACKET3_MEM_WRITE: 252962306a36Sopenharmony_ci { 253062306a36Sopenharmony_ci u64 offset; 253162306a36Sopenharmony_ci 253262306a36Sopenharmony_ci if (pkt->count != 3) { 253362306a36Sopenharmony_ci DRM_ERROR("bad MEM_WRITE (invalid count)\n"); 253462306a36Sopenharmony_ci return -EINVAL; 253562306a36Sopenharmony_ci } 253662306a36Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 253762306a36Sopenharmony_ci if (r) { 253862306a36Sopenharmony_ci DRM_ERROR("bad MEM_WRITE (missing reloc)\n"); 253962306a36Sopenharmony_ci return -EINVAL; 254062306a36Sopenharmony_ci } 254162306a36Sopenharmony_ci offset = radeon_get_ib_value(p, idx+0); 254262306a36Sopenharmony_ci offset += ((u64)(radeon_get_ib_value(p, idx+1) & 0xff)) << 32UL; 254362306a36Sopenharmony_ci if (offset & 0x7) { 254462306a36Sopenharmony_ci DRM_ERROR("bad MEM_WRITE (address not qwords aligned)\n"); 254562306a36Sopenharmony_ci return -EINVAL; 254662306a36Sopenharmony_ci } 254762306a36Sopenharmony_ci if ((offset + 8) > radeon_bo_size(reloc->robj)) { 254862306a36Sopenharmony_ci DRM_ERROR("bad MEM_WRITE bo too small: 0x%llx, 0x%lx\n", 254962306a36Sopenharmony_ci offset + 8, radeon_bo_size(reloc->robj)); 255062306a36Sopenharmony_ci return -EINVAL; 255162306a36Sopenharmony_ci } 255262306a36Sopenharmony_ci offset += reloc->gpu_offset; 255362306a36Sopenharmony_ci ib[idx+0] = offset; 255462306a36Sopenharmony_ci ib[idx+1] = upper_32_bits(offset) & 0xff; 255562306a36Sopenharmony_ci break; 255662306a36Sopenharmony_ci } 255762306a36Sopenharmony_ci case PACKET3_COPY_DW: 255862306a36Sopenharmony_ci if (pkt->count != 4) { 255962306a36Sopenharmony_ci DRM_ERROR("bad COPY_DW (invalid count)\n"); 256062306a36Sopenharmony_ci return -EINVAL; 256162306a36Sopenharmony_ci } 256262306a36Sopenharmony_ci if (idx_value & 0x1) { 256362306a36Sopenharmony_ci u64 offset; 256462306a36Sopenharmony_ci /* SRC is memory. */ 256562306a36Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 256662306a36Sopenharmony_ci if (r) { 256762306a36Sopenharmony_ci DRM_ERROR("bad COPY_DW (missing src reloc)\n"); 256862306a36Sopenharmony_ci return -EINVAL; 256962306a36Sopenharmony_ci } 257062306a36Sopenharmony_ci offset = radeon_get_ib_value(p, idx+1); 257162306a36Sopenharmony_ci offset += ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32; 257262306a36Sopenharmony_ci if ((offset + 4) > radeon_bo_size(reloc->robj)) { 257362306a36Sopenharmony_ci DRM_ERROR("bad COPY_DW src bo too small: 0x%llx, 0x%lx\n", 257462306a36Sopenharmony_ci offset + 4, radeon_bo_size(reloc->robj)); 257562306a36Sopenharmony_ci return -EINVAL; 257662306a36Sopenharmony_ci } 257762306a36Sopenharmony_ci offset += reloc->gpu_offset; 257862306a36Sopenharmony_ci ib[idx+1] = offset; 257962306a36Sopenharmony_ci ib[idx+2] = upper_32_bits(offset) & 0xff; 258062306a36Sopenharmony_ci } else { 258162306a36Sopenharmony_ci /* SRC is a reg. */ 258262306a36Sopenharmony_ci reg = radeon_get_ib_value(p, idx+1) << 2; 258362306a36Sopenharmony_ci if (!evergreen_is_safe_reg(p, reg)) { 258462306a36Sopenharmony_ci dev_warn(p->dev, "forbidden register 0x%08x at %d\n", 258562306a36Sopenharmony_ci reg, idx + 1); 258662306a36Sopenharmony_ci return -EINVAL; 258762306a36Sopenharmony_ci } 258862306a36Sopenharmony_ci } 258962306a36Sopenharmony_ci if (idx_value & 0x2) { 259062306a36Sopenharmony_ci u64 offset; 259162306a36Sopenharmony_ci /* DST is memory. */ 259262306a36Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 259362306a36Sopenharmony_ci if (r) { 259462306a36Sopenharmony_ci DRM_ERROR("bad COPY_DW (missing dst reloc)\n"); 259562306a36Sopenharmony_ci return -EINVAL; 259662306a36Sopenharmony_ci } 259762306a36Sopenharmony_ci offset = radeon_get_ib_value(p, idx+3); 259862306a36Sopenharmony_ci offset += ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32; 259962306a36Sopenharmony_ci if ((offset + 4) > radeon_bo_size(reloc->robj)) { 260062306a36Sopenharmony_ci DRM_ERROR("bad COPY_DW dst bo too small: 0x%llx, 0x%lx\n", 260162306a36Sopenharmony_ci offset + 4, radeon_bo_size(reloc->robj)); 260262306a36Sopenharmony_ci return -EINVAL; 260362306a36Sopenharmony_ci } 260462306a36Sopenharmony_ci offset += reloc->gpu_offset; 260562306a36Sopenharmony_ci ib[idx+3] = offset; 260662306a36Sopenharmony_ci ib[idx+4] = upper_32_bits(offset) & 0xff; 260762306a36Sopenharmony_ci } else { 260862306a36Sopenharmony_ci /* DST is a reg. */ 260962306a36Sopenharmony_ci reg = radeon_get_ib_value(p, idx+3) << 2; 261062306a36Sopenharmony_ci if (!evergreen_is_safe_reg(p, reg)) { 261162306a36Sopenharmony_ci dev_warn(p->dev, "forbidden register 0x%08x at %d\n", 261262306a36Sopenharmony_ci reg, idx + 3); 261362306a36Sopenharmony_ci return -EINVAL; 261462306a36Sopenharmony_ci } 261562306a36Sopenharmony_ci } 261662306a36Sopenharmony_ci break; 261762306a36Sopenharmony_ci case PACKET3_SET_APPEND_CNT: 261862306a36Sopenharmony_ci { 261962306a36Sopenharmony_ci uint32_t areg; 262062306a36Sopenharmony_ci uint32_t allowed_reg_base; 262162306a36Sopenharmony_ci uint32_t source_sel; 262262306a36Sopenharmony_ci if (pkt->count != 2) { 262362306a36Sopenharmony_ci DRM_ERROR("bad SET_APPEND_CNT (invalid count)\n"); 262462306a36Sopenharmony_ci return -EINVAL; 262562306a36Sopenharmony_ci } 262662306a36Sopenharmony_ci 262762306a36Sopenharmony_ci allowed_reg_base = GDS_APPEND_COUNT_0; 262862306a36Sopenharmony_ci allowed_reg_base -= PACKET3_SET_CONTEXT_REG_START; 262962306a36Sopenharmony_ci allowed_reg_base >>= 2; 263062306a36Sopenharmony_ci 263162306a36Sopenharmony_ci areg = idx_value >> 16; 263262306a36Sopenharmony_ci if (areg < allowed_reg_base || areg > (allowed_reg_base + 11)) { 263362306a36Sopenharmony_ci dev_warn(p->dev, "forbidden register for append cnt 0x%08x at %d\n", 263462306a36Sopenharmony_ci areg, idx); 263562306a36Sopenharmony_ci return -EINVAL; 263662306a36Sopenharmony_ci } 263762306a36Sopenharmony_ci 263862306a36Sopenharmony_ci source_sel = G_PACKET3_SET_APPEND_CNT_SRC_SELECT(idx_value); 263962306a36Sopenharmony_ci if (source_sel == PACKET3_SAC_SRC_SEL_MEM) { 264062306a36Sopenharmony_ci uint64_t offset; 264162306a36Sopenharmony_ci uint32_t swap; 264262306a36Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 264362306a36Sopenharmony_ci if (r) { 264462306a36Sopenharmony_ci DRM_ERROR("bad SET_APPEND_CNT (missing reloc)\n"); 264562306a36Sopenharmony_ci return -EINVAL; 264662306a36Sopenharmony_ci } 264762306a36Sopenharmony_ci offset = radeon_get_ib_value(p, idx + 1); 264862306a36Sopenharmony_ci swap = offset & 0x3; 264962306a36Sopenharmony_ci offset &= ~0x3; 265062306a36Sopenharmony_ci 265162306a36Sopenharmony_ci offset += ((u64)(radeon_get_ib_value(p, idx + 2) & 0xff)) << 32; 265262306a36Sopenharmony_ci 265362306a36Sopenharmony_ci offset += reloc->gpu_offset; 265462306a36Sopenharmony_ci ib[idx+1] = (offset & 0xfffffffc) | swap; 265562306a36Sopenharmony_ci ib[idx+2] = upper_32_bits(offset) & 0xff; 265662306a36Sopenharmony_ci } else { 265762306a36Sopenharmony_ci DRM_ERROR("bad SET_APPEND_CNT (unsupported operation)\n"); 265862306a36Sopenharmony_ci return -EINVAL; 265962306a36Sopenharmony_ci } 266062306a36Sopenharmony_ci break; 266162306a36Sopenharmony_ci } 266262306a36Sopenharmony_ci case PACKET3_NOP: 266362306a36Sopenharmony_ci break; 266462306a36Sopenharmony_ci default: 266562306a36Sopenharmony_ci DRM_ERROR("Packet3 opcode %x not supported\n", pkt->opcode); 266662306a36Sopenharmony_ci return -EINVAL; 266762306a36Sopenharmony_ci } 266862306a36Sopenharmony_ci return 0; 266962306a36Sopenharmony_ci} 267062306a36Sopenharmony_ci 267162306a36Sopenharmony_ciint evergreen_cs_parse(struct radeon_cs_parser *p) 267262306a36Sopenharmony_ci{ 267362306a36Sopenharmony_ci struct radeon_cs_packet pkt; 267462306a36Sopenharmony_ci struct evergreen_cs_track *track; 267562306a36Sopenharmony_ci u32 tmp; 267662306a36Sopenharmony_ci int r; 267762306a36Sopenharmony_ci 267862306a36Sopenharmony_ci if (p->track == NULL) { 267962306a36Sopenharmony_ci /* initialize tracker, we are in kms */ 268062306a36Sopenharmony_ci track = kzalloc(sizeof(*track), GFP_KERNEL); 268162306a36Sopenharmony_ci if (track == NULL) 268262306a36Sopenharmony_ci return -ENOMEM; 268362306a36Sopenharmony_ci evergreen_cs_track_init(track); 268462306a36Sopenharmony_ci if (p->rdev->family >= CHIP_CAYMAN) { 268562306a36Sopenharmony_ci tmp = p->rdev->config.cayman.tile_config; 268662306a36Sopenharmony_ci track->reg_safe_bm = cayman_reg_safe_bm; 268762306a36Sopenharmony_ci } else { 268862306a36Sopenharmony_ci tmp = p->rdev->config.evergreen.tile_config; 268962306a36Sopenharmony_ci track->reg_safe_bm = evergreen_reg_safe_bm; 269062306a36Sopenharmony_ci } 269162306a36Sopenharmony_ci BUILD_BUG_ON(ARRAY_SIZE(cayman_reg_safe_bm) != REG_SAFE_BM_SIZE); 269262306a36Sopenharmony_ci BUILD_BUG_ON(ARRAY_SIZE(evergreen_reg_safe_bm) != REG_SAFE_BM_SIZE); 269362306a36Sopenharmony_ci switch (tmp & 0xf) { 269462306a36Sopenharmony_ci case 0: 269562306a36Sopenharmony_ci track->npipes = 1; 269662306a36Sopenharmony_ci break; 269762306a36Sopenharmony_ci case 1: 269862306a36Sopenharmony_ci default: 269962306a36Sopenharmony_ci track->npipes = 2; 270062306a36Sopenharmony_ci break; 270162306a36Sopenharmony_ci case 2: 270262306a36Sopenharmony_ci track->npipes = 4; 270362306a36Sopenharmony_ci break; 270462306a36Sopenharmony_ci case 3: 270562306a36Sopenharmony_ci track->npipes = 8; 270662306a36Sopenharmony_ci break; 270762306a36Sopenharmony_ci } 270862306a36Sopenharmony_ci 270962306a36Sopenharmony_ci switch ((tmp & 0xf0) >> 4) { 271062306a36Sopenharmony_ci case 0: 271162306a36Sopenharmony_ci track->nbanks = 4; 271262306a36Sopenharmony_ci break; 271362306a36Sopenharmony_ci case 1: 271462306a36Sopenharmony_ci default: 271562306a36Sopenharmony_ci track->nbanks = 8; 271662306a36Sopenharmony_ci break; 271762306a36Sopenharmony_ci case 2: 271862306a36Sopenharmony_ci track->nbanks = 16; 271962306a36Sopenharmony_ci break; 272062306a36Sopenharmony_ci } 272162306a36Sopenharmony_ci 272262306a36Sopenharmony_ci switch ((tmp & 0xf00) >> 8) { 272362306a36Sopenharmony_ci case 0: 272462306a36Sopenharmony_ci track->group_size = 256; 272562306a36Sopenharmony_ci break; 272662306a36Sopenharmony_ci case 1: 272762306a36Sopenharmony_ci default: 272862306a36Sopenharmony_ci track->group_size = 512; 272962306a36Sopenharmony_ci break; 273062306a36Sopenharmony_ci } 273162306a36Sopenharmony_ci 273262306a36Sopenharmony_ci switch ((tmp & 0xf000) >> 12) { 273362306a36Sopenharmony_ci case 0: 273462306a36Sopenharmony_ci track->row_size = 1; 273562306a36Sopenharmony_ci break; 273662306a36Sopenharmony_ci case 1: 273762306a36Sopenharmony_ci default: 273862306a36Sopenharmony_ci track->row_size = 2; 273962306a36Sopenharmony_ci break; 274062306a36Sopenharmony_ci case 2: 274162306a36Sopenharmony_ci track->row_size = 4; 274262306a36Sopenharmony_ci break; 274362306a36Sopenharmony_ci } 274462306a36Sopenharmony_ci 274562306a36Sopenharmony_ci p->track = track; 274662306a36Sopenharmony_ci } 274762306a36Sopenharmony_ci do { 274862306a36Sopenharmony_ci r = radeon_cs_packet_parse(p, &pkt, p->idx); 274962306a36Sopenharmony_ci if (r) { 275062306a36Sopenharmony_ci kfree(p->track); 275162306a36Sopenharmony_ci p->track = NULL; 275262306a36Sopenharmony_ci return r; 275362306a36Sopenharmony_ci } 275462306a36Sopenharmony_ci p->idx += pkt.count + 2; 275562306a36Sopenharmony_ci switch (pkt.type) { 275662306a36Sopenharmony_ci case RADEON_PACKET_TYPE0: 275762306a36Sopenharmony_ci r = evergreen_cs_parse_packet0(p, &pkt); 275862306a36Sopenharmony_ci break; 275962306a36Sopenharmony_ci case RADEON_PACKET_TYPE2: 276062306a36Sopenharmony_ci break; 276162306a36Sopenharmony_ci case RADEON_PACKET_TYPE3: 276262306a36Sopenharmony_ci r = evergreen_packet3_check(p, &pkt); 276362306a36Sopenharmony_ci break; 276462306a36Sopenharmony_ci default: 276562306a36Sopenharmony_ci DRM_ERROR("Unknown packet type %d !\n", pkt.type); 276662306a36Sopenharmony_ci kfree(p->track); 276762306a36Sopenharmony_ci p->track = NULL; 276862306a36Sopenharmony_ci return -EINVAL; 276962306a36Sopenharmony_ci } 277062306a36Sopenharmony_ci if (r) { 277162306a36Sopenharmony_ci kfree(p->track); 277262306a36Sopenharmony_ci p->track = NULL; 277362306a36Sopenharmony_ci return r; 277462306a36Sopenharmony_ci } 277562306a36Sopenharmony_ci } while (p->idx < p->chunk_ib->length_dw); 277662306a36Sopenharmony_ci#if 0 277762306a36Sopenharmony_ci for (r = 0; r < p->ib.length_dw; r++) { 277862306a36Sopenharmony_ci pr_info("%05d 0x%08X\n", r, p->ib.ptr[r]); 277962306a36Sopenharmony_ci mdelay(1); 278062306a36Sopenharmony_ci } 278162306a36Sopenharmony_ci#endif 278262306a36Sopenharmony_ci kfree(p->track); 278362306a36Sopenharmony_ci p->track = NULL; 278462306a36Sopenharmony_ci return 0; 278562306a36Sopenharmony_ci} 278662306a36Sopenharmony_ci 278762306a36Sopenharmony_ci/** 278862306a36Sopenharmony_ci * evergreen_dma_cs_parse() - parse the DMA IB 278962306a36Sopenharmony_ci * @p: parser structure holding parsing context. 279062306a36Sopenharmony_ci * 279162306a36Sopenharmony_ci * Parses the DMA IB from the CS ioctl and updates 279262306a36Sopenharmony_ci * the GPU addresses based on the reloc information and 279362306a36Sopenharmony_ci * checks for errors. (Evergreen-Cayman) 279462306a36Sopenharmony_ci * Returns 0 for success and an error on failure. 279562306a36Sopenharmony_ci **/ 279662306a36Sopenharmony_ciint evergreen_dma_cs_parse(struct radeon_cs_parser *p) 279762306a36Sopenharmony_ci{ 279862306a36Sopenharmony_ci struct radeon_cs_chunk *ib_chunk = p->chunk_ib; 279962306a36Sopenharmony_ci struct radeon_bo_list *src_reloc, *dst_reloc, *dst2_reloc; 280062306a36Sopenharmony_ci u32 header, cmd, count, sub_cmd; 280162306a36Sopenharmony_ci uint32_t *ib = p->ib.ptr; 280262306a36Sopenharmony_ci u32 idx; 280362306a36Sopenharmony_ci u64 src_offset, dst_offset, dst2_offset; 280462306a36Sopenharmony_ci int r; 280562306a36Sopenharmony_ci 280662306a36Sopenharmony_ci do { 280762306a36Sopenharmony_ci if (p->idx >= ib_chunk->length_dw) { 280862306a36Sopenharmony_ci DRM_ERROR("Can not parse packet at %d after CS end %d !\n", 280962306a36Sopenharmony_ci p->idx, ib_chunk->length_dw); 281062306a36Sopenharmony_ci return -EINVAL; 281162306a36Sopenharmony_ci } 281262306a36Sopenharmony_ci idx = p->idx; 281362306a36Sopenharmony_ci header = radeon_get_ib_value(p, idx); 281462306a36Sopenharmony_ci cmd = GET_DMA_CMD(header); 281562306a36Sopenharmony_ci count = GET_DMA_COUNT(header); 281662306a36Sopenharmony_ci sub_cmd = GET_DMA_SUB_CMD(header); 281762306a36Sopenharmony_ci 281862306a36Sopenharmony_ci switch (cmd) { 281962306a36Sopenharmony_ci case DMA_PACKET_WRITE: 282062306a36Sopenharmony_ci r = r600_dma_cs_next_reloc(p, &dst_reloc); 282162306a36Sopenharmony_ci if (r) { 282262306a36Sopenharmony_ci DRM_ERROR("bad DMA_PACKET_WRITE\n"); 282362306a36Sopenharmony_ci return -EINVAL; 282462306a36Sopenharmony_ci } 282562306a36Sopenharmony_ci switch (sub_cmd) { 282662306a36Sopenharmony_ci /* tiled */ 282762306a36Sopenharmony_ci case 8: 282862306a36Sopenharmony_ci dst_offset = radeon_get_ib_value(p, idx+1); 282962306a36Sopenharmony_ci dst_offset <<= 8; 283062306a36Sopenharmony_ci 283162306a36Sopenharmony_ci ib[idx+1] += (u32)(dst_reloc->gpu_offset >> 8); 283262306a36Sopenharmony_ci p->idx += count + 7; 283362306a36Sopenharmony_ci break; 283462306a36Sopenharmony_ci /* linear */ 283562306a36Sopenharmony_ci case 0: 283662306a36Sopenharmony_ci dst_offset = radeon_get_ib_value(p, idx+1); 283762306a36Sopenharmony_ci dst_offset |= ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32; 283862306a36Sopenharmony_ci 283962306a36Sopenharmony_ci ib[idx+1] += (u32)(dst_reloc->gpu_offset & 0xfffffffc); 284062306a36Sopenharmony_ci ib[idx+2] += upper_32_bits(dst_reloc->gpu_offset) & 0xff; 284162306a36Sopenharmony_ci p->idx += count + 3; 284262306a36Sopenharmony_ci break; 284362306a36Sopenharmony_ci default: 284462306a36Sopenharmony_ci DRM_ERROR("bad DMA_PACKET_WRITE [%6d] 0x%08x sub cmd is not 0 or 8\n", idx, header); 284562306a36Sopenharmony_ci return -EINVAL; 284662306a36Sopenharmony_ci } 284762306a36Sopenharmony_ci if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { 284862306a36Sopenharmony_ci dev_warn(p->dev, "DMA write buffer too small (%llu %lu)\n", 284962306a36Sopenharmony_ci dst_offset, radeon_bo_size(dst_reloc->robj)); 285062306a36Sopenharmony_ci return -EINVAL; 285162306a36Sopenharmony_ci } 285262306a36Sopenharmony_ci break; 285362306a36Sopenharmony_ci case DMA_PACKET_COPY: 285462306a36Sopenharmony_ci r = r600_dma_cs_next_reloc(p, &src_reloc); 285562306a36Sopenharmony_ci if (r) { 285662306a36Sopenharmony_ci DRM_ERROR("bad DMA_PACKET_COPY\n"); 285762306a36Sopenharmony_ci return -EINVAL; 285862306a36Sopenharmony_ci } 285962306a36Sopenharmony_ci r = r600_dma_cs_next_reloc(p, &dst_reloc); 286062306a36Sopenharmony_ci if (r) { 286162306a36Sopenharmony_ci DRM_ERROR("bad DMA_PACKET_COPY\n"); 286262306a36Sopenharmony_ci return -EINVAL; 286362306a36Sopenharmony_ci } 286462306a36Sopenharmony_ci switch (sub_cmd) { 286562306a36Sopenharmony_ci /* Copy L2L, DW aligned */ 286662306a36Sopenharmony_ci case 0x00: 286762306a36Sopenharmony_ci /* L2L, dw */ 286862306a36Sopenharmony_ci src_offset = radeon_get_ib_value(p, idx+2); 286962306a36Sopenharmony_ci src_offset |= ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32; 287062306a36Sopenharmony_ci dst_offset = radeon_get_ib_value(p, idx+1); 287162306a36Sopenharmony_ci dst_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0xff)) << 32; 287262306a36Sopenharmony_ci if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) { 287362306a36Sopenharmony_ci dev_warn(p->dev, "DMA L2L, dw src buffer too small (%llu %lu)\n", 287462306a36Sopenharmony_ci src_offset + (count * 4), radeon_bo_size(src_reloc->robj)); 287562306a36Sopenharmony_ci return -EINVAL; 287662306a36Sopenharmony_ci } 287762306a36Sopenharmony_ci if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { 287862306a36Sopenharmony_ci dev_warn(p->dev, "DMA L2L, dw dst buffer too small (%llu %lu)\n", 287962306a36Sopenharmony_ci dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj)); 288062306a36Sopenharmony_ci return -EINVAL; 288162306a36Sopenharmony_ci } 288262306a36Sopenharmony_ci ib[idx+1] += (u32)(dst_reloc->gpu_offset & 0xfffffffc); 288362306a36Sopenharmony_ci ib[idx+2] += (u32)(src_reloc->gpu_offset & 0xfffffffc); 288462306a36Sopenharmony_ci ib[idx+3] += upper_32_bits(dst_reloc->gpu_offset) & 0xff; 288562306a36Sopenharmony_ci ib[idx+4] += upper_32_bits(src_reloc->gpu_offset) & 0xff; 288662306a36Sopenharmony_ci p->idx += 5; 288762306a36Sopenharmony_ci break; 288862306a36Sopenharmony_ci /* Copy L2T/T2L */ 288962306a36Sopenharmony_ci case 0x08: 289062306a36Sopenharmony_ci /* detile bit */ 289162306a36Sopenharmony_ci if (radeon_get_ib_value(p, idx + 2) & (1 << 31)) { 289262306a36Sopenharmony_ci /* tiled src, linear dst */ 289362306a36Sopenharmony_ci src_offset = radeon_get_ib_value(p, idx+1); 289462306a36Sopenharmony_ci src_offset <<= 8; 289562306a36Sopenharmony_ci ib[idx+1] += (u32)(src_reloc->gpu_offset >> 8); 289662306a36Sopenharmony_ci 289762306a36Sopenharmony_ci dst_offset = radeon_get_ib_value(p, idx + 7); 289862306a36Sopenharmony_ci dst_offset |= ((u64)(radeon_get_ib_value(p, idx+8) & 0xff)) << 32; 289962306a36Sopenharmony_ci ib[idx+7] += (u32)(dst_reloc->gpu_offset & 0xfffffffc); 290062306a36Sopenharmony_ci ib[idx+8] += upper_32_bits(dst_reloc->gpu_offset) & 0xff; 290162306a36Sopenharmony_ci } else { 290262306a36Sopenharmony_ci /* linear src, tiled dst */ 290362306a36Sopenharmony_ci src_offset = radeon_get_ib_value(p, idx+7); 290462306a36Sopenharmony_ci src_offset |= ((u64)(radeon_get_ib_value(p, idx+8) & 0xff)) << 32; 290562306a36Sopenharmony_ci ib[idx+7] += (u32)(src_reloc->gpu_offset & 0xfffffffc); 290662306a36Sopenharmony_ci ib[idx+8] += upper_32_bits(src_reloc->gpu_offset) & 0xff; 290762306a36Sopenharmony_ci 290862306a36Sopenharmony_ci dst_offset = radeon_get_ib_value(p, idx+1); 290962306a36Sopenharmony_ci dst_offset <<= 8; 291062306a36Sopenharmony_ci ib[idx+1] += (u32)(dst_reloc->gpu_offset >> 8); 291162306a36Sopenharmony_ci } 291262306a36Sopenharmony_ci if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) { 291362306a36Sopenharmony_ci dev_warn(p->dev, "DMA L2T, src buffer too small (%llu %lu)\n", 291462306a36Sopenharmony_ci src_offset + (count * 4), radeon_bo_size(src_reloc->robj)); 291562306a36Sopenharmony_ci return -EINVAL; 291662306a36Sopenharmony_ci } 291762306a36Sopenharmony_ci if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { 291862306a36Sopenharmony_ci dev_warn(p->dev, "DMA L2T, dst buffer too small (%llu %lu)\n", 291962306a36Sopenharmony_ci dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj)); 292062306a36Sopenharmony_ci return -EINVAL; 292162306a36Sopenharmony_ci } 292262306a36Sopenharmony_ci p->idx += 9; 292362306a36Sopenharmony_ci break; 292462306a36Sopenharmony_ci /* Copy L2L, byte aligned */ 292562306a36Sopenharmony_ci case 0x40: 292662306a36Sopenharmony_ci /* L2L, byte */ 292762306a36Sopenharmony_ci src_offset = radeon_get_ib_value(p, idx+2); 292862306a36Sopenharmony_ci src_offset |= ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32; 292962306a36Sopenharmony_ci dst_offset = radeon_get_ib_value(p, idx+1); 293062306a36Sopenharmony_ci dst_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0xff)) << 32; 293162306a36Sopenharmony_ci if ((src_offset + count) > radeon_bo_size(src_reloc->robj)) { 293262306a36Sopenharmony_ci dev_warn(p->dev, "DMA L2L, byte src buffer too small (%llu %lu)\n", 293362306a36Sopenharmony_ci src_offset + count, radeon_bo_size(src_reloc->robj)); 293462306a36Sopenharmony_ci return -EINVAL; 293562306a36Sopenharmony_ci } 293662306a36Sopenharmony_ci if ((dst_offset + count) > radeon_bo_size(dst_reloc->robj)) { 293762306a36Sopenharmony_ci dev_warn(p->dev, "DMA L2L, byte dst buffer too small (%llu %lu)\n", 293862306a36Sopenharmony_ci dst_offset + count, radeon_bo_size(dst_reloc->robj)); 293962306a36Sopenharmony_ci return -EINVAL; 294062306a36Sopenharmony_ci } 294162306a36Sopenharmony_ci ib[idx+1] += (u32)(dst_reloc->gpu_offset & 0xffffffff); 294262306a36Sopenharmony_ci ib[idx+2] += (u32)(src_reloc->gpu_offset & 0xffffffff); 294362306a36Sopenharmony_ci ib[idx+3] += upper_32_bits(dst_reloc->gpu_offset) & 0xff; 294462306a36Sopenharmony_ci ib[idx+4] += upper_32_bits(src_reloc->gpu_offset) & 0xff; 294562306a36Sopenharmony_ci p->idx += 5; 294662306a36Sopenharmony_ci break; 294762306a36Sopenharmony_ci /* Copy L2L, partial */ 294862306a36Sopenharmony_ci case 0x41: 294962306a36Sopenharmony_ci /* L2L, partial */ 295062306a36Sopenharmony_ci if (p->family < CHIP_CAYMAN) { 295162306a36Sopenharmony_ci DRM_ERROR("L2L Partial is cayman only !\n"); 295262306a36Sopenharmony_ci return -EINVAL; 295362306a36Sopenharmony_ci } 295462306a36Sopenharmony_ci ib[idx+1] += (u32)(src_reloc->gpu_offset & 0xffffffff); 295562306a36Sopenharmony_ci ib[idx+2] += upper_32_bits(src_reloc->gpu_offset) & 0xff; 295662306a36Sopenharmony_ci ib[idx+4] += (u32)(dst_reloc->gpu_offset & 0xffffffff); 295762306a36Sopenharmony_ci ib[idx+5] += upper_32_bits(dst_reloc->gpu_offset) & 0xff; 295862306a36Sopenharmony_ci 295962306a36Sopenharmony_ci p->idx += 9; 296062306a36Sopenharmony_ci break; 296162306a36Sopenharmony_ci /* Copy L2L, DW aligned, broadcast */ 296262306a36Sopenharmony_ci case 0x44: 296362306a36Sopenharmony_ci /* L2L, dw, broadcast */ 296462306a36Sopenharmony_ci r = r600_dma_cs_next_reloc(p, &dst2_reloc); 296562306a36Sopenharmony_ci if (r) { 296662306a36Sopenharmony_ci DRM_ERROR("bad L2L, dw, broadcast DMA_PACKET_COPY\n"); 296762306a36Sopenharmony_ci return -EINVAL; 296862306a36Sopenharmony_ci } 296962306a36Sopenharmony_ci dst_offset = radeon_get_ib_value(p, idx+1); 297062306a36Sopenharmony_ci dst_offset |= ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32; 297162306a36Sopenharmony_ci dst2_offset = radeon_get_ib_value(p, idx+2); 297262306a36Sopenharmony_ci dst2_offset |= ((u64)(radeon_get_ib_value(p, idx+5) & 0xff)) << 32; 297362306a36Sopenharmony_ci src_offset = radeon_get_ib_value(p, idx+3); 297462306a36Sopenharmony_ci src_offset |= ((u64)(radeon_get_ib_value(p, idx+6) & 0xff)) << 32; 297562306a36Sopenharmony_ci if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) { 297662306a36Sopenharmony_ci dev_warn(p->dev, "DMA L2L, dw, broadcast src buffer too small (%llu %lu)\n", 297762306a36Sopenharmony_ci src_offset + (count * 4), radeon_bo_size(src_reloc->robj)); 297862306a36Sopenharmony_ci return -EINVAL; 297962306a36Sopenharmony_ci } 298062306a36Sopenharmony_ci if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { 298162306a36Sopenharmony_ci dev_warn(p->dev, "DMA L2L, dw, broadcast dst buffer too small (%llu %lu)\n", 298262306a36Sopenharmony_ci dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj)); 298362306a36Sopenharmony_ci return -EINVAL; 298462306a36Sopenharmony_ci } 298562306a36Sopenharmony_ci if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) { 298662306a36Sopenharmony_ci dev_warn(p->dev, "DMA L2L, dw, broadcast dst2 buffer too small (%llu %lu)\n", 298762306a36Sopenharmony_ci dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj)); 298862306a36Sopenharmony_ci return -EINVAL; 298962306a36Sopenharmony_ci } 299062306a36Sopenharmony_ci ib[idx+1] += (u32)(dst_reloc->gpu_offset & 0xfffffffc); 299162306a36Sopenharmony_ci ib[idx+2] += (u32)(dst2_reloc->gpu_offset & 0xfffffffc); 299262306a36Sopenharmony_ci ib[idx+3] += (u32)(src_reloc->gpu_offset & 0xfffffffc); 299362306a36Sopenharmony_ci ib[idx+4] += upper_32_bits(dst_reloc->gpu_offset) & 0xff; 299462306a36Sopenharmony_ci ib[idx+5] += upper_32_bits(dst2_reloc->gpu_offset) & 0xff; 299562306a36Sopenharmony_ci ib[idx+6] += upper_32_bits(src_reloc->gpu_offset) & 0xff; 299662306a36Sopenharmony_ci p->idx += 7; 299762306a36Sopenharmony_ci break; 299862306a36Sopenharmony_ci /* Copy L2T Frame to Field */ 299962306a36Sopenharmony_ci case 0x48: 300062306a36Sopenharmony_ci if (radeon_get_ib_value(p, idx + 2) & (1 << 31)) { 300162306a36Sopenharmony_ci DRM_ERROR("bad L2T, frame to fields DMA_PACKET_COPY\n"); 300262306a36Sopenharmony_ci return -EINVAL; 300362306a36Sopenharmony_ci } 300462306a36Sopenharmony_ci r = r600_dma_cs_next_reloc(p, &dst2_reloc); 300562306a36Sopenharmony_ci if (r) { 300662306a36Sopenharmony_ci DRM_ERROR("bad L2T, frame to fields DMA_PACKET_COPY\n"); 300762306a36Sopenharmony_ci return -EINVAL; 300862306a36Sopenharmony_ci } 300962306a36Sopenharmony_ci dst_offset = radeon_get_ib_value(p, idx+1); 301062306a36Sopenharmony_ci dst_offset <<= 8; 301162306a36Sopenharmony_ci dst2_offset = radeon_get_ib_value(p, idx+2); 301262306a36Sopenharmony_ci dst2_offset <<= 8; 301362306a36Sopenharmony_ci src_offset = radeon_get_ib_value(p, idx+8); 301462306a36Sopenharmony_ci src_offset |= ((u64)(radeon_get_ib_value(p, idx+9) & 0xff)) << 32; 301562306a36Sopenharmony_ci if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) { 301662306a36Sopenharmony_ci dev_warn(p->dev, "DMA L2T, frame to fields src buffer too small (%llu %lu)\n", 301762306a36Sopenharmony_ci src_offset + (count * 4), radeon_bo_size(src_reloc->robj)); 301862306a36Sopenharmony_ci return -EINVAL; 301962306a36Sopenharmony_ci } 302062306a36Sopenharmony_ci if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { 302162306a36Sopenharmony_ci dev_warn(p->dev, "DMA L2T, frame to fields buffer too small (%llu %lu)\n", 302262306a36Sopenharmony_ci dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj)); 302362306a36Sopenharmony_ci return -EINVAL; 302462306a36Sopenharmony_ci } 302562306a36Sopenharmony_ci if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) { 302662306a36Sopenharmony_ci dev_warn(p->dev, "DMA L2T, frame to fields buffer too small (%llu %lu)\n", 302762306a36Sopenharmony_ci dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj)); 302862306a36Sopenharmony_ci return -EINVAL; 302962306a36Sopenharmony_ci } 303062306a36Sopenharmony_ci ib[idx+1] += (u32)(dst_reloc->gpu_offset >> 8); 303162306a36Sopenharmony_ci ib[idx+2] += (u32)(dst2_reloc->gpu_offset >> 8); 303262306a36Sopenharmony_ci ib[idx+8] += (u32)(src_reloc->gpu_offset & 0xfffffffc); 303362306a36Sopenharmony_ci ib[idx+9] += upper_32_bits(src_reloc->gpu_offset) & 0xff; 303462306a36Sopenharmony_ci p->idx += 10; 303562306a36Sopenharmony_ci break; 303662306a36Sopenharmony_ci /* Copy L2T/T2L, partial */ 303762306a36Sopenharmony_ci case 0x49: 303862306a36Sopenharmony_ci /* L2T, T2L partial */ 303962306a36Sopenharmony_ci if (p->family < CHIP_CAYMAN) { 304062306a36Sopenharmony_ci DRM_ERROR("L2T, T2L Partial is cayman only !\n"); 304162306a36Sopenharmony_ci return -EINVAL; 304262306a36Sopenharmony_ci } 304362306a36Sopenharmony_ci /* detile bit */ 304462306a36Sopenharmony_ci if (radeon_get_ib_value(p, idx + 2) & (1 << 31)) { 304562306a36Sopenharmony_ci /* tiled src, linear dst */ 304662306a36Sopenharmony_ci ib[idx+1] += (u32)(src_reloc->gpu_offset >> 8); 304762306a36Sopenharmony_ci 304862306a36Sopenharmony_ci ib[idx+7] += (u32)(dst_reloc->gpu_offset & 0xfffffffc); 304962306a36Sopenharmony_ci ib[idx+8] += upper_32_bits(dst_reloc->gpu_offset) & 0xff; 305062306a36Sopenharmony_ci } else { 305162306a36Sopenharmony_ci /* linear src, tiled dst */ 305262306a36Sopenharmony_ci ib[idx+7] += (u32)(src_reloc->gpu_offset & 0xfffffffc); 305362306a36Sopenharmony_ci ib[idx+8] += upper_32_bits(src_reloc->gpu_offset) & 0xff; 305462306a36Sopenharmony_ci 305562306a36Sopenharmony_ci ib[idx+1] += (u32)(dst_reloc->gpu_offset >> 8); 305662306a36Sopenharmony_ci } 305762306a36Sopenharmony_ci p->idx += 12; 305862306a36Sopenharmony_ci break; 305962306a36Sopenharmony_ci /* Copy L2T broadcast */ 306062306a36Sopenharmony_ci case 0x4b: 306162306a36Sopenharmony_ci /* L2T, broadcast */ 306262306a36Sopenharmony_ci if (radeon_get_ib_value(p, idx + 2) & (1 << 31)) { 306362306a36Sopenharmony_ci DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n"); 306462306a36Sopenharmony_ci return -EINVAL; 306562306a36Sopenharmony_ci } 306662306a36Sopenharmony_ci r = r600_dma_cs_next_reloc(p, &dst2_reloc); 306762306a36Sopenharmony_ci if (r) { 306862306a36Sopenharmony_ci DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n"); 306962306a36Sopenharmony_ci return -EINVAL; 307062306a36Sopenharmony_ci } 307162306a36Sopenharmony_ci dst_offset = radeon_get_ib_value(p, idx+1); 307262306a36Sopenharmony_ci dst_offset <<= 8; 307362306a36Sopenharmony_ci dst2_offset = radeon_get_ib_value(p, idx+2); 307462306a36Sopenharmony_ci dst2_offset <<= 8; 307562306a36Sopenharmony_ci src_offset = radeon_get_ib_value(p, idx+8); 307662306a36Sopenharmony_ci src_offset |= ((u64)(radeon_get_ib_value(p, idx+9) & 0xff)) << 32; 307762306a36Sopenharmony_ci if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) { 307862306a36Sopenharmony_ci dev_warn(p->dev, "DMA L2T, broadcast src buffer too small (%llu %lu)\n", 307962306a36Sopenharmony_ci src_offset + (count * 4), radeon_bo_size(src_reloc->robj)); 308062306a36Sopenharmony_ci return -EINVAL; 308162306a36Sopenharmony_ci } 308262306a36Sopenharmony_ci if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { 308362306a36Sopenharmony_ci dev_warn(p->dev, "DMA L2T, broadcast dst buffer too small (%llu %lu)\n", 308462306a36Sopenharmony_ci dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj)); 308562306a36Sopenharmony_ci return -EINVAL; 308662306a36Sopenharmony_ci } 308762306a36Sopenharmony_ci if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) { 308862306a36Sopenharmony_ci dev_warn(p->dev, "DMA L2T, broadcast dst2 buffer too small (%llu %lu)\n", 308962306a36Sopenharmony_ci dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj)); 309062306a36Sopenharmony_ci return -EINVAL; 309162306a36Sopenharmony_ci } 309262306a36Sopenharmony_ci ib[idx+1] += (u32)(dst_reloc->gpu_offset >> 8); 309362306a36Sopenharmony_ci ib[idx+2] += (u32)(dst2_reloc->gpu_offset >> 8); 309462306a36Sopenharmony_ci ib[idx+8] += (u32)(src_reloc->gpu_offset & 0xfffffffc); 309562306a36Sopenharmony_ci ib[idx+9] += upper_32_bits(src_reloc->gpu_offset) & 0xff; 309662306a36Sopenharmony_ci p->idx += 10; 309762306a36Sopenharmony_ci break; 309862306a36Sopenharmony_ci /* Copy L2T/T2L (tile units) */ 309962306a36Sopenharmony_ci case 0x4c: 310062306a36Sopenharmony_ci /* L2T, T2L */ 310162306a36Sopenharmony_ci /* detile bit */ 310262306a36Sopenharmony_ci if (radeon_get_ib_value(p, idx + 2) & (1 << 31)) { 310362306a36Sopenharmony_ci /* tiled src, linear dst */ 310462306a36Sopenharmony_ci src_offset = radeon_get_ib_value(p, idx+1); 310562306a36Sopenharmony_ci src_offset <<= 8; 310662306a36Sopenharmony_ci ib[idx+1] += (u32)(src_reloc->gpu_offset >> 8); 310762306a36Sopenharmony_ci 310862306a36Sopenharmony_ci dst_offset = radeon_get_ib_value(p, idx+7); 310962306a36Sopenharmony_ci dst_offset |= ((u64)(radeon_get_ib_value(p, idx+8) & 0xff)) << 32; 311062306a36Sopenharmony_ci ib[idx+7] += (u32)(dst_reloc->gpu_offset & 0xfffffffc); 311162306a36Sopenharmony_ci ib[idx+8] += upper_32_bits(dst_reloc->gpu_offset) & 0xff; 311262306a36Sopenharmony_ci } else { 311362306a36Sopenharmony_ci /* linear src, tiled dst */ 311462306a36Sopenharmony_ci src_offset = radeon_get_ib_value(p, idx+7); 311562306a36Sopenharmony_ci src_offset |= ((u64)(radeon_get_ib_value(p, idx+8) & 0xff)) << 32; 311662306a36Sopenharmony_ci ib[idx+7] += (u32)(src_reloc->gpu_offset & 0xfffffffc); 311762306a36Sopenharmony_ci ib[idx+8] += upper_32_bits(src_reloc->gpu_offset) & 0xff; 311862306a36Sopenharmony_ci 311962306a36Sopenharmony_ci dst_offset = radeon_get_ib_value(p, idx+1); 312062306a36Sopenharmony_ci dst_offset <<= 8; 312162306a36Sopenharmony_ci ib[idx+1] += (u32)(dst_reloc->gpu_offset >> 8); 312262306a36Sopenharmony_ci } 312362306a36Sopenharmony_ci if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) { 312462306a36Sopenharmony_ci dev_warn(p->dev, "DMA L2T, T2L src buffer too small (%llu %lu)\n", 312562306a36Sopenharmony_ci src_offset + (count * 4), radeon_bo_size(src_reloc->robj)); 312662306a36Sopenharmony_ci return -EINVAL; 312762306a36Sopenharmony_ci } 312862306a36Sopenharmony_ci if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { 312962306a36Sopenharmony_ci dev_warn(p->dev, "DMA L2T, T2L dst buffer too small (%llu %lu)\n", 313062306a36Sopenharmony_ci dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj)); 313162306a36Sopenharmony_ci return -EINVAL; 313262306a36Sopenharmony_ci } 313362306a36Sopenharmony_ci p->idx += 9; 313462306a36Sopenharmony_ci break; 313562306a36Sopenharmony_ci /* Copy T2T, partial (tile units) */ 313662306a36Sopenharmony_ci case 0x4d: 313762306a36Sopenharmony_ci /* T2T partial */ 313862306a36Sopenharmony_ci if (p->family < CHIP_CAYMAN) { 313962306a36Sopenharmony_ci DRM_ERROR("L2T, T2L Partial is cayman only !\n"); 314062306a36Sopenharmony_ci return -EINVAL; 314162306a36Sopenharmony_ci } 314262306a36Sopenharmony_ci ib[idx+1] += (u32)(src_reloc->gpu_offset >> 8); 314362306a36Sopenharmony_ci ib[idx+4] += (u32)(dst_reloc->gpu_offset >> 8); 314462306a36Sopenharmony_ci p->idx += 13; 314562306a36Sopenharmony_ci break; 314662306a36Sopenharmony_ci /* Copy L2T broadcast (tile units) */ 314762306a36Sopenharmony_ci case 0x4f: 314862306a36Sopenharmony_ci /* L2T, broadcast */ 314962306a36Sopenharmony_ci if (radeon_get_ib_value(p, idx + 2) & (1 << 31)) { 315062306a36Sopenharmony_ci DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n"); 315162306a36Sopenharmony_ci return -EINVAL; 315262306a36Sopenharmony_ci } 315362306a36Sopenharmony_ci r = r600_dma_cs_next_reloc(p, &dst2_reloc); 315462306a36Sopenharmony_ci if (r) { 315562306a36Sopenharmony_ci DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n"); 315662306a36Sopenharmony_ci return -EINVAL; 315762306a36Sopenharmony_ci } 315862306a36Sopenharmony_ci dst_offset = radeon_get_ib_value(p, idx+1); 315962306a36Sopenharmony_ci dst_offset <<= 8; 316062306a36Sopenharmony_ci dst2_offset = radeon_get_ib_value(p, idx+2); 316162306a36Sopenharmony_ci dst2_offset <<= 8; 316262306a36Sopenharmony_ci src_offset = radeon_get_ib_value(p, idx+8); 316362306a36Sopenharmony_ci src_offset |= ((u64)(radeon_get_ib_value(p, idx+9) & 0xff)) << 32; 316462306a36Sopenharmony_ci if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) { 316562306a36Sopenharmony_ci dev_warn(p->dev, "DMA L2T, broadcast src buffer too small (%llu %lu)\n", 316662306a36Sopenharmony_ci src_offset + (count * 4), radeon_bo_size(src_reloc->robj)); 316762306a36Sopenharmony_ci return -EINVAL; 316862306a36Sopenharmony_ci } 316962306a36Sopenharmony_ci if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { 317062306a36Sopenharmony_ci dev_warn(p->dev, "DMA L2T, broadcast dst buffer too small (%llu %lu)\n", 317162306a36Sopenharmony_ci dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj)); 317262306a36Sopenharmony_ci return -EINVAL; 317362306a36Sopenharmony_ci } 317462306a36Sopenharmony_ci if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) { 317562306a36Sopenharmony_ci dev_warn(p->dev, "DMA L2T, broadcast dst2 buffer too small (%llu %lu)\n", 317662306a36Sopenharmony_ci dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj)); 317762306a36Sopenharmony_ci return -EINVAL; 317862306a36Sopenharmony_ci } 317962306a36Sopenharmony_ci ib[idx+1] += (u32)(dst_reloc->gpu_offset >> 8); 318062306a36Sopenharmony_ci ib[idx+2] += (u32)(dst2_reloc->gpu_offset >> 8); 318162306a36Sopenharmony_ci ib[idx+8] += (u32)(src_reloc->gpu_offset & 0xfffffffc); 318262306a36Sopenharmony_ci ib[idx+9] += upper_32_bits(src_reloc->gpu_offset) & 0xff; 318362306a36Sopenharmony_ci p->idx += 10; 318462306a36Sopenharmony_ci break; 318562306a36Sopenharmony_ci default: 318662306a36Sopenharmony_ci DRM_ERROR("bad DMA_PACKET_COPY [%6d] 0x%08x invalid sub cmd\n", idx, header); 318762306a36Sopenharmony_ci return -EINVAL; 318862306a36Sopenharmony_ci } 318962306a36Sopenharmony_ci break; 319062306a36Sopenharmony_ci case DMA_PACKET_CONSTANT_FILL: 319162306a36Sopenharmony_ci r = r600_dma_cs_next_reloc(p, &dst_reloc); 319262306a36Sopenharmony_ci if (r) { 319362306a36Sopenharmony_ci DRM_ERROR("bad DMA_PACKET_CONSTANT_FILL\n"); 319462306a36Sopenharmony_ci return -EINVAL; 319562306a36Sopenharmony_ci } 319662306a36Sopenharmony_ci dst_offset = radeon_get_ib_value(p, idx+1); 319762306a36Sopenharmony_ci dst_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0x00ff0000)) << 16; 319862306a36Sopenharmony_ci if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { 319962306a36Sopenharmony_ci dev_warn(p->dev, "DMA constant fill buffer too small (%llu %lu)\n", 320062306a36Sopenharmony_ci dst_offset, radeon_bo_size(dst_reloc->robj)); 320162306a36Sopenharmony_ci return -EINVAL; 320262306a36Sopenharmony_ci } 320362306a36Sopenharmony_ci ib[idx+1] += (u32)(dst_reloc->gpu_offset & 0xfffffffc); 320462306a36Sopenharmony_ci ib[idx+3] += (upper_32_bits(dst_reloc->gpu_offset) << 16) & 0x00ff0000; 320562306a36Sopenharmony_ci p->idx += 4; 320662306a36Sopenharmony_ci break; 320762306a36Sopenharmony_ci case DMA_PACKET_NOP: 320862306a36Sopenharmony_ci p->idx += 1; 320962306a36Sopenharmony_ci break; 321062306a36Sopenharmony_ci default: 321162306a36Sopenharmony_ci DRM_ERROR("Unknown packet type %d at %d !\n", cmd, idx); 321262306a36Sopenharmony_ci return -EINVAL; 321362306a36Sopenharmony_ci } 321462306a36Sopenharmony_ci } while (p->idx < p->chunk_ib->length_dw); 321562306a36Sopenharmony_ci#if 0 321662306a36Sopenharmony_ci for (r = 0; r < p->ib->length_dw; r++) { 321762306a36Sopenharmony_ci pr_info("%05d 0x%08X\n", r, p->ib.ptr[r]); 321862306a36Sopenharmony_ci mdelay(1); 321962306a36Sopenharmony_ci } 322062306a36Sopenharmony_ci#endif 322162306a36Sopenharmony_ci return 0; 322262306a36Sopenharmony_ci} 322362306a36Sopenharmony_ci 322462306a36Sopenharmony_ci/* vm parser */ 322562306a36Sopenharmony_cistatic bool evergreen_vm_reg_valid(u32 reg) 322662306a36Sopenharmony_ci{ 322762306a36Sopenharmony_ci /* context regs are fine */ 322862306a36Sopenharmony_ci if (reg >= 0x28000) 322962306a36Sopenharmony_ci return true; 323062306a36Sopenharmony_ci 323162306a36Sopenharmony_ci /* check config regs */ 323262306a36Sopenharmony_ci switch (reg) { 323362306a36Sopenharmony_ci case WAIT_UNTIL: 323462306a36Sopenharmony_ci case GRBM_GFX_INDEX: 323562306a36Sopenharmony_ci case CP_STRMOUT_CNTL: 323662306a36Sopenharmony_ci case CP_COHER_CNTL: 323762306a36Sopenharmony_ci case CP_COHER_SIZE: 323862306a36Sopenharmony_ci case VGT_VTX_VECT_EJECT_REG: 323962306a36Sopenharmony_ci case VGT_CACHE_INVALIDATION: 324062306a36Sopenharmony_ci case VGT_GS_VERTEX_REUSE: 324162306a36Sopenharmony_ci case VGT_PRIMITIVE_TYPE: 324262306a36Sopenharmony_ci case VGT_INDEX_TYPE: 324362306a36Sopenharmony_ci case VGT_NUM_INDICES: 324462306a36Sopenharmony_ci case VGT_NUM_INSTANCES: 324562306a36Sopenharmony_ci case VGT_COMPUTE_DIM_X: 324662306a36Sopenharmony_ci case VGT_COMPUTE_DIM_Y: 324762306a36Sopenharmony_ci case VGT_COMPUTE_DIM_Z: 324862306a36Sopenharmony_ci case VGT_COMPUTE_START_X: 324962306a36Sopenharmony_ci case VGT_COMPUTE_START_Y: 325062306a36Sopenharmony_ci case VGT_COMPUTE_START_Z: 325162306a36Sopenharmony_ci case VGT_COMPUTE_INDEX: 325262306a36Sopenharmony_ci case VGT_COMPUTE_THREAD_GROUP_SIZE: 325362306a36Sopenharmony_ci case VGT_HS_OFFCHIP_PARAM: 325462306a36Sopenharmony_ci case PA_CL_ENHANCE: 325562306a36Sopenharmony_ci case PA_SU_LINE_STIPPLE_VALUE: 325662306a36Sopenharmony_ci case PA_SC_LINE_STIPPLE_STATE: 325762306a36Sopenharmony_ci case PA_SC_ENHANCE: 325862306a36Sopenharmony_ci case SQ_DYN_GPR_CNTL_PS_FLUSH_REQ: 325962306a36Sopenharmony_ci case SQ_DYN_GPR_SIMD_LOCK_EN: 326062306a36Sopenharmony_ci case SQ_CONFIG: 326162306a36Sopenharmony_ci case SQ_GPR_RESOURCE_MGMT_1: 326262306a36Sopenharmony_ci case SQ_GLOBAL_GPR_RESOURCE_MGMT_1: 326362306a36Sopenharmony_ci case SQ_GLOBAL_GPR_RESOURCE_MGMT_2: 326462306a36Sopenharmony_ci case SQ_CONST_MEM_BASE: 326562306a36Sopenharmony_ci case SQ_STATIC_THREAD_MGMT_1: 326662306a36Sopenharmony_ci case SQ_STATIC_THREAD_MGMT_2: 326762306a36Sopenharmony_ci case SQ_STATIC_THREAD_MGMT_3: 326862306a36Sopenharmony_ci case SPI_CONFIG_CNTL: 326962306a36Sopenharmony_ci case SPI_CONFIG_CNTL_1: 327062306a36Sopenharmony_ci case TA_CNTL_AUX: 327162306a36Sopenharmony_ci case DB_DEBUG: 327262306a36Sopenharmony_ci case DB_DEBUG2: 327362306a36Sopenharmony_ci case DB_DEBUG3: 327462306a36Sopenharmony_ci case DB_DEBUG4: 327562306a36Sopenharmony_ci case DB_WATERMARKS: 327662306a36Sopenharmony_ci case TD_PS_BORDER_COLOR_INDEX: 327762306a36Sopenharmony_ci case TD_PS_BORDER_COLOR_RED: 327862306a36Sopenharmony_ci case TD_PS_BORDER_COLOR_GREEN: 327962306a36Sopenharmony_ci case TD_PS_BORDER_COLOR_BLUE: 328062306a36Sopenharmony_ci case TD_PS_BORDER_COLOR_ALPHA: 328162306a36Sopenharmony_ci case TD_VS_BORDER_COLOR_INDEX: 328262306a36Sopenharmony_ci case TD_VS_BORDER_COLOR_RED: 328362306a36Sopenharmony_ci case TD_VS_BORDER_COLOR_GREEN: 328462306a36Sopenharmony_ci case TD_VS_BORDER_COLOR_BLUE: 328562306a36Sopenharmony_ci case TD_VS_BORDER_COLOR_ALPHA: 328662306a36Sopenharmony_ci case TD_GS_BORDER_COLOR_INDEX: 328762306a36Sopenharmony_ci case TD_GS_BORDER_COLOR_RED: 328862306a36Sopenharmony_ci case TD_GS_BORDER_COLOR_GREEN: 328962306a36Sopenharmony_ci case TD_GS_BORDER_COLOR_BLUE: 329062306a36Sopenharmony_ci case TD_GS_BORDER_COLOR_ALPHA: 329162306a36Sopenharmony_ci case TD_HS_BORDER_COLOR_INDEX: 329262306a36Sopenharmony_ci case TD_HS_BORDER_COLOR_RED: 329362306a36Sopenharmony_ci case TD_HS_BORDER_COLOR_GREEN: 329462306a36Sopenharmony_ci case TD_HS_BORDER_COLOR_BLUE: 329562306a36Sopenharmony_ci case TD_HS_BORDER_COLOR_ALPHA: 329662306a36Sopenharmony_ci case TD_LS_BORDER_COLOR_INDEX: 329762306a36Sopenharmony_ci case TD_LS_BORDER_COLOR_RED: 329862306a36Sopenharmony_ci case TD_LS_BORDER_COLOR_GREEN: 329962306a36Sopenharmony_ci case TD_LS_BORDER_COLOR_BLUE: 330062306a36Sopenharmony_ci case TD_LS_BORDER_COLOR_ALPHA: 330162306a36Sopenharmony_ci case TD_CS_BORDER_COLOR_INDEX: 330262306a36Sopenharmony_ci case TD_CS_BORDER_COLOR_RED: 330362306a36Sopenharmony_ci case TD_CS_BORDER_COLOR_GREEN: 330462306a36Sopenharmony_ci case TD_CS_BORDER_COLOR_BLUE: 330562306a36Sopenharmony_ci case TD_CS_BORDER_COLOR_ALPHA: 330662306a36Sopenharmony_ci case SQ_ESGS_RING_SIZE: 330762306a36Sopenharmony_ci case SQ_GSVS_RING_SIZE: 330862306a36Sopenharmony_ci case SQ_ESTMP_RING_SIZE: 330962306a36Sopenharmony_ci case SQ_GSTMP_RING_SIZE: 331062306a36Sopenharmony_ci case SQ_HSTMP_RING_SIZE: 331162306a36Sopenharmony_ci case SQ_LSTMP_RING_SIZE: 331262306a36Sopenharmony_ci case SQ_PSTMP_RING_SIZE: 331362306a36Sopenharmony_ci case SQ_VSTMP_RING_SIZE: 331462306a36Sopenharmony_ci case SQ_ESGS_RING_ITEMSIZE: 331562306a36Sopenharmony_ci case SQ_ESTMP_RING_ITEMSIZE: 331662306a36Sopenharmony_ci case SQ_GSTMP_RING_ITEMSIZE: 331762306a36Sopenharmony_ci case SQ_GSVS_RING_ITEMSIZE: 331862306a36Sopenharmony_ci case SQ_GS_VERT_ITEMSIZE: 331962306a36Sopenharmony_ci case SQ_GS_VERT_ITEMSIZE_1: 332062306a36Sopenharmony_ci case SQ_GS_VERT_ITEMSIZE_2: 332162306a36Sopenharmony_ci case SQ_GS_VERT_ITEMSIZE_3: 332262306a36Sopenharmony_ci case SQ_GSVS_RING_OFFSET_1: 332362306a36Sopenharmony_ci case SQ_GSVS_RING_OFFSET_2: 332462306a36Sopenharmony_ci case SQ_GSVS_RING_OFFSET_3: 332562306a36Sopenharmony_ci case SQ_HSTMP_RING_ITEMSIZE: 332662306a36Sopenharmony_ci case SQ_LSTMP_RING_ITEMSIZE: 332762306a36Sopenharmony_ci case SQ_PSTMP_RING_ITEMSIZE: 332862306a36Sopenharmony_ci case SQ_VSTMP_RING_ITEMSIZE: 332962306a36Sopenharmony_ci case VGT_TF_RING_SIZE: 333062306a36Sopenharmony_ci case SQ_ESGS_RING_BASE: 333162306a36Sopenharmony_ci case SQ_GSVS_RING_BASE: 333262306a36Sopenharmony_ci case SQ_ESTMP_RING_BASE: 333362306a36Sopenharmony_ci case SQ_GSTMP_RING_BASE: 333462306a36Sopenharmony_ci case SQ_HSTMP_RING_BASE: 333562306a36Sopenharmony_ci case SQ_LSTMP_RING_BASE: 333662306a36Sopenharmony_ci case SQ_PSTMP_RING_BASE: 333762306a36Sopenharmony_ci case SQ_VSTMP_RING_BASE: 333862306a36Sopenharmony_ci case CAYMAN_VGT_OFFCHIP_LDS_BASE: 333962306a36Sopenharmony_ci case CAYMAN_SQ_EX_ALLOC_TABLE_SLOTS: 334062306a36Sopenharmony_ci return true; 334162306a36Sopenharmony_ci default: 334262306a36Sopenharmony_ci DRM_ERROR("Invalid register 0x%x in CS\n", reg); 334362306a36Sopenharmony_ci return false; 334462306a36Sopenharmony_ci } 334562306a36Sopenharmony_ci} 334662306a36Sopenharmony_ci 334762306a36Sopenharmony_cistatic int evergreen_vm_packet3_check(struct radeon_device *rdev, 334862306a36Sopenharmony_ci u32 *ib, struct radeon_cs_packet *pkt) 334962306a36Sopenharmony_ci{ 335062306a36Sopenharmony_ci u32 idx = pkt->idx + 1; 335162306a36Sopenharmony_ci u32 idx_value = ib[idx]; 335262306a36Sopenharmony_ci u32 start_reg, end_reg, reg, i; 335362306a36Sopenharmony_ci u32 command, info; 335462306a36Sopenharmony_ci 335562306a36Sopenharmony_ci switch (pkt->opcode) { 335662306a36Sopenharmony_ci case PACKET3_NOP: 335762306a36Sopenharmony_ci break; 335862306a36Sopenharmony_ci case PACKET3_SET_BASE: 335962306a36Sopenharmony_ci if (idx_value != 1) { 336062306a36Sopenharmony_ci DRM_ERROR("bad SET_BASE"); 336162306a36Sopenharmony_ci return -EINVAL; 336262306a36Sopenharmony_ci } 336362306a36Sopenharmony_ci break; 336462306a36Sopenharmony_ci case PACKET3_CLEAR_STATE: 336562306a36Sopenharmony_ci case PACKET3_INDEX_BUFFER_SIZE: 336662306a36Sopenharmony_ci case PACKET3_DISPATCH_DIRECT: 336762306a36Sopenharmony_ci case PACKET3_DISPATCH_INDIRECT: 336862306a36Sopenharmony_ci case PACKET3_MODE_CONTROL: 336962306a36Sopenharmony_ci case PACKET3_SET_PREDICATION: 337062306a36Sopenharmony_ci case PACKET3_COND_EXEC: 337162306a36Sopenharmony_ci case PACKET3_PRED_EXEC: 337262306a36Sopenharmony_ci case PACKET3_DRAW_INDIRECT: 337362306a36Sopenharmony_ci case PACKET3_DRAW_INDEX_INDIRECT: 337462306a36Sopenharmony_ci case PACKET3_INDEX_BASE: 337562306a36Sopenharmony_ci case PACKET3_DRAW_INDEX_2: 337662306a36Sopenharmony_ci case PACKET3_CONTEXT_CONTROL: 337762306a36Sopenharmony_ci case PACKET3_DRAW_INDEX_OFFSET: 337862306a36Sopenharmony_ci case PACKET3_INDEX_TYPE: 337962306a36Sopenharmony_ci case PACKET3_DRAW_INDEX: 338062306a36Sopenharmony_ci case PACKET3_DRAW_INDEX_AUTO: 338162306a36Sopenharmony_ci case PACKET3_DRAW_INDEX_IMMD: 338262306a36Sopenharmony_ci case PACKET3_NUM_INSTANCES: 338362306a36Sopenharmony_ci case PACKET3_DRAW_INDEX_MULTI_AUTO: 338462306a36Sopenharmony_ci case PACKET3_STRMOUT_BUFFER_UPDATE: 338562306a36Sopenharmony_ci case PACKET3_DRAW_INDEX_OFFSET_2: 338662306a36Sopenharmony_ci case PACKET3_DRAW_INDEX_MULTI_ELEMENT: 338762306a36Sopenharmony_ci case PACKET3_MPEG_INDEX: 338862306a36Sopenharmony_ci case PACKET3_WAIT_REG_MEM: 338962306a36Sopenharmony_ci case PACKET3_MEM_WRITE: 339062306a36Sopenharmony_ci case PACKET3_PFP_SYNC_ME: 339162306a36Sopenharmony_ci case PACKET3_SURFACE_SYNC: 339262306a36Sopenharmony_ci case PACKET3_EVENT_WRITE: 339362306a36Sopenharmony_ci case PACKET3_EVENT_WRITE_EOP: 339462306a36Sopenharmony_ci case PACKET3_EVENT_WRITE_EOS: 339562306a36Sopenharmony_ci case PACKET3_SET_CONTEXT_REG: 339662306a36Sopenharmony_ci case PACKET3_SET_BOOL_CONST: 339762306a36Sopenharmony_ci case PACKET3_SET_LOOP_CONST: 339862306a36Sopenharmony_ci case PACKET3_SET_RESOURCE: 339962306a36Sopenharmony_ci case PACKET3_SET_SAMPLER: 340062306a36Sopenharmony_ci case PACKET3_SET_CTL_CONST: 340162306a36Sopenharmony_ci case PACKET3_SET_RESOURCE_OFFSET: 340262306a36Sopenharmony_ci case PACKET3_SET_CONTEXT_REG_INDIRECT: 340362306a36Sopenharmony_ci case PACKET3_SET_RESOURCE_INDIRECT: 340462306a36Sopenharmony_ci case CAYMAN_PACKET3_DEALLOC_STATE: 340562306a36Sopenharmony_ci break; 340662306a36Sopenharmony_ci case PACKET3_COND_WRITE: 340762306a36Sopenharmony_ci if (idx_value & 0x100) { 340862306a36Sopenharmony_ci reg = ib[idx + 5] * 4; 340962306a36Sopenharmony_ci if (!evergreen_vm_reg_valid(reg)) 341062306a36Sopenharmony_ci return -EINVAL; 341162306a36Sopenharmony_ci } 341262306a36Sopenharmony_ci break; 341362306a36Sopenharmony_ci case PACKET3_COPY_DW: 341462306a36Sopenharmony_ci if (idx_value & 0x2) { 341562306a36Sopenharmony_ci reg = ib[idx + 3] * 4; 341662306a36Sopenharmony_ci if (!evergreen_vm_reg_valid(reg)) 341762306a36Sopenharmony_ci return -EINVAL; 341862306a36Sopenharmony_ci } 341962306a36Sopenharmony_ci break; 342062306a36Sopenharmony_ci case PACKET3_SET_CONFIG_REG: 342162306a36Sopenharmony_ci start_reg = (idx_value << 2) + PACKET3_SET_CONFIG_REG_START; 342262306a36Sopenharmony_ci end_reg = 4 * pkt->count + start_reg - 4; 342362306a36Sopenharmony_ci if ((start_reg < PACKET3_SET_CONFIG_REG_START) || 342462306a36Sopenharmony_ci (start_reg >= PACKET3_SET_CONFIG_REG_END) || 342562306a36Sopenharmony_ci (end_reg >= PACKET3_SET_CONFIG_REG_END)) { 342662306a36Sopenharmony_ci DRM_ERROR("bad PACKET3_SET_CONFIG_REG\n"); 342762306a36Sopenharmony_ci return -EINVAL; 342862306a36Sopenharmony_ci } 342962306a36Sopenharmony_ci for (i = 0; i < pkt->count; i++) { 343062306a36Sopenharmony_ci reg = start_reg + (4 * i); 343162306a36Sopenharmony_ci if (!evergreen_vm_reg_valid(reg)) 343262306a36Sopenharmony_ci return -EINVAL; 343362306a36Sopenharmony_ci } 343462306a36Sopenharmony_ci break; 343562306a36Sopenharmony_ci case PACKET3_CP_DMA: 343662306a36Sopenharmony_ci command = ib[idx + 4]; 343762306a36Sopenharmony_ci info = ib[idx + 1]; 343862306a36Sopenharmony_ci if ((((info & 0x60000000) >> 29) != 0) || /* src = GDS or DATA */ 343962306a36Sopenharmony_ci (((info & 0x00300000) >> 20) != 0) || /* dst = GDS */ 344062306a36Sopenharmony_ci ((((info & 0x00300000) >> 20) == 0) && 344162306a36Sopenharmony_ci (command & PACKET3_CP_DMA_CMD_DAS)) || /* dst = register */ 344262306a36Sopenharmony_ci ((((info & 0x60000000) >> 29) == 0) && 344362306a36Sopenharmony_ci (command & PACKET3_CP_DMA_CMD_SAS))) { /* src = register */ 344462306a36Sopenharmony_ci /* non mem to mem copies requires dw aligned count */ 344562306a36Sopenharmony_ci if ((command & 0x1fffff) % 4) { 344662306a36Sopenharmony_ci DRM_ERROR("CP DMA command requires dw count alignment\n"); 344762306a36Sopenharmony_ci return -EINVAL; 344862306a36Sopenharmony_ci } 344962306a36Sopenharmony_ci } 345062306a36Sopenharmony_ci if (command & PACKET3_CP_DMA_CMD_SAS) { 345162306a36Sopenharmony_ci /* src address space is register */ 345262306a36Sopenharmony_ci if (((info & 0x60000000) >> 29) == 0) { 345362306a36Sopenharmony_ci start_reg = idx_value << 2; 345462306a36Sopenharmony_ci if (command & PACKET3_CP_DMA_CMD_SAIC) { 345562306a36Sopenharmony_ci reg = start_reg; 345662306a36Sopenharmony_ci if (!evergreen_vm_reg_valid(reg)) { 345762306a36Sopenharmony_ci DRM_ERROR("CP DMA Bad SRC register\n"); 345862306a36Sopenharmony_ci return -EINVAL; 345962306a36Sopenharmony_ci } 346062306a36Sopenharmony_ci } else { 346162306a36Sopenharmony_ci for (i = 0; i < (command & 0x1fffff); i++) { 346262306a36Sopenharmony_ci reg = start_reg + (4 * i); 346362306a36Sopenharmony_ci if (!evergreen_vm_reg_valid(reg)) { 346462306a36Sopenharmony_ci DRM_ERROR("CP DMA Bad SRC register\n"); 346562306a36Sopenharmony_ci return -EINVAL; 346662306a36Sopenharmony_ci } 346762306a36Sopenharmony_ci } 346862306a36Sopenharmony_ci } 346962306a36Sopenharmony_ci } 347062306a36Sopenharmony_ci } 347162306a36Sopenharmony_ci if (command & PACKET3_CP_DMA_CMD_DAS) { 347262306a36Sopenharmony_ci /* dst address space is register */ 347362306a36Sopenharmony_ci if (((info & 0x00300000) >> 20) == 0) { 347462306a36Sopenharmony_ci start_reg = ib[idx + 2]; 347562306a36Sopenharmony_ci if (command & PACKET3_CP_DMA_CMD_DAIC) { 347662306a36Sopenharmony_ci reg = start_reg; 347762306a36Sopenharmony_ci if (!evergreen_vm_reg_valid(reg)) { 347862306a36Sopenharmony_ci DRM_ERROR("CP DMA Bad DST register\n"); 347962306a36Sopenharmony_ci return -EINVAL; 348062306a36Sopenharmony_ci } 348162306a36Sopenharmony_ci } else { 348262306a36Sopenharmony_ci for (i = 0; i < (command & 0x1fffff); i++) { 348362306a36Sopenharmony_ci reg = start_reg + (4 * i); 348462306a36Sopenharmony_ci if (!evergreen_vm_reg_valid(reg)) { 348562306a36Sopenharmony_ci DRM_ERROR("CP DMA Bad DST register\n"); 348662306a36Sopenharmony_ci return -EINVAL; 348762306a36Sopenharmony_ci } 348862306a36Sopenharmony_ci } 348962306a36Sopenharmony_ci } 349062306a36Sopenharmony_ci } 349162306a36Sopenharmony_ci } 349262306a36Sopenharmony_ci break; 349362306a36Sopenharmony_ci case PACKET3_SET_APPEND_CNT: { 349462306a36Sopenharmony_ci uint32_t areg; 349562306a36Sopenharmony_ci uint32_t allowed_reg_base; 349662306a36Sopenharmony_ci 349762306a36Sopenharmony_ci if (pkt->count != 2) { 349862306a36Sopenharmony_ci DRM_ERROR("bad SET_APPEND_CNT (invalid count)\n"); 349962306a36Sopenharmony_ci return -EINVAL; 350062306a36Sopenharmony_ci } 350162306a36Sopenharmony_ci 350262306a36Sopenharmony_ci allowed_reg_base = GDS_APPEND_COUNT_0; 350362306a36Sopenharmony_ci allowed_reg_base -= PACKET3_SET_CONTEXT_REG_START; 350462306a36Sopenharmony_ci allowed_reg_base >>= 2; 350562306a36Sopenharmony_ci 350662306a36Sopenharmony_ci areg = idx_value >> 16; 350762306a36Sopenharmony_ci if (areg < allowed_reg_base || areg > (allowed_reg_base + 11)) { 350862306a36Sopenharmony_ci DRM_ERROR("forbidden register for append cnt 0x%08x at %d\n", 350962306a36Sopenharmony_ci areg, idx); 351062306a36Sopenharmony_ci return -EINVAL; 351162306a36Sopenharmony_ci } 351262306a36Sopenharmony_ci break; 351362306a36Sopenharmony_ci } 351462306a36Sopenharmony_ci default: 351562306a36Sopenharmony_ci return -EINVAL; 351662306a36Sopenharmony_ci } 351762306a36Sopenharmony_ci return 0; 351862306a36Sopenharmony_ci} 351962306a36Sopenharmony_ci 352062306a36Sopenharmony_ciint evergreen_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib) 352162306a36Sopenharmony_ci{ 352262306a36Sopenharmony_ci int ret = 0; 352362306a36Sopenharmony_ci u32 idx = 0; 352462306a36Sopenharmony_ci struct radeon_cs_packet pkt; 352562306a36Sopenharmony_ci 352662306a36Sopenharmony_ci do { 352762306a36Sopenharmony_ci pkt.idx = idx; 352862306a36Sopenharmony_ci pkt.type = RADEON_CP_PACKET_GET_TYPE(ib->ptr[idx]); 352962306a36Sopenharmony_ci pkt.count = RADEON_CP_PACKET_GET_COUNT(ib->ptr[idx]); 353062306a36Sopenharmony_ci pkt.one_reg_wr = 0; 353162306a36Sopenharmony_ci switch (pkt.type) { 353262306a36Sopenharmony_ci case RADEON_PACKET_TYPE0: 353362306a36Sopenharmony_ci dev_err(rdev->dev, "Packet0 not allowed!\n"); 353462306a36Sopenharmony_ci ret = -EINVAL; 353562306a36Sopenharmony_ci break; 353662306a36Sopenharmony_ci case RADEON_PACKET_TYPE2: 353762306a36Sopenharmony_ci idx += 1; 353862306a36Sopenharmony_ci break; 353962306a36Sopenharmony_ci case RADEON_PACKET_TYPE3: 354062306a36Sopenharmony_ci pkt.opcode = RADEON_CP_PACKET3_GET_OPCODE(ib->ptr[idx]); 354162306a36Sopenharmony_ci ret = evergreen_vm_packet3_check(rdev, ib->ptr, &pkt); 354262306a36Sopenharmony_ci idx += pkt.count + 2; 354362306a36Sopenharmony_ci break; 354462306a36Sopenharmony_ci default: 354562306a36Sopenharmony_ci dev_err(rdev->dev, "Unknown packet type %d !\n", pkt.type); 354662306a36Sopenharmony_ci ret = -EINVAL; 354762306a36Sopenharmony_ci break; 354862306a36Sopenharmony_ci } 354962306a36Sopenharmony_ci if (ret) 355062306a36Sopenharmony_ci break; 355162306a36Sopenharmony_ci } while (idx < ib->length_dw); 355262306a36Sopenharmony_ci 355362306a36Sopenharmony_ci return ret; 355462306a36Sopenharmony_ci} 355562306a36Sopenharmony_ci 355662306a36Sopenharmony_ci/** 355762306a36Sopenharmony_ci * evergreen_dma_ib_parse() - parse the DMA IB for VM 355862306a36Sopenharmony_ci * @rdev: radeon_device pointer 355962306a36Sopenharmony_ci * @ib: radeon_ib pointer 356062306a36Sopenharmony_ci * 356162306a36Sopenharmony_ci * Parses the DMA IB from the VM CS ioctl 356262306a36Sopenharmony_ci * checks for errors. (Cayman-SI) 356362306a36Sopenharmony_ci * Returns 0 for success and an error on failure. 356462306a36Sopenharmony_ci **/ 356562306a36Sopenharmony_ciint evergreen_dma_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib) 356662306a36Sopenharmony_ci{ 356762306a36Sopenharmony_ci u32 idx = 0; 356862306a36Sopenharmony_ci u32 header, cmd, count, sub_cmd; 356962306a36Sopenharmony_ci 357062306a36Sopenharmony_ci do { 357162306a36Sopenharmony_ci header = ib->ptr[idx]; 357262306a36Sopenharmony_ci cmd = GET_DMA_CMD(header); 357362306a36Sopenharmony_ci count = GET_DMA_COUNT(header); 357462306a36Sopenharmony_ci sub_cmd = GET_DMA_SUB_CMD(header); 357562306a36Sopenharmony_ci 357662306a36Sopenharmony_ci switch (cmd) { 357762306a36Sopenharmony_ci case DMA_PACKET_WRITE: 357862306a36Sopenharmony_ci switch (sub_cmd) { 357962306a36Sopenharmony_ci /* tiled */ 358062306a36Sopenharmony_ci case 8: 358162306a36Sopenharmony_ci idx += count + 7; 358262306a36Sopenharmony_ci break; 358362306a36Sopenharmony_ci /* linear */ 358462306a36Sopenharmony_ci case 0: 358562306a36Sopenharmony_ci idx += count + 3; 358662306a36Sopenharmony_ci break; 358762306a36Sopenharmony_ci default: 358862306a36Sopenharmony_ci DRM_ERROR("bad DMA_PACKET_WRITE [%6d] 0x%08x sub cmd is not 0 or 8\n", idx, ib->ptr[idx]); 358962306a36Sopenharmony_ci return -EINVAL; 359062306a36Sopenharmony_ci } 359162306a36Sopenharmony_ci break; 359262306a36Sopenharmony_ci case DMA_PACKET_COPY: 359362306a36Sopenharmony_ci switch (sub_cmd) { 359462306a36Sopenharmony_ci /* Copy L2L, DW aligned */ 359562306a36Sopenharmony_ci case 0x00: 359662306a36Sopenharmony_ci idx += 5; 359762306a36Sopenharmony_ci break; 359862306a36Sopenharmony_ci /* Copy L2T/T2L */ 359962306a36Sopenharmony_ci case 0x08: 360062306a36Sopenharmony_ci idx += 9; 360162306a36Sopenharmony_ci break; 360262306a36Sopenharmony_ci /* Copy L2L, byte aligned */ 360362306a36Sopenharmony_ci case 0x40: 360462306a36Sopenharmony_ci idx += 5; 360562306a36Sopenharmony_ci break; 360662306a36Sopenharmony_ci /* Copy L2L, partial */ 360762306a36Sopenharmony_ci case 0x41: 360862306a36Sopenharmony_ci idx += 9; 360962306a36Sopenharmony_ci break; 361062306a36Sopenharmony_ci /* Copy L2L, DW aligned, broadcast */ 361162306a36Sopenharmony_ci case 0x44: 361262306a36Sopenharmony_ci idx += 7; 361362306a36Sopenharmony_ci break; 361462306a36Sopenharmony_ci /* Copy L2T Frame to Field */ 361562306a36Sopenharmony_ci case 0x48: 361662306a36Sopenharmony_ci idx += 10; 361762306a36Sopenharmony_ci break; 361862306a36Sopenharmony_ci /* Copy L2T/T2L, partial */ 361962306a36Sopenharmony_ci case 0x49: 362062306a36Sopenharmony_ci idx += 12; 362162306a36Sopenharmony_ci break; 362262306a36Sopenharmony_ci /* Copy L2T broadcast */ 362362306a36Sopenharmony_ci case 0x4b: 362462306a36Sopenharmony_ci idx += 10; 362562306a36Sopenharmony_ci break; 362662306a36Sopenharmony_ci /* Copy L2T/T2L (tile units) */ 362762306a36Sopenharmony_ci case 0x4c: 362862306a36Sopenharmony_ci idx += 9; 362962306a36Sopenharmony_ci break; 363062306a36Sopenharmony_ci /* Copy T2T, partial (tile units) */ 363162306a36Sopenharmony_ci case 0x4d: 363262306a36Sopenharmony_ci idx += 13; 363362306a36Sopenharmony_ci break; 363462306a36Sopenharmony_ci /* Copy L2T broadcast (tile units) */ 363562306a36Sopenharmony_ci case 0x4f: 363662306a36Sopenharmony_ci idx += 10; 363762306a36Sopenharmony_ci break; 363862306a36Sopenharmony_ci default: 363962306a36Sopenharmony_ci DRM_ERROR("bad DMA_PACKET_COPY [%6d] 0x%08x invalid sub cmd\n", idx, ib->ptr[idx]); 364062306a36Sopenharmony_ci return -EINVAL; 364162306a36Sopenharmony_ci } 364262306a36Sopenharmony_ci break; 364362306a36Sopenharmony_ci case DMA_PACKET_CONSTANT_FILL: 364462306a36Sopenharmony_ci idx += 4; 364562306a36Sopenharmony_ci break; 364662306a36Sopenharmony_ci case DMA_PACKET_NOP: 364762306a36Sopenharmony_ci idx += 1; 364862306a36Sopenharmony_ci break; 364962306a36Sopenharmony_ci default: 365062306a36Sopenharmony_ci DRM_ERROR("Unknown packet type %d at %d !\n", cmd, idx); 365162306a36Sopenharmony_ci return -EINVAL; 365262306a36Sopenharmony_ci } 365362306a36Sopenharmony_ci } while (idx < ib->length_dw); 365462306a36Sopenharmony_ci 365562306a36Sopenharmony_ci return 0; 365662306a36Sopenharmony_ci} 3657