18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright 2010 Advanced Micro Devices, Inc. 38c2ecf20Sopenharmony_ci * Copyright 2008 Red Hat Inc. 48c2ecf20Sopenharmony_ci * Copyright 2009 Jerome Glisse. 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 78c2ecf20Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 88c2ecf20Sopenharmony_ci * to deal in the Software without restriction, including without limitation 98c2ecf20Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 108c2ecf20Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 118c2ecf20Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 128c2ecf20Sopenharmony_ci * 138c2ecf20Sopenharmony_ci * The above copyright notice and this permission notice shall be included in 148c2ecf20Sopenharmony_ci * all copies or substantial portions of the Software. 158c2ecf20Sopenharmony_ci * 168c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 178c2ecf20Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 188c2ecf20Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 198c2ecf20Sopenharmony_ci * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 208c2ecf20Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 218c2ecf20Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 228c2ecf20Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE. 238c2ecf20Sopenharmony_ci * 248c2ecf20Sopenharmony_ci * Authors: Dave Airlie 258c2ecf20Sopenharmony_ci * Alex Deucher 268c2ecf20Sopenharmony_ci * Jerome Glisse 278c2ecf20Sopenharmony_ci */ 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci#include "radeon.h" 308c2ecf20Sopenharmony_ci#include "radeon_asic.h" 318c2ecf20Sopenharmony_ci#include "evergreend.h" 328c2ecf20Sopenharmony_ci#include "evergreen_reg_safe.h" 338c2ecf20Sopenharmony_ci#include "cayman_reg_safe.h" 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci#define MAX(a,b) (((a)>(b))?(a):(b)) 368c2ecf20Sopenharmony_ci#define MIN(a,b) (((a)<(b))?(a):(b)) 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci#define REG_SAFE_BM_SIZE ARRAY_SIZE(evergreen_reg_safe_bm) 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ciint r600_dma_cs_next_reloc(struct radeon_cs_parser *p, 418c2ecf20Sopenharmony_ci struct radeon_bo_list **cs_reloc); 428c2ecf20Sopenharmony_cistruct evergreen_cs_track { 438c2ecf20Sopenharmony_ci u32 group_size; 448c2ecf20Sopenharmony_ci u32 nbanks; 458c2ecf20Sopenharmony_ci u32 npipes; 468c2ecf20Sopenharmony_ci u32 row_size; 478c2ecf20Sopenharmony_ci /* value we track */ 488c2ecf20Sopenharmony_ci u32 nsamples; /* unused */ 498c2ecf20Sopenharmony_ci struct radeon_bo *cb_color_bo[12]; 508c2ecf20Sopenharmony_ci u32 cb_color_bo_offset[12]; 518c2ecf20Sopenharmony_ci struct radeon_bo *cb_color_fmask_bo[8]; /* unused */ 528c2ecf20Sopenharmony_ci struct radeon_bo *cb_color_cmask_bo[8]; /* unused */ 538c2ecf20Sopenharmony_ci u32 cb_color_info[12]; 548c2ecf20Sopenharmony_ci u32 cb_color_view[12]; 558c2ecf20Sopenharmony_ci u32 cb_color_pitch[12]; 568c2ecf20Sopenharmony_ci u32 cb_color_slice[12]; 578c2ecf20Sopenharmony_ci u32 cb_color_slice_idx[12]; 588c2ecf20Sopenharmony_ci u32 cb_color_attrib[12]; 598c2ecf20Sopenharmony_ci u32 cb_color_cmask_slice[8];/* unused */ 608c2ecf20Sopenharmony_ci u32 cb_color_fmask_slice[8];/* unused */ 618c2ecf20Sopenharmony_ci u32 cb_target_mask; 628c2ecf20Sopenharmony_ci u32 cb_shader_mask; /* unused */ 638c2ecf20Sopenharmony_ci u32 vgt_strmout_config; 648c2ecf20Sopenharmony_ci u32 vgt_strmout_buffer_config; 658c2ecf20Sopenharmony_ci struct radeon_bo *vgt_strmout_bo[4]; 668c2ecf20Sopenharmony_ci u32 vgt_strmout_bo_offset[4]; 678c2ecf20Sopenharmony_ci u32 vgt_strmout_size[4]; 688c2ecf20Sopenharmony_ci u32 db_depth_control; 698c2ecf20Sopenharmony_ci u32 db_depth_view; 708c2ecf20Sopenharmony_ci u32 db_depth_slice; 718c2ecf20Sopenharmony_ci u32 db_depth_size; 728c2ecf20Sopenharmony_ci u32 db_z_info; 738c2ecf20Sopenharmony_ci u32 db_z_read_offset; 748c2ecf20Sopenharmony_ci u32 db_z_write_offset; 758c2ecf20Sopenharmony_ci struct radeon_bo *db_z_read_bo; 768c2ecf20Sopenharmony_ci struct radeon_bo *db_z_write_bo; 778c2ecf20Sopenharmony_ci u32 db_s_info; 788c2ecf20Sopenharmony_ci u32 db_s_read_offset; 798c2ecf20Sopenharmony_ci u32 db_s_write_offset; 808c2ecf20Sopenharmony_ci struct radeon_bo *db_s_read_bo; 818c2ecf20Sopenharmony_ci struct radeon_bo *db_s_write_bo; 828c2ecf20Sopenharmony_ci bool sx_misc_kill_all_prims; 838c2ecf20Sopenharmony_ci bool cb_dirty; 848c2ecf20Sopenharmony_ci bool db_dirty; 858c2ecf20Sopenharmony_ci bool streamout_dirty; 868c2ecf20Sopenharmony_ci u32 htile_offset; 878c2ecf20Sopenharmony_ci u32 htile_surface; 888c2ecf20Sopenharmony_ci struct radeon_bo *htile_bo; 898c2ecf20Sopenharmony_ci unsigned long indirect_draw_buffer_size; 908c2ecf20Sopenharmony_ci const unsigned *reg_safe_bm; 918c2ecf20Sopenharmony_ci}; 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_cistatic u32 evergreen_cs_get_aray_mode(u32 tiling_flags) 948c2ecf20Sopenharmony_ci{ 958c2ecf20Sopenharmony_ci if (tiling_flags & RADEON_TILING_MACRO) 968c2ecf20Sopenharmony_ci return ARRAY_2D_TILED_THIN1; 978c2ecf20Sopenharmony_ci else if (tiling_flags & RADEON_TILING_MICRO) 988c2ecf20Sopenharmony_ci return ARRAY_1D_TILED_THIN1; 998c2ecf20Sopenharmony_ci else 1008c2ecf20Sopenharmony_ci return ARRAY_LINEAR_GENERAL; 1018c2ecf20Sopenharmony_ci} 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_cistatic u32 evergreen_cs_get_num_banks(u32 nbanks) 1048c2ecf20Sopenharmony_ci{ 1058c2ecf20Sopenharmony_ci switch (nbanks) { 1068c2ecf20Sopenharmony_ci case 2: 1078c2ecf20Sopenharmony_ci return ADDR_SURF_2_BANK; 1088c2ecf20Sopenharmony_ci case 4: 1098c2ecf20Sopenharmony_ci return ADDR_SURF_4_BANK; 1108c2ecf20Sopenharmony_ci case 8: 1118c2ecf20Sopenharmony_ci default: 1128c2ecf20Sopenharmony_ci return ADDR_SURF_8_BANK; 1138c2ecf20Sopenharmony_ci case 16: 1148c2ecf20Sopenharmony_ci return ADDR_SURF_16_BANK; 1158c2ecf20Sopenharmony_ci } 1168c2ecf20Sopenharmony_ci} 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_cistatic void evergreen_cs_track_init(struct evergreen_cs_track *track) 1198c2ecf20Sopenharmony_ci{ 1208c2ecf20Sopenharmony_ci int i; 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci for (i = 0; i < 8; i++) { 1238c2ecf20Sopenharmony_ci track->cb_color_fmask_bo[i] = NULL; 1248c2ecf20Sopenharmony_ci track->cb_color_cmask_bo[i] = NULL; 1258c2ecf20Sopenharmony_ci track->cb_color_cmask_slice[i] = 0; 1268c2ecf20Sopenharmony_ci track->cb_color_fmask_slice[i] = 0; 1278c2ecf20Sopenharmony_ci } 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci for (i = 0; i < 12; i++) { 1308c2ecf20Sopenharmony_ci track->cb_color_bo[i] = NULL; 1318c2ecf20Sopenharmony_ci track->cb_color_bo_offset[i] = 0xFFFFFFFF; 1328c2ecf20Sopenharmony_ci track->cb_color_info[i] = 0; 1338c2ecf20Sopenharmony_ci track->cb_color_view[i] = 0xFFFFFFFF; 1348c2ecf20Sopenharmony_ci track->cb_color_pitch[i] = 0; 1358c2ecf20Sopenharmony_ci track->cb_color_slice[i] = 0xfffffff; 1368c2ecf20Sopenharmony_ci track->cb_color_slice_idx[i] = 0; 1378c2ecf20Sopenharmony_ci } 1388c2ecf20Sopenharmony_ci track->cb_target_mask = 0xFFFFFFFF; 1398c2ecf20Sopenharmony_ci track->cb_shader_mask = 0xFFFFFFFF; 1408c2ecf20Sopenharmony_ci track->cb_dirty = true; 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci track->db_depth_slice = 0xffffffff; 1438c2ecf20Sopenharmony_ci track->db_depth_view = 0xFFFFC000; 1448c2ecf20Sopenharmony_ci track->db_depth_size = 0xFFFFFFFF; 1458c2ecf20Sopenharmony_ci track->db_depth_control = 0xFFFFFFFF; 1468c2ecf20Sopenharmony_ci track->db_z_info = 0xFFFFFFFF; 1478c2ecf20Sopenharmony_ci track->db_z_read_offset = 0xFFFFFFFF; 1488c2ecf20Sopenharmony_ci track->db_z_write_offset = 0xFFFFFFFF; 1498c2ecf20Sopenharmony_ci track->db_z_read_bo = NULL; 1508c2ecf20Sopenharmony_ci track->db_z_write_bo = NULL; 1518c2ecf20Sopenharmony_ci track->db_s_info = 0xFFFFFFFF; 1528c2ecf20Sopenharmony_ci track->db_s_read_offset = 0xFFFFFFFF; 1538c2ecf20Sopenharmony_ci track->db_s_write_offset = 0xFFFFFFFF; 1548c2ecf20Sopenharmony_ci track->db_s_read_bo = NULL; 1558c2ecf20Sopenharmony_ci track->db_s_write_bo = NULL; 1568c2ecf20Sopenharmony_ci track->db_dirty = true; 1578c2ecf20Sopenharmony_ci track->htile_bo = NULL; 1588c2ecf20Sopenharmony_ci track->htile_offset = 0xFFFFFFFF; 1598c2ecf20Sopenharmony_ci track->htile_surface = 0; 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_ci for (i = 0; i < 4; i++) { 1628c2ecf20Sopenharmony_ci track->vgt_strmout_size[i] = 0; 1638c2ecf20Sopenharmony_ci track->vgt_strmout_bo[i] = NULL; 1648c2ecf20Sopenharmony_ci track->vgt_strmout_bo_offset[i] = 0xFFFFFFFF; 1658c2ecf20Sopenharmony_ci } 1668c2ecf20Sopenharmony_ci track->streamout_dirty = true; 1678c2ecf20Sopenharmony_ci track->sx_misc_kill_all_prims = false; 1688c2ecf20Sopenharmony_ci} 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_cistruct eg_surface { 1718c2ecf20Sopenharmony_ci /* value gathered from cs */ 1728c2ecf20Sopenharmony_ci unsigned nbx; 1738c2ecf20Sopenharmony_ci unsigned nby; 1748c2ecf20Sopenharmony_ci unsigned format; 1758c2ecf20Sopenharmony_ci unsigned mode; 1768c2ecf20Sopenharmony_ci unsigned nbanks; 1778c2ecf20Sopenharmony_ci unsigned bankw; 1788c2ecf20Sopenharmony_ci unsigned bankh; 1798c2ecf20Sopenharmony_ci unsigned tsplit; 1808c2ecf20Sopenharmony_ci unsigned mtilea; 1818c2ecf20Sopenharmony_ci unsigned nsamples; 1828c2ecf20Sopenharmony_ci /* output value */ 1838c2ecf20Sopenharmony_ci unsigned bpe; 1848c2ecf20Sopenharmony_ci unsigned layer_size; 1858c2ecf20Sopenharmony_ci unsigned palign; 1868c2ecf20Sopenharmony_ci unsigned halign; 1878c2ecf20Sopenharmony_ci unsigned long base_align; 1888c2ecf20Sopenharmony_ci}; 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_cistatic int evergreen_surface_check_linear(struct radeon_cs_parser *p, 1918c2ecf20Sopenharmony_ci struct eg_surface *surf, 1928c2ecf20Sopenharmony_ci const char *prefix) 1938c2ecf20Sopenharmony_ci{ 1948c2ecf20Sopenharmony_ci surf->layer_size = surf->nbx * surf->nby * surf->bpe * surf->nsamples; 1958c2ecf20Sopenharmony_ci surf->base_align = surf->bpe; 1968c2ecf20Sopenharmony_ci surf->palign = 1; 1978c2ecf20Sopenharmony_ci surf->halign = 1; 1988c2ecf20Sopenharmony_ci return 0; 1998c2ecf20Sopenharmony_ci} 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_cistatic int evergreen_surface_check_linear_aligned(struct radeon_cs_parser *p, 2028c2ecf20Sopenharmony_ci struct eg_surface *surf, 2038c2ecf20Sopenharmony_ci const char *prefix) 2048c2ecf20Sopenharmony_ci{ 2058c2ecf20Sopenharmony_ci struct evergreen_cs_track *track = p->track; 2068c2ecf20Sopenharmony_ci unsigned palign; 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci palign = MAX(64, track->group_size / surf->bpe); 2098c2ecf20Sopenharmony_ci surf->layer_size = surf->nbx * surf->nby * surf->bpe * surf->nsamples; 2108c2ecf20Sopenharmony_ci surf->base_align = track->group_size; 2118c2ecf20Sopenharmony_ci surf->palign = palign; 2128c2ecf20Sopenharmony_ci surf->halign = 1; 2138c2ecf20Sopenharmony_ci if (surf->nbx & (palign - 1)) { 2148c2ecf20Sopenharmony_ci if (prefix) { 2158c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d %s pitch %d invalid must be aligned with %d\n", 2168c2ecf20Sopenharmony_ci __func__, __LINE__, prefix, surf->nbx, palign); 2178c2ecf20Sopenharmony_ci } 2188c2ecf20Sopenharmony_ci return -EINVAL; 2198c2ecf20Sopenharmony_ci } 2208c2ecf20Sopenharmony_ci return 0; 2218c2ecf20Sopenharmony_ci} 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_cistatic int evergreen_surface_check_1d(struct radeon_cs_parser *p, 2248c2ecf20Sopenharmony_ci struct eg_surface *surf, 2258c2ecf20Sopenharmony_ci const char *prefix) 2268c2ecf20Sopenharmony_ci{ 2278c2ecf20Sopenharmony_ci struct evergreen_cs_track *track = p->track; 2288c2ecf20Sopenharmony_ci unsigned palign; 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_ci palign = track->group_size / (8 * surf->bpe * surf->nsamples); 2318c2ecf20Sopenharmony_ci palign = MAX(8, palign); 2328c2ecf20Sopenharmony_ci surf->layer_size = surf->nbx * surf->nby * surf->bpe; 2338c2ecf20Sopenharmony_ci surf->base_align = track->group_size; 2348c2ecf20Sopenharmony_ci surf->palign = palign; 2358c2ecf20Sopenharmony_ci surf->halign = 8; 2368c2ecf20Sopenharmony_ci if ((surf->nbx & (palign - 1))) { 2378c2ecf20Sopenharmony_ci if (prefix) { 2388c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d %s pitch %d invalid must be aligned with %d (%d %d %d)\n", 2398c2ecf20Sopenharmony_ci __func__, __LINE__, prefix, surf->nbx, palign, 2408c2ecf20Sopenharmony_ci track->group_size, surf->bpe, surf->nsamples); 2418c2ecf20Sopenharmony_ci } 2428c2ecf20Sopenharmony_ci return -EINVAL; 2438c2ecf20Sopenharmony_ci } 2448c2ecf20Sopenharmony_ci if ((surf->nby & (8 - 1))) { 2458c2ecf20Sopenharmony_ci if (prefix) { 2468c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d %s height %d invalid must be aligned with 8\n", 2478c2ecf20Sopenharmony_ci __func__, __LINE__, prefix, surf->nby); 2488c2ecf20Sopenharmony_ci } 2498c2ecf20Sopenharmony_ci return -EINVAL; 2508c2ecf20Sopenharmony_ci } 2518c2ecf20Sopenharmony_ci return 0; 2528c2ecf20Sopenharmony_ci} 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_cistatic int evergreen_surface_check_2d(struct radeon_cs_parser *p, 2558c2ecf20Sopenharmony_ci struct eg_surface *surf, 2568c2ecf20Sopenharmony_ci const char *prefix) 2578c2ecf20Sopenharmony_ci{ 2588c2ecf20Sopenharmony_ci struct evergreen_cs_track *track = p->track; 2598c2ecf20Sopenharmony_ci unsigned palign, halign, tileb, slice_pt; 2608c2ecf20Sopenharmony_ci unsigned mtile_pr, mtile_ps, mtileb; 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci tileb = 64 * surf->bpe * surf->nsamples; 2638c2ecf20Sopenharmony_ci slice_pt = 1; 2648c2ecf20Sopenharmony_ci if (tileb > surf->tsplit) { 2658c2ecf20Sopenharmony_ci slice_pt = tileb / surf->tsplit; 2668c2ecf20Sopenharmony_ci } 2678c2ecf20Sopenharmony_ci tileb = tileb / slice_pt; 2688c2ecf20Sopenharmony_ci /* macro tile width & height */ 2698c2ecf20Sopenharmony_ci palign = (8 * surf->bankw * track->npipes) * surf->mtilea; 2708c2ecf20Sopenharmony_ci halign = (8 * surf->bankh * surf->nbanks) / surf->mtilea; 2718c2ecf20Sopenharmony_ci mtileb = (palign / 8) * (halign / 8) * tileb; 2728c2ecf20Sopenharmony_ci mtile_pr = surf->nbx / palign; 2738c2ecf20Sopenharmony_ci mtile_ps = (mtile_pr * surf->nby) / halign; 2748c2ecf20Sopenharmony_ci surf->layer_size = mtile_ps * mtileb * slice_pt; 2758c2ecf20Sopenharmony_ci surf->base_align = (palign / 8) * (halign / 8) * tileb; 2768c2ecf20Sopenharmony_ci surf->palign = palign; 2778c2ecf20Sopenharmony_ci surf->halign = halign; 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci if ((surf->nbx & (palign - 1))) { 2808c2ecf20Sopenharmony_ci if (prefix) { 2818c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d %s pitch %d invalid must be aligned with %d\n", 2828c2ecf20Sopenharmony_ci __func__, __LINE__, prefix, surf->nbx, palign); 2838c2ecf20Sopenharmony_ci } 2848c2ecf20Sopenharmony_ci return -EINVAL; 2858c2ecf20Sopenharmony_ci } 2868c2ecf20Sopenharmony_ci if ((surf->nby & (halign - 1))) { 2878c2ecf20Sopenharmony_ci if (prefix) { 2888c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d %s height %d invalid must be aligned with %d\n", 2898c2ecf20Sopenharmony_ci __func__, __LINE__, prefix, surf->nby, halign); 2908c2ecf20Sopenharmony_ci } 2918c2ecf20Sopenharmony_ci return -EINVAL; 2928c2ecf20Sopenharmony_ci } 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci return 0; 2958c2ecf20Sopenharmony_ci} 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_cistatic int evergreen_surface_check(struct radeon_cs_parser *p, 2988c2ecf20Sopenharmony_ci struct eg_surface *surf, 2998c2ecf20Sopenharmony_ci const char *prefix) 3008c2ecf20Sopenharmony_ci{ 3018c2ecf20Sopenharmony_ci /* some common value computed here */ 3028c2ecf20Sopenharmony_ci surf->bpe = r600_fmt_get_blocksize(surf->format); 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci switch (surf->mode) { 3058c2ecf20Sopenharmony_ci case ARRAY_LINEAR_GENERAL: 3068c2ecf20Sopenharmony_ci return evergreen_surface_check_linear(p, surf, prefix); 3078c2ecf20Sopenharmony_ci case ARRAY_LINEAR_ALIGNED: 3088c2ecf20Sopenharmony_ci return evergreen_surface_check_linear_aligned(p, surf, prefix); 3098c2ecf20Sopenharmony_ci case ARRAY_1D_TILED_THIN1: 3108c2ecf20Sopenharmony_ci return evergreen_surface_check_1d(p, surf, prefix); 3118c2ecf20Sopenharmony_ci case ARRAY_2D_TILED_THIN1: 3128c2ecf20Sopenharmony_ci return evergreen_surface_check_2d(p, surf, prefix); 3138c2ecf20Sopenharmony_ci default: 3148c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d %s invalid array mode %d\n", 3158c2ecf20Sopenharmony_ci __func__, __LINE__, prefix, surf->mode); 3168c2ecf20Sopenharmony_ci return -EINVAL; 3178c2ecf20Sopenharmony_ci } 3188c2ecf20Sopenharmony_ci return -EINVAL; 3198c2ecf20Sopenharmony_ci} 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_cistatic int evergreen_surface_value_conv_check(struct radeon_cs_parser *p, 3228c2ecf20Sopenharmony_ci struct eg_surface *surf, 3238c2ecf20Sopenharmony_ci const char *prefix) 3248c2ecf20Sopenharmony_ci{ 3258c2ecf20Sopenharmony_ci switch (surf->mode) { 3268c2ecf20Sopenharmony_ci case ARRAY_2D_TILED_THIN1: 3278c2ecf20Sopenharmony_ci break; 3288c2ecf20Sopenharmony_ci case ARRAY_LINEAR_GENERAL: 3298c2ecf20Sopenharmony_ci case ARRAY_LINEAR_ALIGNED: 3308c2ecf20Sopenharmony_ci case ARRAY_1D_TILED_THIN1: 3318c2ecf20Sopenharmony_ci return 0; 3328c2ecf20Sopenharmony_ci default: 3338c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d %s invalid array mode %d\n", 3348c2ecf20Sopenharmony_ci __func__, __LINE__, prefix, surf->mode); 3358c2ecf20Sopenharmony_ci return -EINVAL; 3368c2ecf20Sopenharmony_ci } 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci switch (surf->nbanks) { 3398c2ecf20Sopenharmony_ci case 0: surf->nbanks = 2; break; 3408c2ecf20Sopenharmony_ci case 1: surf->nbanks = 4; break; 3418c2ecf20Sopenharmony_ci case 2: surf->nbanks = 8; break; 3428c2ecf20Sopenharmony_ci case 3: surf->nbanks = 16; break; 3438c2ecf20Sopenharmony_ci default: 3448c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d %s invalid number of banks %d\n", 3458c2ecf20Sopenharmony_ci __func__, __LINE__, prefix, surf->nbanks); 3468c2ecf20Sopenharmony_ci return -EINVAL; 3478c2ecf20Sopenharmony_ci } 3488c2ecf20Sopenharmony_ci switch (surf->bankw) { 3498c2ecf20Sopenharmony_ci case 0: surf->bankw = 1; break; 3508c2ecf20Sopenharmony_ci case 1: surf->bankw = 2; break; 3518c2ecf20Sopenharmony_ci case 2: surf->bankw = 4; break; 3528c2ecf20Sopenharmony_ci case 3: surf->bankw = 8; break; 3538c2ecf20Sopenharmony_ci default: 3548c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d %s invalid bankw %d\n", 3558c2ecf20Sopenharmony_ci __func__, __LINE__, prefix, surf->bankw); 3568c2ecf20Sopenharmony_ci return -EINVAL; 3578c2ecf20Sopenharmony_ci } 3588c2ecf20Sopenharmony_ci switch (surf->bankh) { 3598c2ecf20Sopenharmony_ci case 0: surf->bankh = 1; break; 3608c2ecf20Sopenharmony_ci case 1: surf->bankh = 2; break; 3618c2ecf20Sopenharmony_ci case 2: surf->bankh = 4; break; 3628c2ecf20Sopenharmony_ci case 3: surf->bankh = 8; break; 3638c2ecf20Sopenharmony_ci default: 3648c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d %s invalid bankh %d\n", 3658c2ecf20Sopenharmony_ci __func__, __LINE__, prefix, surf->bankh); 3668c2ecf20Sopenharmony_ci return -EINVAL; 3678c2ecf20Sopenharmony_ci } 3688c2ecf20Sopenharmony_ci switch (surf->mtilea) { 3698c2ecf20Sopenharmony_ci case 0: surf->mtilea = 1; break; 3708c2ecf20Sopenharmony_ci case 1: surf->mtilea = 2; break; 3718c2ecf20Sopenharmony_ci case 2: surf->mtilea = 4; break; 3728c2ecf20Sopenharmony_ci case 3: surf->mtilea = 8; break; 3738c2ecf20Sopenharmony_ci default: 3748c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d %s invalid macro tile aspect %d\n", 3758c2ecf20Sopenharmony_ci __func__, __LINE__, prefix, surf->mtilea); 3768c2ecf20Sopenharmony_ci return -EINVAL; 3778c2ecf20Sopenharmony_ci } 3788c2ecf20Sopenharmony_ci switch (surf->tsplit) { 3798c2ecf20Sopenharmony_ci case 0: surf->tsplit = 64; break; 3808c2ecf20Sopenharmony_ci case 1: surf->tsplit = 128; break; 3818c2ecf20Sopenharmony_ci case 2: surf->tsplit = 256; break; 3828c2ecf20Sopenharmony_ci case 3: surf->tsplit = 512; break; 3838c2ecf20Sopenharmony_ci case 4: surf->tsplit = 1024; break; 3848c2ecf20Sopenharmony_ci case 5: surf->tsplit = 2048; break; 3858c2ecf20Sopenharmony_ci case 6: surf->tsplit = 4096; break; 3868c2ecf20Sopenharmony_ci default: 3878c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d %s invalid tile split %d\n", 3888c2ecf20Sopenharmony_ci __func__, __LINE__, prefix, surf->tsplit); 3898c2ecf20Sopenharmony_ci return -EINVAL; 3908c2ecf20Sopenharmony_ci } 3918c2ecf20Sopenharmony_ci return 0; 3928c2ecf20Sopenharmony_ci} 3938c2ecf20Sopenharmony_ci 3948c2ecf20Sopenharmony_cistatic int evergreen_cs_track_validate_cb(struct radeon_cs_parser *p, unsigned id) 3958c2ecf20Sopenharmony_ci{ 3968c2ecf20Sopenharmony_ci struct evergreen_cs_track *track = p->track; 3978c2ecf20Sopenharmony_ci struct eg_surface surf; 3988c2ecf20Sopenharmony_ci unsigned pitch, slice, mslice; 3998c2ecf20Sopenharmony_ci unsigned long offset; 4008c2ecf20Sopenharmony_ci int r; 4018c2ecf20Sopenharmony_ci 4028c2ecf20Sopenharmony_ci mslice = G_028C6C_SLICE_MAX(track->cb_color_view[id]) + 1; 4038c2ecf20Sopenharmony_ci pitch = track->cb_color_pitch[id]; 4048c2ecf20Sopenharmony_ci slice = track->cb_color_slice[id]; 4058c2ecf20Sopenharmony_ci surf.nbx = (pitch + 1) * 8; 4068c2ecf20Sopenharmony_ci surf.nby = ((slice + 1) * 64) / surf.nbx; 4078c2ecf20Sopenharmony_ci surf.mode = G_028C70_ARRAY_MODE(track->cb_color_info[id]); 4088c2ecf20Sopenharmony_ci surf.format = G_028C70_FORMAT(track->cb_color_info[id]); 4098c2ecf20Sopenharmony_ci surf.tsplit = G_028C74_TILE_SPLIT(track->cb_color_attrib[id]); 4108c2ecf20Sopenharmony_ci surf.nbanks = G_028C74_NUM_BANKS(track->cb_color_attrib[id]); 4118c2ecf20Sopenharmony_ci surf.bankw = G_028C74_BANK_WIDTH(track->cb_color_attrib[id]); 4128c2ecf20Sopenharmony_ci surf.bankh = G_028C74_BANK_HEIGHT(track->cb_color_attrib[id]); 4138c2ecf20Sopenharmony_ci surf.mtilea = G_028C74_MACRO_TILE_ASPECT(track->cb_color_attrib[id]); 4148c2ecf20Sopenharmony_ci surf.nsamples = 1; 4158c2ecf20Sopenharmony_ci 4168c2ecf20Sopenharmony_ci if (!r600_fmt_is_valid_color(surf.format)) { 4178c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d cb invalid format %d for %d (0x%08x)\n", 4188c2ecf20Sopenharmony_ci __func__, __LINE__, surf.format, 4198c2ecf20Sopenharmony_ci id, track->cb_color_info[id]); 4208c2ecf20Sopenharmony_ci return -EINVAL; 4218c2ecf20Sopenharmony_ci } 4228c2ecf20Sopenharmony_ci 4238c2ecf20Sopenharmony_ci r = evergreen_surface_value_conv_check(p, &surf, "cb"); 4248c2ecf20Sopenharmony_ci if (r) { 4258c2ecf20Sopenharmony_ci return r; 4268c2ecf20Sopenharmony_ci } 4278c2ecf20Sopenharmony_ci 4288c2ecf20Sopenharmony_ci r = evergreen_surface_check(p, &surf, "cb"); 4298c2ecf20Sopenharmony_ci if (r) { 4308c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d cb[%d] invalid (0x%08x 0x%08x 0x%08x 0x%08x)\n", 4318c2ecf20Sopenharmony_ci __func__, __LINE__, id, track->cb_color_pitch[id], 4328c2ecf20Sopenharmony_ci track->cb_color_slice[id], track->cb_color_attrib[id], 4338c2ecf20Sopenharmony_ci track->cb_color_info[id]); 4348c2ecf20Sopenharmony_ci return r; 4358c2ecf20Sopenharmony_ci } 4368c2ecf20Sopenharmony_ci 4378c2ecf20Sopenharmony_ci offset = track->cb_color_bo_offset[id] << 8; 4388c2ecf20Sopenharmony_ci if (offset & (surf.base_align - 1)) { 4398c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d cb[%d] bo base %ld not aligned with %ld\n", 4408c2ecf20Sopenharmony_ci __func__, __LINE__, id, offset, surf.base_align); 4418c2ecf20Sopenharmony_ci return -EINVAL; 4428c2ecf20Sopenharmony_ci } 4438c2ecf20Sopenharmony_ci 4448c2ecf20Sopenharmony_ci offset += surf.layer_size * mslice; 4458c2ecf20Sopenharmony_ci if (offset > radeon_bo_size(track->cb_color_bo[id])) { 4468c2ecf20Sopenharmony_ci /* old ddx are broken they allocate bo with w*h*bpp but 4478c2ecf20Sopenharmony_ci * program slice with ALIGN(h, 8), catch this and patch 4488c2ecf20Sopenharmony_ci * command stream. 4498c2ecf20Sopenharmony_ci */ 4508c2ecf20Sopenharmony_ci if (!surf.mode) { 4518c2ecf20Sopenharmony_ci uint32_t *ib = p->ib.ptr; 4528c2ecf20Sopenharmony_ci unsigned long tmp, nby, bsize, size, min = 0; 4538c2ecf20Sopenharmony_ci 4548c2ecf20Sopenharmony_ci /* find the height the ddx wants */ 4558c2ecf20Sopenharmony_ci if (surf.nby > 8) { 4568c2ecf20Sopenharmony_ci min = surf.nby - 8; 4578c2ecf20Sopenharmony_ci } 4588c2ecf20Sopenharmony_ci bsize = radeon_bo_size(track->cb_color_bo[id]); 4598c2ecf20Sopenharmony_ci tmp = track->cb_color_bo_offset[id] << 8; 4608c2ecf20Sopenharmony_ci for (nby = surf.nby; nby > min; nby--) { 4618c2ecf20Sopenharmony_ci size = nby * surf.nbx * surf.bpe * surf.nsamples; 4628c2ecf20Sopenharmony_ci if ((tmp + size * mslice) <= bsize) { 4638c2ecf20Sopenharmony_ci break; 4648c2ecf20Sopenharmony_ci } 4658c2ecf20Sopenharmony_ci } 4668c2ecf20Sopenharmony_ci if (nby > min) { 4678c2ecf20Sopenharmony_ci surf.nby = nby; 4688c2ecf20Sopenharmony_ci slice = ((nby * surf.nbx) / 64) - 1; 4698c2ecf20Sopenharmony_ci if (!evergreen_surface_check(p, &surf, "cb")) { 4708c2ecf20Sopenharmony_ci /* check if this one works */ 4718c2ecf20Sopenharmony_ci tmp += surf.layer_size * mslice; 4728c2ecf20Sopenharmony_ci if (tmp <= bsize) { 4738c2ecf20Sopenharmony_ci ib[track->cb_color_slice_idx[id]] = slice; 4748c2ecf20Sopenharmony_ci goto old_ddx_ok; 4758c2ecf20Sopenharmony_ci } 4768c2ecf20Sopenharmony_ci } 4778c2ecf20Sopenharmony_ci } 4788c2ecf20Sopenharmony_ci } 4798c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d cb[%d] bo too small (layer size %d, " 4808c2ecf20Sopenharmony_ci "offset %d, max layer %d, bo size %ld, slice %d)\n", 4818c2ecf20Sopenharmony_ci __func__, __LINE__, id, surf.layer_size, 4828c2ecf20Sopenharmony_ci track->cb_color_bo_offset[id] << 8, mslice, 4838c2ecf20Sopenharmony_ci radeon_bo_size(track->cb_color_bo[id]), slice); 4848c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d problematic surf: (%d %d) (%d %d %d %d %d %d %d)\n", 4858c2ecf20Sopenharmony_ci __func__, __LINE__, surf.nbx, surf.nby, 4868c2ecf20Sopenharmony_ci surf.mode, surf.bpe, surf.nsamples, 4878c2ecf20Sopenharmony_ci surf.bankw, surf.bankh, 4888c2ecf20Sopenharmony_ci surf.tsplit, surf.mtilea); 4898c2ecf20Sopenharmony_ci return -EINVAL; 4908c2ecf20Sopenharmony_ci } 4918c2ecf20Sopenharmony_ciold_ddx_ok: 4928c2ecf20Sopenharmony_ci 4938c2ecf20Sopenharmony_ci return 0; 4948c2ecf20Sopenharmony_ci} 4958c2ecf20Sopenharmony_ci 4968c2ecf20Sopenharmony_cistatic int evergreen_cs_track_validate_htile(struct radeon_cs_parser *p, 4978c2ecf20Sopenharmony_ci unsigned nbx, unsigned nby) 4988c2ecf20Sopenharmony_ci{ 4998c2ecf20Sopenharmony_ci struct evergreen_cs_track *track = p->track; 5008c2ecf20Sopenharmony_ci unsigned long size; 5018c2ecf20Sopenharmony_ci 5028c2ecf20Sopenharmony_ci if (track->htile_bo == NULL) { 5038c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d htile enabled without htile surface 0x%08x\n", 5048c2ecf20Sopenharmony_ci __func__, __LINE__, track->db_z_info); 5058c2ecf20Sopenharmony_ci return -EINVAL; 5068c2ecf20Sopenharmony_ci } 5078c2ecf20Sopenharmony_ci 5088c2ecf20Sopenharmony_ci if (G_028ABC_LINEAR(track->htile_surface)) { 5098c2ecf20Sopenharmony_ci /* pitch must be 16 htiles aligned == 16 * 8 pixel aligned */ 5108c2ecf20Sopenharmony_ci nbx = round_up(nbx, 16 * 8); 5118c2ecf20Sopenharmony_ci /* height is npipes htiles aligned == npipes * 8 pixel aligned */ 5128c2ecf20Sopenharmony_ci nby = round_up(nby, track->npipes * 8); 5138c2ecf20Sopenharmony_ci } else { 5148c2ecf20Sopenharmony_ci /* always assume 8x8 htile */ 5158c2ecf20Sopenharmony_ci /* align is htile align * 8, htile align vary according to 5168c2ecf20Sopenharmony_ci * number of pipe and tile width and nby 5178c2ecf20Sopenharmony_ci */ 5188c2ecf20Sopenharmony_ci switch (track->npipes) { 5198c2ecf20Sopenharmony_ci case 8: 5208c2ecf20Sopenharmony_ci /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/ 5218c2ecf20Sopenharmony_ci nbx = round_up(nbx, 64 * 8); 5228c2ecf20Sopenharmony_ci nby = round_up(nby, 64 * 8); 5238c2ecf20Sopenharmony_ci break; 5248c2ecf20Sopenharmony_ci case 4: 5258c2ecf20Sopenharmony_ci /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/ 5268c2ecf20Sopenharmony_ci nbx = round_up(nbx, 64 * 8); 5278c2ecf20Sopenharmony_ci nby = round_up(nby, 32 * 8); 5288c2ecf20Sopenharmony_ci break; 5298c2ecf20Sopenharmony_ci case 2: 5308c2ecf20Sopenharmony_ci /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/ 5318c2ecf20Sopenharmony_ci nbx = round_up(nbx, 32 * 8); 5328c2ecf20Sopenharmony_ci nby = round_up(nby, 32 * 8); 5338c2ecf20Sopenharmony_ci break; 5348c2ecf20Sopenharmony_ci case 1: 5358c2ecf20Sopenharmony_ci /* HTILE_WIDTH = 8 & HTILE_HEIGHT = 8*/ 5368c2ecf20Sopenharmony_ci nbx = round_up(nbx, 32 * 8); 5378c2ecf20Sopenharmony_ci nby = round_up(nby, 16 * 8); 5388c2ecf20Sopenharmony_ci break; 5398c2ecf20Sopenharmony_ci default: 5408c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d invalid num pipes %d\n", 5418c2ecf20Sopenharmony_ci __func__, __LINE__, track->npipes); 5428c2ecf20Sopenharmony_ci return -EINVAL; 5438c2ecf20Sopenharmony_ci } 5448c2ecf20Sopenharmony_ci } 5458c2ecf20Sopenharmony_ci /* compute number of htile */ 5468c2ecf20Sopenharmony_ci nbx = nbx >> 3; 5478c2ecf20Sopenharmony_ci nby = nby >> 3; 5488c2ecf20Sopenharmony_ci /* size must be aligned on npipes * 2K boundary */ 5498c2ecf20Sopenharmony_ci size = roundup(nbx * nby * 4, track->npipes * (2 << 10)); 5508c2ecf20Sopenharmony_ci size += track->htile_offset; 5518c2ecf20Sopenharmony_ci 5528c2ecf20Sopenharmony_ci if (size > radeon_bo_size(track->htile_bo)) { 5538c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d htile surface too small %ld for %ld (%d %d)\n", 5548c2ecf20Sopenharmony_ci __func__, __LINE__, radeon_bo_size(track->htile_bo), 5558c2ecf20Sopenharmony_ci size, nbx, nby); 5568c2ecf20Sopenharmony_ci return -EINVAL; 5578c2ecf20Sopenharmony_ci } 5588c2ecf20Sopenharmony_ci return 0; 5598c2ecf20Sopenharmony_ci} 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_cistatic int evergreen_cs_track_validate_stencil(struct radeon_cs_parser *p) 5628c2ecf20Sopenharmony_ci{ 5638c2ecf20Sopenharmony_ci struct evergreen_cs_track *track = p->track; 5648c2ecf20Sopenharmony_ci struct eg_surface surf; 5658c2ecf20Sopenharmony_ci unsigned pitch, slice, mslice; 5668c2ecf20Sopenharmony_ci unsigned long offset; 5678c2ecf20Sopenharmony_ci int r; 5688c2ecf20Sopenharmony_ci 5698c2ecf20Sopenharmony_ci mslice = G_028008_SLICE_MAX(track->db_depth_view) + 1; 5708c2ecf20Sopenharmony_ci pitch = G_028058_PITCH_TILE_MAX(track->db_depth_size); 5718c2ecf20Sopenharmony_ci slice = track->db_depth_slice; 5728c2ecf20Sopenharmony_ci surf.nbx = (pitch + 1) * 8; 5738c2ecf20Sopenharmony_ci surf.nby = ((slice + 1) * 64) / surf.nbx; 5748c2ecf20Sopenharmony_ci surf.mode = G_028040_ARRAY_MODE(track->db_z_info); 5758c2ecf20Sopenharmony_ci surf.format = G_028044_FORMAT(track->db_s_info); 5768c2ecf20Sopenharmony_ci surf.tsplit = G_028044_TILE_SPLIT(track->db_s_info); 5778c2ecf20Sopenharmony_ci surf.nbanks = G_028040_NUM_BANKS(track->db_z_info); 5788c2ecf20Sopenharmony_ci surf.bankw = G_028040_BANK_WIDTH(track->db_z_info); 5798c2ecf20Sopenharmony_ci surf.bankh = G_028040_BANK_HEIGHT(track->db_z_info); 5808c2ecf20Sopenharmony_ci surf.mtilea = G_028040_MACRO_TILE_ASPECT(track->db_z_info); 5818c2ecf20Sopenharmony_ci surf.nsamples = 1; 5828c2ecf20Sopenharmony_ci 5838c2ecf20Sopenharmony_ci if (surf.format != 1) { 5848c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d stencil invalid format %d\n", 5858c2ecf20Sopenharmony_ci __func__, __LINE__, surf.format); 5868c2ecf20Sopenharmony_ci return -EINVAL; 5878c2ecf20Sopenharmony_ci } 5888c2ecf20Sopenharmony_ci /* replace by color format so we can use same code */ 5898c2ecf20Sopenharmony_ci surf.format = V_028C70_COLOR_8; 5908c2ecf20Sopenharmony_ci 5918c2ecf20Sopenharmony_ci r = evergreen_surface_value_conv_check(p, &surf, "stencil"); 5928c2ecf20Sopenharmony_ci if (r) { 5938c2ecf20Sopenharmony_ci return r; 5948c2ecf20Sopenharmony_ci } 5958c2ecf20Sopenharmony_ci 5968c2ecf20Sopenharmony_ci r = evergreen_surface_check(p, &surf, NULL); 5978c2ecf20Sopenharmony_ci if (r) { 5988c2ecf20Sopenharmony_ci /* old userspace doesn't compute proper depth/stencil alignment 5998c2ecf20Sopenharmony_ci * check that alignment against a bigger byte per elements and 6008c2ecf20Sopenharmony_ci * only report if that alignment is wrong too. 6018c2ecf20Sopenharmony_ci */ 6028c2ecf20Sopenharmony_ci surf.format = V_028C70_COLOR_8_8_8_8; 6038c2ecf20Sopenharmony_ci r = evergreen_surface_check(p, &surf, "stencil"); 6048c2ecf20Sopenharmony_ci if (r) { 6058c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d stencil invalid (0x%08x 0x%08x 0x%08x 0x%08x)\n", 6068c2ecf20Sopenharmony_ci __func__, __LINE__, track->db_depth_size, 6078c2ecf20Sopenharmony_ci track->db_depth_slice, track->db_s_info, track->db_z_info); 6088c2ecf20Sopenharmony_ci } 6098c2ecf20Sopenharmony_ci return r; 6108c2ecf20Sopenharmony_ci } 6118c2ecf20Sopenharmony_ci 6128c2ecf20Sopenharmony_ci offset = track->db_s_read_offset << 8; 6138c2ecf20Sopenharmony_ci if (offset & (surf.base_align - 1)) { 6148c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d stencil read bo base %ld not aligned with %ld\n", 6158c2ecf20Sopenharmony_ci __func__, __LINE__, offset, surf.base_align); 6168c2ecf20Sopenharmony_ci return -EINVAL; 6178c2ecf20Sopenharmony_ci } 6188c2ecf20Sopenharmony_ci offset += surf.layer_size * mslice; 6198c2ecf20Sopenharmony_ci if (offset > radeon_bo_size(track->db_s_read_bo)) { 6208c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d stencil read bo too small (layer size %d, " 6218c2ecf20Sopenharmony_ci "offset %ld, max layer %d, bo size %ld)\n", 6228c2ecf20Sopenharmony_ci __func__, __LINE__, surf.layer_size, 6238c2ecf20Sopenharmony_ci (unsigned long)track->db_s_read_offset << 8, mslice, 6248c2ecf20Sopenharmony_ci radeon_bo_size(track->db_s_read_bo)); 6258c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d stencil invalid (0x%08x 0x%08x 0x%08x 0x%08x)\n", 6268c2ecf20Sopenharmony_ci __func__, __LINE__, track->db_depth_size, 6278c2ecf20Sopenharmony_ci track->db_depth_slice, track->db_s_info, track->db_z_info); 6288c2ecf20Sopenharmony_ci return -EINVAL; 6298c2ecf20Sopenharmony_ci } 6308c2ecf20Sopenharmony_ci 6318c2ecf20Sopenharmony_ci offset = track->db_s_write_offset << 8; 6328c2ecf20Sopenharmony_ci if (offset & (surf.base_align - 1)) { 6338c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d stencil write bo base %ld not aligned with %ld\n", 6348c2ecf20Sopenharmony_ci __func__, __LINE__, offset, surf.base_align); 6358c2ecf20Sopenharmony_ci return -EINVAL; 6368c2ecf20Sopenharmony_ci } 6378c2ecf20Sopenharmony_ci offset += surf.layer_size * mslice; 6388c2ecf20Sopenharmony_ci if (offset > radeon_bo_size(track->db_s_write_bo)) { 6398c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d stencil write bo too small (layer size %d, " 6408c2ecf20Sopenharmony_ci "offset %ld, max layer %d, bo size %ld)\n", 6418c2ecf20Sopenharmony_ci __func__, __LINE__, surf.layer_size, 6428c2ecf20Sopenharmony_ci (unsigned long)track->db_s_write_offset << 8, mslice, 6438c2ecf20Sopenharmony_ci radeon_bo_size(track->db_s_write_bo)); 6448c2ecf20Sopenharmony_ci return -EINVAL; 6458c2ecf20Sopenharmony_ci } 6468c2ecf20Sopenharmony_ci 6478c2ecf20Sopenharmony_ci /* hyperz */ 6488c2ecf20Sopenharmony_ci if (G_028040_TILE_SURFACE_ENABLE(track->db_z_info)) { 6498c2ecf20Sopenharmony_ci r = evergreen_cs_track_validate_htile(p, surf.nbx, surf.nby); 6508c2ecf20Sopenharmony_ci if (r) { 6518c2ecf20Sopenharmony_ci return r; 6528c2ecf20Sopenharmony_ci } 6538c2ecf20Sopenharmony_ci } 6548c2ecf20Sopenharmony_ci 6558c2ecf20Sopenharmony_ci return 0; 6568c2ecf20Sopenharmony_ci} 6578c2ecf20Sopenharmony_ci 6588c2ecf20Sopenharmony_cistatic int evergreen_cs_track_validate_depth(struct radeon_cs_parser *p) 6598c2ecf20Sopenharmony_ci{ 6608c2ecf20Sopenharmony_ci struct evergreen_cs_track *track = p->track; 6618c2ecf20Sopenharmony_ci struct eg_surface surf; 6628c2ecf20Sopenharmony_ci unsigned pitch, slice, mslice; 6638c2ecf20Sopenharmony_ci unsigned long offset; 6648c2ecf20Sopenharmony_ci int r; 6658c2ecf20Sopenharmony_ci 6668c2ecf20Sopenharmony_ci mslice = G_028008_SLICE_MAX(track->db_depth_view) + 1; 6678c2ecf20Sopenharmony_ci pitch = G_028058_PITCH_TILE_MAX(track->db_depth_size); 6688c2ecf20Sopenharmony_ci slice = track->db_depth_slice; 6698c2ecf20Sopenharmony_ci surf.nbx = (pitch + 1) * 8; 6708c2ecf20Sopenharmony_ci surf.nby = ((slice + 1) * 64) / surf.nbx; 6718c2ecf20Sopenharmony_ci surf.mode = G_028040_ARRAY_MODE(track->db_z_info); 6728c2ecf20Sopenharmony_ci surf.format = G_028040_FORMAT(track->db_z_info); 6738c2ecf20Sopenharmony_ci surf.tsplit = G_028040_TILE_SPLIT(track->db_z_info); 6748c2ecf20Sopenharmony_ci surf.nbanks = G_028040_NUM_BANKS(track->db_z_info); 6758c2ecf20Sopenharmony_ci surf.bankw = G_028040_BANK_WIDTH(track->db_z_info); 6768c2ecf20Sopenharmony_ci surf.bankh = G_028040_BANK_HEIGHT(track->db_z_info); 6778c2ecf20Sopenharmony_ci surf.mtilea = G_028040_MACRO_TILE_ASPECT(track->db_z_info); 6788c2ecf20Sopenharmony_ci surf.nsamples = 1; 6798c2ecf20Sopenharmony_ci 6808c2ecf20Sopenharmony_ci switch (surf.format) { 6818c2ecf20Sopenharmony_ci case V_028040_Z_16: 6828c2ecf20Sopenharmony_ci surf.format = V_028C70_COLOR_16; 6838c2ecf20Sopenharmony_ci break; 6848c2ecf20Sopenharmony_ci case V_028040_Z_24: 6858c2ecf20Sopenharmony_ci case V_028040_Z_32_FLOAT: 6868c2ecf20Sopenharmony_ci surf.format = V_028C70_COLOR_8_8_8_8; 6878c2ecf20Sopenharmony_ci break; 6888c2ecf20Sopenharmony_ci default: 6898c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d depth invalid format %d\n", 6908c2ecf20Sopenharmony_ci __func__, __LINE__, surf.format); 6918c2ecf20Sopenharmony_ci return -EINVAL; 6928c2ecf20Sopenharmony_ci } 6938c2ecf20Sopenharmony_ci 6948c2ecf20Sopenharmony_ci r = evergreen_surface_value_conv_check(p, &surf, "depth"); 6958c2ecf20Sopenharmony_ci if (r) { 6968c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d depth invalid (0x%08x 0x%08x 0x%08x)\n", 6978c2ecf20Sopenharmony_ci __func__, __LINE__, track->db_depth_size, 6988c2ecf20Sopenharmony_ci track->db_depth_slice, track->db_z_info); 6998c2ecf20Sopenharmony_ci return r; 7008c2ecf20Sopenharmony_ci } 7018c2ecf20Sopenharmony_ci 7028c2ecf20Sopenharmony_ci r = evergreen_surface_check(p, &surf, "depth"); 7038c2ecf20Sopenharmony_ci if (r) { 7048c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d depth invalid (0x%08x 0x%08x 0x%08x)\n", 7058c2ecf20Sopenharmony_ci __func__, __LINE__, track->db_depth_size, 7068c2ecf20Sopenharmony_ci track->db_depth_slice, track->db_z_info); 7078c2ecf20Sopenharmony_ci return r; 7088c2ecf20Sopenharmony_ci } 7098c2ecf20Sopenharmony_ci 7108c2ecf20Sopenharmony_ci offset = track->db_z_read_offset << 8; 7118c2ecf20Sopenharmony_ci if (offset & (surf.base_align - 1)) { 7128c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d stencil read bo base %ld not aligned with %ld\n", 7138c2ecf20Sopenharmony_ci __func__, __LINE__, offset, surf.base_align); 7148c2ecf20Sopenharmony_ci return -EINVAL; 7158c2ecf20Sopenharmony_ci } 7168c2ecf20Sopenharmony_ci offset += surf.layer_size * mslice; 7178c2ecf20Sopenharmony_ci if (offset > radeon_bo_size(track->db_z_read_bo)) { 7188c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d depth read bo too small (layer size %d, " 7198c2ecf20Sopenharmony_ci "offset %ld, max layer %d, bo size %ld)\n", 7208c2ecf20Sopenharmony_ci __func__, __LINE__, surf.layer_size, 7218c2ecf20Sopenharmony_ci (unsigned long)track->db_z_read_offset << 8, mslice, 7228c2ecf20Sopenharmony_ci radeon_bo_size(track->db_z_read_bo)); 7238c2ecf20Sopenharmony_ci return -EINVAL; 7248c2ecf20Sopenharmony_ci } 7258c2ecf20Sopenharmony_ci 7268c2ecf20Sopenharmony_ci offset = track->db_z_write_offset << 8; 7278c2ecf20Sopenharmony_ci if (offset & (surf.base_align - 1)) { 7288c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d stencil write bo base %ld not aligned with %ld\n", 7298c2ecf20Sopenharmony_ci __func__, __LINE__, offset, surf.base_align); 7308c2ecf20Sopenharmony_ci return -EINVAL; 7318c2ecf20Sopenharmony_ci } 7328c2ecf20Sopenharmony_ci offset += surf.layer_size * mslice; 7338c2ecf20Sopenharmony_ci if (offset > radeon_bo_size(track->db_z_write_bo)) { 7348c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d depth write bo too small (layer size %d, " 7358c2ecf20Sopenharmony_ci "offset %ld, max layer %d, bo size %ld)\n", 7368c2ecf20Sopenharmony_ci __func__, __LINE__, surf.layer_size, 7378c2ecf20Sopenharmony_ci (unsigned long)track->db_z_write_offset << 8, mslice, 7388c2ecf20Sopenharmony_ci radeon_bo_size(track->db_z_write_bo)); 7398c2ecf20Sopenharmony_ci return -EINVAL; 7408c2ecf20Sopenharmony_ci } 7418c2ecf20Sopenharmony_ci 7428c2ecf20Sopenharmony_ci /* hyperz */ 7438c2ecf20Sopenharmony_ci if (G_028040_TILE_SURFACE_ENABLE(track->db_z_info)) { 7448c2ecf20Sopenharmony_ci r = evergreen_cs_track_validate_htile(p, surf.nbx, surf.nby); 7458c2ecf20Sopenharmony_ci if (r) { 7468c2ecf20Sopenharmony_ci return r; 7478c2ecf20Sopenharmony_ci } 7488c2ecf20Sopenharmony_ci } 7498c2ecf20Sopenharmony_ci 7508c2ecf20Sopenharmony_ci return 0; 7518c2ecf20Sopenharmony_ci} 7528c2ecf20Sopenharmony_ci 7538c2ecf20Sopenharmony_cistatic int evergreen_cs_track_validate_texture(struct radeon_cs_parser *p, 7548c2ecf20Sopenharmony_ci struct radeon_bo *texture, 7558c2ecf20Sopenharmony_ci struct radeon_bo *mipmap, 7568c2ecf20Sopenharmony_ci unsigned idx) 7578c2ecf20Sopenharmony_ci{ 7588c2ecf20Sopenharmony_ci struct eg_surface surf; 7598c2ecf20Sopenharmony_ci unsigned long toffset, moffset; 7608c2ecf20Sopenharmony_ci unsigned dim, llevel, mslice, width, height, depth, i; 7618c2ecf20Sopenharmony_ci u32 texdw[8]; 7628c2ecf20Sopenharmony_ci int r; 7638c2ecf20Sopenharmony_ci 7648c2ecf20Sopenharmony_ci texdw[0] = radeon_get_ib_value(p, idx + 0); 7658c2ecf20Sopenharmony_ci texdw[1] = radeon_get_ib_value(p, idx + 1); 7668c2ecf20Sopenharmony_ci texdw[2] = radeon_get_ib_value(p, idx + 2); 7678c2ecf20Sopenharmony_ci texdw[3] = radeon_get_ib_value(p, idx + 3); 7688c2ecf20Sopenharmony_ci texdw[4] = radeon_get_ib_value(p, idx + 4); 7698c2ecf20Sopenharmony_ci texdw[5] = radeon_get_ib_value(p, idx + 5); 7708c2ecf20Sopenharmony_ci texdw[6] = radeon_get_ib_value(p, idx + 6); 7718c2ecf20Sopenharmony_ci texdw[7] = radeon_get_ib_value(p, idx + 7); 7728c2ecf20Sopenharmony_ci dim = G_030000_DIM(texdw[0]); 7738c2ecf20Sopenharmony_ci llevel = G_030014_LAST_LEVEL(texdw[5]); 7748c2ecf20Sopenharmony_ci mslice = G_030014_LAST_ARRAY(texdw[5]) + 1; 7758c2ecf20Sopenharmony_ci width = G_030000_TEX_WIDTH(texdw[0]) + 1; 7768c2ecf20Sopenharmony_ci height = G_030004_TEX_HEIGHT(texdw[1]) + 1; 7778c2ecf20Sopenharmony_ci depth = G_030004_TEX_DEPTH(texdw[1]) + 1; 7788c2ecf20Sopenharmony_ci surf.format = G_03001C_DATA_FORMAT(texdw[7]); 7798c2ecf20Sopenharmony_ci surf.nbx = (G_030000_PITCH(texdw[0]) + 1) * 8; 7808c2ecf20Sopenharmony_ci surf.nbx = r600_fmt_get_nblocksx(surf.format, surf.nbx); 7818c2ecf20Sopenharmony_ci surf.nby = r600_fmt_get_nblocksy(surf.format, height); 7828c2ecf20Sopenharmony_ci surf.mode = G_030004_ARRAY_MODE(texdw[1]); 7838c2ecf20Sopenharmony_ci surf.tsplit = G_030018_TILE_SPLIT(texdw[6]); 7848c2ecf20Sopenharmony_ci surf.nbanks = G_03001C_NUM_BANKS(texdw[7]); 7858c2ecf20Sopenharmony_ci surf.bankw = G_03001C_BANK_WIDTH(texdw[7]); 7868c2ecf20Sopenharmony_ci surf.bankh = G_03001C_BANK_HEIGHT(texdw[7]); 7878c2ecf20Sopenharmony_ci surf.mtilea = G_03001C_MACRO_TILE_ASPECT(texdw[7]); 7888c2ecf20Sopenharmony_ci surf.nsamples = 1; 7898c2ecf20Sopenharmony_ci toffset = texdw[2] << 8; 7908c2ecf20Sopenharmony_ci moffset = texdw[3] << 8; 7918c2ecf20Sopenharmony_ci 7928c2ecf20Sopenharmony_ci if (!r600_fmt_is_valid_texture(surf.format, p->family)) { 7938c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d texture invalid format %d\n", 7948c2ecf20Sopenharmony_ci __func__, __LINE__, surf.format); 7958c2ecf20Sopenharmony_ci return -EINVAL; 7968c2ecf20Sopenharmony_ci } 7978c2ecf20Sopenharmony_ci switch (dim) { 7988c2ecf20Sopenharmony_ci case V_030000_SQ_TEX_DIM_1D: 7998c2ecf20Sopenharmony_ci case V_030000_SQ_TEX_DIM_2D: 8008c2ecf20Sopenharmony_ci case V_030000_SQ_TEX_DIM_CUBEMAP: 8018c2ecf20Sopenharmony_ci case V_030000_SQ_TEX_DIM_1D_ARRAY: 8028c2ecf20Sopenharmony_ci case V_030000_SQ_TEX_DIM_2D_ARRAY: 8038c2ecf20Sopenharmony_ci depth = 1; 8048c2ecf20Sopenharmony_ci break; 8058c2ecf20Sopenharmony_ci case V_030000_SQ_TEX_DIM_2D_MSAA: 8068c2ecf20Sopenharmony_ci case V_030000_SQ_TEX_DIM_2D_ARRAY_MSAA: 8078c2ecf20Sopenharmony_ci surf.nsamples = 1 << llevel; 8088c2ecf20Sopenharmony_ci llevel = 0; 8098c2ecf20Sopenharmony_ci depth = 1; 8108c2ecf20Sopenharmony_ci break; 8118c2ecf20Sopenharmony_ci case V_030000_SQ_TEX_DIM_3D: 8128c2ecf20Sopenharmony_ci break; 8138c2ecf20Sopenharmony_ci default: 8148c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d texture invalid dimension %d\n", 8158c2ecf20Sopenharmony_ci __func__, __LINE__, dim); 8168c2ecf20Sopenharmony_ci return -EINVAL; 8178c2ecf20Sopenharmony_ci } 8188c2ecf20Sopenharmony_ci 8198c2ecf20Sopenharmony_ci r = evergreen_surface_value_conv_check(p, &surf, "texture"); 8208c2ecf20Sopenharmony_ci if (r) { 8218c2ecf20Sopenharmony_ci return r; 8228c2ecf20Sopenharmony_ci } 8238c2ecf20Sopenharmony_ci 8248c2ecf20Sopenharmony_ci /* align height */ 8258c2ecf20Sopenharmony_ci evergreen_surface_check(p, &surf, NULL); 8268c2ecf20Sopenharmony_ci surf.nby = ALIGN(surf.nby, surf.halign); 8278c2ecf20Sopenharmony_ci 8288c2ecf20Sopenharmony_ci r = evergreen_surface_check(p, &surf, "texture"); 8298c2ecf20Sopenharmony_ci if (r) { 8308c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d texture invalid 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x 0x%08x\n", 8318c2ecf20Sopenharmony_ci __func__, __LINE__, texdw[0], texdw[1], texdw[4], 8328c2ecf20Sopenharmony_ci texdw[5], texdw[6], texdw[7]); 8338c2ecf20Sopenharmony_ci return r; 8348c2ecf20Sopenharmony_ci } 8358c2ecf20Sopenharmony_ci 8368c2ecf20Sopenharmony_ci /* check texture size */ 8378c2ecf20Sopenharmony_ci if (toffset & (surf.base_align - 1)) { 8388c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d texture bo base %ld not aligned with %ld\n", 8398c2ecf20Sopenharmony_ci __func__, __LINE__, toffset, surf.base_align); 8408c2ecf20Sopenharmony_ci return -EINVAL; 8418c2ecf20Sopenharmony_ci } 8428c2ecf20Sopenharmony_ci if (surf.nsamples <= 1 && moffset & (surf.base_align - 1)) { 8438c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d mipmap bo base %ld not aligned with %ld\n", 8448c2ecf20Sopenharmony_ci __func__, __LINE__, moffset, surf.base_align); 8458c2ecf20Sopenharmony_ci return -EINVAL; 8468c2ecf20Sopenharmony_ci } 8478c2ecf20Sopenharmony_ci if (dim == SQ_TEX_DIM_3D) { 8488c2ecf20Sopenharmony_ci toffset += surf.layer_size * depth; 8498c2ecf20Sopenharmony_ci } else { 8508c2ecf20Sopenharmony_ci toffset += surf.layer_size * mslice; 8518c2ecf20Sopenharmony_ci } 8528c2ecf20Sopenharmony_ci if (toffset > radeon_bo_size(texture)) { 8538c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d texture bo too small (layer size %d, " 8548c2ecf20Sopenharmony_ci "offset %ld, max layer %d, depth %d, bo size %ld) (%d %d)\n", 8558c2ecf20Sopenharmony_ci __func__, __LINE__, surf.layer_size, 8568c2ecf20Sopenharmony_ci (unsigned long)texdw[2] << 8, mslice, 8578c2ecf20Sopenharmony_ci depth, radeon_bo_size(texture), 8588c2ecf20Sopenharmony_ci surf.nbx, surf.nby); 8598c2ecf20Sopenharmony_ci return -EINVAL; 8608c2ecf20Sopenharmony_ci } 8618c2ecf20Sopenharmony_ci 8628c2ecf20Sopenharmony_ci if (!mipmap) { 8638c2ecf20Sopenharmony_ci if (llevel) { 8648c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%i got NULL MIP_ADDRESS relocation\n", 8658c2ecf20Sopenharmony_ci __func__, __LINE__); 8668c2ecf20Sopenharmony_ci return -EINVAL; 8678c2ecf20Sopenharmony_ci } else { 8688c2ecf20Sopenharmony_ci return 0; /* everything's ok */ 8698c2ecf20Sopenharmony_ci } 8708c2ecf20Sopenharmony_ci } 8718c2ecf20Sopenharmony_ci 8728c2ecf20Sopenharmony_ci /* check mipmap size */ 8738c2ecf20Sopenharmony_ci for (i = 1; i <= llevel; i++) { 8748c2ecf20Sopenharmony_ci unsigned w, h, d; 8758c2ecf20Sopenharmony_ci 8768c2ecf20Sopenharmony_ci w = r600_mip_minify(width, i); 8778c2ecf20Sopenharmony_ci h = r600_mip_minify(height, i); 8788c2ecf20Sopenharmony_ci d = r600_mip_minify(depth, i); 8798c2ecf20Sopenharmony_ci surf.nbx = r600_fmt_get_nblocksx(surf.format, w); 8808c2ecf20Sopenharmony_ci surf.nby = r600_fmt_get_nblocksy(surf.format, h); 8818c2ecf20Sopenharmony_ci 8828c2ecf20Sopenharmony_ci switch (surf.mode) { 8838c2ecf20Sopenharmony_ci case ARRAY_2D_TILED_THIN1: 8848c2ecf20Sopenharmony_ci if (surf.nbx < surf.palign || surf.nby < surf.halign) { 8858c2ecf20Sopenharmony_ci surf.mode = ARRAY_1D_TILED_THIN1; 8868c2ecf20Sopenharmony_ci } 8878c2ecf20Sopenharmony_ci /* recompute alignment */ 8888c2ecf20Sopenharmony_ci evergreen_surface_check(p, &surf, NULL); 8898c2ecf20Sopenharmony_ci break; 8908c2ecf20Sopenharmony_ci case ARRAY_LINEAR_GENERAL: 8918c2ecf20Sopenharmony_ci case ARRAY_LINEAR_ALIGNED: 8928c2ecf20Sopenharmony_ci case ARRAY_1D_TILED_THIN1: 8938c2ecf20Sopenharmony_ci break; 8948c2ecf20Sopenharmony_ci default: 8958c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d invalid array mode %d\n", 8968c2ecf20Sopenharmony_ci __func__, __LINE__, surf.mode); 8978c2ecf20Sopenharmony_ci return -EINVAL; 8988c2ecf20Sopenharmony_ci } 8998c2ecf20Sopenharmony_ci surf.nbx = ALIGN(surf.nbx, surf.palign); 9008c2ecf20Sopenharmony_ci surf.nby = ALIGN(surf.nby, surf.halign); 9018c2ecf20Sopenharmony_ci 9028c2ecf20Sopenharmony_ci r = evergreen_surface_check(p, &surf, "mipmap"); 9038c2ecf20Sopenharmony_ci if (r) { 9048c2ecf20Sopenharmony_ci return r; 9058c2ecf20Sopenharmony_ci } 9068c2ecf20Sopenharmony_ci 9078c2ecf20Sopenharmony_ci if (dim == SQ_TEX_DIM_3D) { 9088c2ecf20Sopenharmony_ci moffset += surf.layer_size * d; 9098c2ecf20Sopenharmony_ci } else { 9108c2ecf20Sopenharmony_ci moffset += surf.layer_size * mslice; 9118c2ecf20Sopenharmony_ci } 9128c2ecf20Sopenharmony_ci if (moffset > radeon_bo_size(mipmap)) { 9138c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d mipmap [%d] bo too small (layer size %d, " 9148c2ecf20Sopenharmony_ci "offset %ld, coffset %ld, max layer %d, depth %d, " 9158c2ecf20Sopenharmony_ci "bo size %ld) level0 (%d %d %d)\n", 9168c2ecf20Sopenharmony_ci __func__, __LINE__, i, surf.layer_size, 9178c2ecf20Sopenharmony_ci (unsigned long)texdw[3] << 8, moffset, mslice, 9188c2ecf20Sopenharmony_ci d, radeon_bo_size(mipmap), 9198c2ecf20Sopenharmony_ci width, height, depth); 9208c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d problematic surf: (%d %d) (%d %d %d %d %d %d %d)\n", 9218c2ecf20Sopenharmony_ci __func__, __LINE__, surf.nbx, surf.nby, 9228c2ecf20Sopenharmony_ci surf.mode, surf.bpe, surf.nsamples, 9238c2ecf20Sopenharmony_ci surf.bankw, surf.bankh, 9248c2ecf20Sopenharmony_ci surf.tsplit, surf.mtilea); 9258c2ecf20Sopenharmony_ci return -EINVAL; 9268c2ecf20Sopenharmony_ci } 9278c2ecf20Sopenharmony_ci } 9288c2ecf20Sopenharmony_ci 9298c2ecf20Sopenharmony_ci return 0; 9308c2ecf20Sopenharmony_ci} 9318c2ecf20Sopenharmony_ci 9328c2ecf20Sopenharmony_cistatic int evergreen_cs_track_check(struct radeon_cs_parser *p) 9338c2ecf20Sopenharmony_ci{ 9348c2ecf20Sopenharmony_ci struct evergreen_cs_track *track = p->track; 9358c2ecf20Sopenharmony_ci unsigned tmp, i; 9368c2ecf20Sopenharmony_ci int r; 9378c2ecf20Sopenharmony_ci unsigned buffer_mask = 0; 9388c2ecf20Sopenharmony_ci 9398c2ecf20Sopenharmony_ci /* check streamout */ 9408c2ecf20Sopenharmony_ci if (track->streamout_dirty && track->vgt_strmout_config) { 9418c2ecf20Sopenharmony_ci for (i = 0; i < 4; i++) { 9428c2ecf20Sopenharmony_ci if (track->vgt_strmout_config & (1 << i)) { 9438c2ecf20Sopenharmony_ci buffer_mask |= (track->vgt_strmout_buffer_config >> (i * 4)) & 0xf; 9448c2ecf20Sopenharmony_ci } 9458c2ecf20Sopenharmony_ci } 9468c2ecf20Sopenharmony_ci 9478c2ecf20Sopenharmony_ci for (i = 0; i < 4; i++) { 9488c2ecf20Sopenharmony_ci if (buffer_mask & (1 << i)) { 9498c2ecf20Sopenharmony_ci if (track->vgt_strmout_bo[i]) { 9508c2ecf20Sopenharmony_ci u64 offset = (u64)track->vgt_strmout_bo_offset[i] + 9518c2ecf20Sopenharmony_ci (u64)track->vgt_strmout_size[i]; 9528c2ecf20Sopenharmony_ci if (offset > radeon_bo_size(track->vgt_strmout_bo[i])) { 9538c2ecf20Sopenharmony_ci DRM_ERROR("streamout %d bo too small: 0x%llx, 0x%lx\n", 9548c2ecf20Sopenharmony_ci i, offset, 9558c2ecf20Sopenharmony_ci radeon_bo_size(track->vgt_strmout_bo[i])); 9568c2ecf20Sopenharmony_ci return -EINVAL; 9578c2ecf20Sopenharmony_ci } 9588c2ecf20Sopenharmony_ci } else { 9598c2ecf20Sopenharmony_ci dev_warn(p->dev, "No buffer for streamout %d\n", i); 9608c2ecf20Sopenharmony_ci return -EINVAL; 9618c2ecf20Sopenharmony_ci } 9628c2ecf20Sopenharmony_ci } 9638c2ecf20Sopenharmony_ci } 9648c2ecf20Sopenharmony_ci track->streamout_dirty = false; 9658c2ecf20Sopenharmony_ci } 9668c2ecf20Sopenharmony_ci 9678c2ecf20Sopenharmony_ci if (track->sx_misc_kill_all_prims) 9688c2ecf20Sopenharmony_ci return 0; 9698c2ecf20Sopenharmony_ci 9708c2ecf20Sopenharmony_ci /* check that we have a cb for each enabled target 9718c2ecf20Sopenharmony_ci */ 9728c2ecf20Sopenharmony_ci if (track->cb_dirty) { 9738c2ecf20Sopenharmony_ci tmp = track->cb_target_mask; 9748c2ecf20Sopenharmony_ci for (i = 0; i < 8; i++) { 9758c2ecf20Sopenharmony_ci u32 format = G_028C70_FORMAT(track->cb_color_info[i]); 9768c2ecf20Sopenharmony_ci 9778c2ecf20Sopenharmony_ci if (format != V_028C70_COLOR_INVALID && 9788c2ecf20Sopenharmony_ci (tmp >> (i * 4)) & 0xF) { 9798c2ecf20Sopenharmony_ci /* at least one component is enabled */ 9808c2ecf20Sopenharmony_ci if (track->cb_color_bo[i] == NULL) { 9818c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d mask 0x%08X | 0x%08X no cb for %d\n", 9828c2ecf20Sopenharmony_ci __func__, __LINE__, track->cb_target_mask, track->cb_shader_mask, i); 9838c2ecf20Sopenharmony_ci return -EINVAL; 9848c2ecf20Sopenharmony_ci } 9858c2ecf20Sopenharmony_ci /* check cb */ 9868c2ecf20Sopenharmony_ci r = evergreen_cs_track_validate_cb(p, i); 9878c2ecf20Sopenharmony_ci if (r) { 9888c2ecf20Sopenharmony_ci return r; 9898c2ecf20Sopenharmony_ci } 9908c2ecf20Sopenharmony_ci } 9918c2ecf20Sopenharmony_ci } 9928c2ecf20Sopenharmony_ci track->cb_dirty = false; 9938c2ecf20Sopenharmony_ci } 9948c2ecf20Sopenharmony_ci 9958c2ecf20Sopenharmony_ci if (track->db_dirty) { 9968c2ecf20Sopenharmony_ci /* Check stencil buffer */ 9978c2ecf20Sopenharmony_ci if (G_028044_FORMAT(track->db_s_info) != V_028044_STENCIL_INVALID && 9988c2ecf20Sopenharmony_ci G_028800_STENCIL_ENABLE(track->db_depth_control)) { 9998c2ecf20Sopenharmony_ci r = evergreen_cs_track_validate_stencil(p); 10008c2ecf20Sopenharmony_ci if (r) 10018c2ecf20Sopenharmony_ci return r; 10028c2ecf20Sopenharmony_ci } 10038c2ecf20Sopenharmony_ci /* Check depth buffer */ 10048c2ecf20Sopenharmony_ci if (G_028040_FORMAT(track->db_z_info) != V_028040_Z_INVALID && 10058c2ecf20Sopenharmony_ci G_028800_Z_ENABLE(track->db_depth_control)) { 10068c2ecf20Sopenharmony_ci r = evergreen_cs_track_validate_depth(p); 10078c2ecf20Sopenharmony_ci if (r) 10088c2ecf20Sopenharmony_ci return r; 10098c2ecf20Sopenharmony_ci } 10108c2ecf20Sopenharmony_ci track->db_dirty = false; 10118c2ecf20Sopenharmony_ci } 10128c2ecf20Sopenharmony_ci 10138c2ecf20Sopenharmony_ci return 0; 10148c2ecf20Sopenharmony_ci} 10158c2ecf20Sopenharmony_ci 10168c2ecf20Sopenharmony_ci/** 10178c2ecf20Sopenharmony_ci * evergreen_cs_packet_parse_vline() - parse userspace VLINE packet 10188c2ecf20Sopenharmony_ci * @parser: parser structure holding parsing context. 10198c2ecf20Sopenharmony_ci * 10208c2ecf20Sopenharmony_ci * This is an Evergreen(+)-specific function for parsing VLINE packets. 10218c2ecf20Sopenharmony_ci * Real work is done by r600_cs_common_vline_parse function. 10228c2ecf20Sopenharmony_ci * Here we just set up ASIC-specific register table and call 10238c2ecf20Sopenharmony_ci * the common implementation function. 10248c2ecf20Sopenharmony_ci */ 10258c2ecf20Sopenharmony_cistatic int evergreen_cs_packet_parse_vline(struct radeon_cs_parser *p) 10268c2ecf20Sopenharmony_ci{ 10278c2ecf20Sopenharmony_ci 10288c2ecf20Sopenharmony_ci static uint32_t vline_start_end[6] = { 10298c2ecf20Sopenharmony_ci EVERGREEN_VLINE_START_END + EVERGREEN_CRTC0_REGISTER_OFFSET, 10308c2ecf20Sopenharmony_ci EVERGREEN_VLINE_START_END + EVERGREEN_CRTC1_REGISTER_OFFSET, 10318c2ecf20Sopenharmony_ci EVERGREEN_VLINE_START_END + EVERGREEN_CRTC2_REGISTER_OFFSET, 10328c2ecf20Sopenharmony_ci EVERGREEN_VLINE_START_END + EVERGREEN_CRTC3_REGISTER_OFFSET, 10338c2ecf20Sopenharmony_ci EVERGREEN_VLINE_START_END + EVERGREEN_CRTC4_REGISTER_OFFSET, 10348c2ecf20Sopenharmony_ci EVERGREEN_VLINE_START_END + EVERGREEN_CRTC5_REGISTER_OFFSET 10358c2ecf20Sopenharmony_ci }; 10368c2ecf20Sopenharmony_ci static uint32_t vline_status[6] = { 10378c2ecf20Sopenharmony_ci EVERGREEN_VLINE_STATUS + EVERGREEN_CRTC0_REGISTER_OFFSET, 10388c2ecf20Sopenharmony_ci EVERGREEN_VLINE_STATUS + EVERGREEN_CRTC1_REGISTER_OFFSET, 10398c2ecf20Sopenharmony_ci EVERGREEN_VLINE_STATUS + EVERGREEN_CRTC2_REGISTER_OFFSET, 10408c2ecf20Sopenharmony_ci EVERGREEN_VLINE_STATUS + EVERGREEN_CRTC3_REGISTER_OFFSET, 10418c2ecf20Sopenharmony_ci EVERGREEN_VLINE_STATUS + EVERGREEN_CRTC4_REGISTER_OFFSET, 10428c2ecf20Sopenharmony_ci EVERGREEN_VLINE_STATUS + EVERGREEN_CRTC5_REGISTER_OFFSET 10438c2ecf20Sopenharmony_ci }; 10448c2ecf20Sopenharmony_ci 10458c2ecf20Sopenharmony_ci return r600_cs_common_vline_parse(p, vline_start_end, vline_status); 10468c2ecf20Sopenharmony_ci} 10478c2ecf20Sopenharmony_ci 10488c2ecf20Sopenharmony_cistatic int evergreen_packet0_check(struct radeon_cs_parser *p, 10498c2ecf20Sopenharmony_ci struct radeon_cs_packet *pkt, 10508c2ecf20Sopenharmony_ci unsigned idx, unsigned reg) 10518c2ecf20Sopenharmony_ci{ 10528c2ecf20Sopenharmony_ci int r; 10538c2ecf20Sopenharmony_ci 10548c2ecf20Sopenharmony_ci switch (reg) { 10558c2ecf20Sopenharmony_ci case EVERGREEN_VLINE_START_END: 10568c2ecf20Sopenharmony_ci r = evergreen_cs_packet_parse_vline(p); 10578c2ecf20Sopenharmony_ci if (r) { 10588c2ecf20Sopenharmony_ci DRM_ERROR("No reloc for ib[%d]=0x%04X\n", 10598c2ecf20Sopenharmony_ci idx, reg); 10608c2ecf20Sopenharmony_ci return r; 10618c2ecf20Sopenharmony_ci } 10628c2ecf20Sopenharmony_ci break; 10638c2ecf20Sopenharmony_ci default: 10648c2ecf20Sopenharmony_ci pr_err("Forbidden register 0x%04X in cs at %d\n", reg, idx); 10658c2ecf20Sopenharmony_ci return -EINVAL; 10668c2ecf20Sopenharmony_ci } 10678c2ecf20Sopenharmony_ci return 0; 10688c2ecf20Sopenharmony_ci} 10698c2ecf20Sopenharmony_ci 10708c2ecf20Sopenharmony_cistatic int evergreen_cs_parse_packet0(struct radeon_cs_parser *p, 10718c2ecf20Sopenharmony_ci struct radeon_cs_packet *pkt) 10728c2ecf20Sopenharmony_ci{ 10738c2ecf20Sopenharmony_ci unsigned reg, i; 10748c2ecf20Sopenharmony_ci unsigned idx; 10758c2ecf20Sopenharmony_ci int r; 10768c2ecf20Sopenharmony_ci 10778c2ecf20Sopenharmony_ci idx = pkt->idx + 1; 10788c2ecf20Sopenharmony_ci reg = pkt->reg; 10798c2ecf20Sopenharmony_ci for (i = 0; i <= pkt->count; i++, idx++, reg += 4) { 10808c2ecf20Sopenharmony_ci r = evergreen_packet0_check(p, pkt, idx, reg); 10818c2ecf20Sopenharmony_ci if (r) { 10828c2ecf20Sopenharmony_ci return r; 10838c2ecf20Sopenharmony_ci } 10848c2ecf20Sopenharmony_ci } 10858c2ecf20Sopenharmony_ci return 0; 10868c2ecf20Sopenharmony_ci} 10878c2ecf20Sopenharmony_ci 10888c2ecf20Sopenharmony_ci/** 10898c2ecf20Sopenharmony_ci * evergreen_cs_handle_reg() - process registers that need special handling. 10908c2ecf20Sopenharmony_ci * @parser: parser structure holding parsing context 10918c2ecf20Sopenharmony_ci * @reg: register we are testing 10928c2ecf20Sopenharmony_ci * @idx: index into the cs buffer 10938c2ecf20Sopenharmony_ci */ 10948c2ecf20Sopenharmony_cistatic int evergreen_cs_handle_reg(struct radeon_cs_parser *p, u32 reg, u32 idx) 10958c2ecf20Sopenharmony_ci{ 10968c2ecf20Sopenharmony_ci struct evergreen_cs_track *track = (struct evergreen_cs_track *)p->track; 10978c2ecf20Sopenharmony_ci struct radeon_bo_list *reloc; 10988c2ecf20Sopenharmony_ci u32 tmp, *ib; 10998c2ecf20Sopenharmony_ci int r; 11008c2ecf20Sopenharmony_ci 11018c2ecf20Sopenharmony_ci ib = p->ib.ptr; 11028c2ecf20Sopenharmony_ci switch (reg) { 11038c2ecf20Sopenharmony_ci /* force following reg to 0 in an attempt to disable out buffer 11048c2ecf20Sopenharmony_ci * which will need us to better understand how it works to perform 11058c2ecf20Sopenharmony_ci * security check on it (Jerome) 11068c2ecf20Sopenharmony_ci */ 11078c2ecf20Sopenharmony_ci case SQ_ESGS_RING_SIZE: 11088c2ecf20Sopenharmony_ci case SQ_GSVS_RING_SIZE: 11098c2ecf20Sopenharmony_ci case SQ_ESTMP_RING_SIZE: 11108c2ecf20Sopenharmony_ci case SQ_GSTMP_RING_SIZE: 11118c2ecf20Sopenharmony_ci case SQ_HSTMP_RING_SIZE: 11128c2ecf20Sopenharmony_ci case SQ_LSTMP_RING_SIZE: 11138c2ecf20Sopenharmony_ci case SQ_PSTMP_RING_SIZE: 11148c2ecf20Sopenharmony_ci case SQ_VSTMP_RING_SIZE: 11158c2ecf20Sopenharmony_ci case SQ_ESGS_RING_ITEMSIZE: 11168c2ecf20Sopenharmony_ci case SQ_ESTMP_RING_ITEMSIZE: 11178c2ecf20Sopenharmony_ci case SQ_GSTMP_RING_ITEMSIZE: 11188c2ecf20Sopenharmony_ci case SQ_GSVS_RING_ITEMSIZE: 11198c2ecf20Sopenharmony_ci case SQ_GS_VERT_ITEMSIZE: 11208c2ecf20Sopenharmony_ci case SQ_GS_VERT_ITEMSIZE_1: 11218c2ecf20Sopenharmony_ci case SQ_GS_VERT_ITEMSIZE_2: 11228c2ecf20Sopenharmony_ci case SQ_GS_VERT_ITEMSIZE_3: 11238c2ecf20Sopenharmony_ci case SQ_GSVS_RING_OFFSET_1: 11248c2ecf20Sopenharmony_ci case SQ_GSVS_RING_OFFSET_2: 11258c2ecf20Sopenharmony_ci case SQ_GSVS_RING_OFFSET_3: 11268c2ecf20Sopenharmony_ci case SQ_HSTMP_RING_ITEMSIZE: 11278c2ecf20Sopenharmony_ci case SQ_LSTMP_RING_ITEMSIZE: 11288c2ecf20Sopenharmony_ci case SQ_PSTMP_RING_ITEMSIZE: 11298c2ecf20Sopenharmony_ci case SQ_VSTMP_RING_ITEMSIZE: 11308c2ecf20Sopenharmony_ci case VGT_TF_RING_SIZE: 11318c2ecf20Sopenharmony_ci /* get value to populate the IB don't remove */ 11328c2ecf20Sopenharmony_ci /*tmp =radeon_get_ib_value(p, idx); 11338c2ecf20Sopenharmony_ci ib[idx] = 0;*/ 11348c2ecf20Sopenharmony_ci break; 11358c2ecf20Sopenharmony_ci case SQ_ESGS_RING_BASE: 11368c2ecf20Sopenharmony_ci case SQ_GSVS_RING_BASE: 11378c2ecf20Sopenharmony_ci case SQ_ESTMP_RING_BASE: 11388c2ecf20Sopenharmony_ci case SQ_GSTMP_RING_BASE: 11398c2ecf20Sopenharmony_ci case SQ_HSTMP_RING_BASE: 11408c2ecf20Sopenharmony_ci case SQ_LSTMP_RING_BASE: 11418c2ecf20Sopenharmony_ci case SQ_PSTMP_RING_BASE: 11428c2ecf20Sopenharmony_ci case SQ_VSTMP_RING_BASE: 11438c2ecf20Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 11448c2ecf20Sopenharmony_ci if (r) { 11458c2ecf20Sopenharmony_ci dev_warn(p->dev, "bad SET_CONTEXT_REG " 11468c2ecf20Sopenharmony_ci "0x%04X\n", reg); 11478c2ecf20Sopenharmony_ci return -EINVAL; 11488c2ecf20Sopenharmony_ci } 11498c2ecf20Sopenharmony_ci ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff); 11508c2ecf20Sopenharmony_ci break; 11518c2ecf20Sopenharmony_ci case DB_DEPTH_CONTROL: 11528c2ecf20Sopenharmony_ci track->db_depth_control = radeon_get_ib_value(p, idx); 11538c2ecf20Sopenharmony_ci track->db_dirty = true; 11548c2ecf20Sopenharmony_ci break; 11558c2ecf20Sopenharmony_ci case CAYMAN_DB_EQAA: 11568c2ecf20Sopenharmony_ci if (p->rdev->family < CHIP_CAYMAN) { 11578c2ecf20Sopenharmony_ci dev_warn(p->dev, "bad SET_CONTEXT_REG " 11588c2ecf20Sopenharmony_ci "0x%04X\n", reg); 11598c2ecf20Sopenharmony_ci return -EINVAL; 11608c2ecf20Sopenharmony_ci } 11618c2ecf20Sopenharmony_ci break; 11628c2ecf20Sopenharmony_ci case CAYMAN_DB_DEPTH_INFO: 11638c2ecf20Sopenharmony_ci if (p->rdev->family < CHIP_CAYMAN) { 11648c2ecf20Sopenharmony_ci dev_warn(p->dev, "bad SET_CONTEXT_REG " 11658c2ecf20Sopenharmony_ci "0x%04X\n", reg); 11668c2ecf20Sopenharmony_ci return -EINVAL; 11678c2ecf20Sopenharmony_ci } 11688c2ecf20Sopenharmony_ci break; 11698c2ecf20Sopenharmony_ci case DB_Z_INFO: 11708c2ecf20Sopenharmony_ci track->db_z_info = radeon_get_ib_value(p, idx); 11718c2ecf20Sopenharmony_ci if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { 11728c2ecf20Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 11738c2ecf20Sopenharmony_ci if (r) { 11748c2ecf20Sopenharmony_ci dev_warn(p->dev, "bad SET_CONTEXT_REG " 11758c2ecf20Sopenharmony_ci "0x%04X\n", reg); 11768c2ecf20Sopenharmony_ci return -EINVAL; 11778c2ecf20Sopenharmony_ci } 11788c2ecf20Sopenharmony_ci ib[idx] &= ~Z_ARRAY_MODE(0xf); 11798c2ecf20Sopenharmony_ci track->db_z_info &= ~Z_ARRAY_MODE(0xf); 11808c2ecf20Sopenharmony_ci ib[idx] |= Z_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->tiling_flags)); 11818c2ecf20Sopenharmony_ci track->db_z_info |= Z_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->tiling_flags)); 11828c2ecf20Sopenharmony_ci if (reloc->tiling_flags & RADEON_TILING_MACRO) { 11838c2ecf20Sopenharmony_ci unsigned bankw, bankh, mtaspect, tile_split; 11848c2ecf20Sopenharmony_ci 11858c2ecf20Sopenharmony_ci evergreen_tiling_fields(reloc->tiling_flags, 11868c2ecf20Sopenharmony_ci &bankw, &bankh, &mtaspect, 11878c2ecf20Sopenharmony_ci &tile_split); 11888c2ecf20Sopenharmony_ci ib[idx] |= DB_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks)); 11898c2ecf20Sopenharmony_ci ib[idx] |= DB_TILE_SPLIT(tile_split) | 11908c2ecf20Sopenharmony_ci DB_BANK_WIDTH(bankw) | 11918c2ecf20Sopenharmony_ci DB_BANK_HEIGHT(bankh) | 11928c2ecf20Sopenharmony_ci DB_MACRO_TILE_ASPECT(mtaspect); 11938c2ecf20Sopenharmony_ci } 11948c2ecf20Sopenharmony_ci } 11958c2ecf20Sopenharmony_ci track->db_dirty = true; 11968c2ecf20Sopenharmony_ci break; 11978c2ecf20Sopenharmony_ci case DB_STENCIL_INFO: 11988c2ecf20Sopenharmony_ci track->db_s_info = radeon_get_ib_value(p, idx); 11998c2ecf20Sopenharmony_ci track->db_dirty = true; 12008c2ecf20Sopenharmony_ci break; 12018c2ecf20Sopenharmony_ci case DB_DEPTH_VIEW: 12028c2ecf20Sopenharmony_ci track->db_depth_view = radeon_get_ib_value(p, idx); 12038c2ecf20Sopenharmony_ci track->db_dirty = true; 12048c2ecf20Sopenharmony_ci break; 12058c2ecf20Sopenharmony_ci case DB_DEPTH_SIZE: 12068c2ecf20Sopenharmony_ci track->db_depth_size = radeon_get_ib_value(p, idx); 12078c2ecf20Sopenharmony_ci track->db_dirty = true; 12088c2ecf20Sopenharmony_ci break; 12098c2ecf20Sopenharmony_ci case R_02805C_DB_DEPTH_SLICE: 12108c2ecf20Sopenharmony_ci track->db_depth_slice = radeon_get_ib_value(p, idx); 12118c2ecf20Sopenharmony_ci track->db_dirty = true; 12128c2ecf20Sopenharmony_ci break; 12138c2ecf20Sopenharmony_ci case DB_Z_READ_BASE: 12148c2ecf20Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 12158c2ecf20Sopenharmony_ci if (r) { 12168c2ecf20Sopenharmony_ci dev_warn(p->dev, "bad SET_CONTEXT_REG " 12178c2ecf20Sopenharmony_ci "0x%04X\n", reg); 12188c2ecf20Sopenharmony_ci return -EINVAL; 12198c2ecf20Sopenharmony_ci } 12208c2ecf20Sopenharmony_ci track->db_z_read_offset = radeon_get_ib_value(p, idx); 12218c2ecf20Sopenharmony_ci ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff); 12228c2ecf20Sopenharmony_ci track->db_z_read_bo = reloc->robj; 12238c2ecf20Sopenharmony_ci track->db_dirty = true; 12248c2ecf20Sopenharmony_ci break; 12258c2ecf20Sopenharmony_ci case DB_Z_WRITE_BASE: 12268c2ecf20Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 12278c2ecf20Sopenharmony_ci if (r) { 12288c2ecf20Sopenharmony_ci dev_warn(p->dev, "bad SET_CONTEXT_REG " 12298c2ecf20Sopenharmony_ci "0x%04X\n", reg); 12308c2ecf20Sopenharmony_ci return -EINVAL; 12318c2ecf20Sopenharmony_ci } 12328c2ecf20Sopenharmony_ci track->db_z_write_offset = radeon_get_ib_value(p, idx); 12338c2ecf20Sopenharmony_ci ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff); 12348c2ecf20Sopenharmony_ci track->db_z_write_bo = reloc->robj; 12358c2ecf20Sopenharmony_ci track->db_dirty = true; 12368c2ecf20Sopenharmony_ci break; 12378c2ecf20Sopenharmony_ci case DB_STENCIL_READ_BASE: 12388c2ecf20Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 12398c2ecf20Sopenharmony_ci if (r) { 12408c2ecf20Sopenharmony_ci dev_warn(p->dev, "bad SET_CONTEXT_REG " 12418c2ecf20Sopenharmony_ci "0x%04X\n", reg); 12428c2ecf20Sopenharmony_ci return -EINVAL; 12438c2ecf20Sopenharmony_ci } 12448c2ecf20Sopenharmony_ci track->db_s_read_offset = radeon_get_ib_value(p, idx); 12458c2ecf20Sopenharmony_ci ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff); 12468c2ecf20Sopenharmony_ci track->db_s_read_bo = reloc->robj; 12478c2ecf20Sopenharmony_ci track->db_dirty = true; 12488c2ecf20Sopenharmony_ci break; 12498c2ecf20Sopenharmony_ci case DB_STENCIL_WRITE_BASE: 12508c2ecf20Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 12518c2ecf20Sopenharmony_ci if (r) { 12528c2ecf20Sopenharmony_ci dev_warn(p->dev, "bad SET_CONTEXT_REG " 12538c2ecf20Sopenharmony_ci "0x%04X\n", reg); 12548c2ecf20Sopenharmony_ci return -EINVAL; 12558c2ecf20Sopenharmony_ci } 12568c2ecf20Sopenharmony_ci track->db_s_write_offset = radeon_get_ib_value(p, idx); 12578c2ecf20Sopenharmony_ci ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff); 12588c2ecf20Sopenharmony_ci track->db_s_write_bo = reloc->robj; 12598c2ecf20Sopenharmony_ci track->db_dirty = true; 12608c2ecf20Sopenharmony_ci break; 12618c2ecf20Sopenharmony_ci case VGT_STRMOUT_CONFIG: 12628c2ecf20Sopenharmony_ci track->vgt_strmout_config = radeon_get_ib_value(p, idx); 12638c2ecf20Sopenharmony_ci track->streamout_dirty = true; 12648c2ecf20Sopenharmony_ci break; 12658c2ecf20Sopenharmony_ci case VGT_STRMOUT_BUFFER_CONFIG: 12668c2ecf20Sopenharmony_ci track->vgt_strmout_buffer_config = radeon_get_ib_value(p, idx); 12678c2ecf20Sopenharmony_ci track->streamout_dirty = true; 12688c2ecf20Sopenharmony_ci break; 12698c2ecf20Sopenharmony_ci case VGT_STRMOUT_BUFFER_BASE_0: 12708c2ecf20Sopenharmony_ci case VGT_STRMOUT_BUFFER_BASE_1: 12718c2ecf20Sopenharmony_ci case VGT_STRMOUT_BUFFER_BASE_2: 12728c2ecf20Sopenharmony_ci case VGT_STRMOUT_BUFFER_BASE_3: 12738c2ecf20Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 12748c2ecf20Sopenharmony_ci if (r) { 12758c2ecf20Sopenharmony_ci dev_warn(p->dev, "bad SET_CONTEXT_REG " 12768c2ecf20Sopenharmony_ci "0x%04X\n", reg); 12778c2ecf20Sopenharmony_ci return -EINVAL; 12788c2ecf20Sopenharmony_ci } 12798c2ecf20Sopenharmony_ci tmp = (reg - VGT_STRMOUT_BUFFER_BASE_0) / 16; 12808c2ecf20Sopenharmony_ci track->vgt_strmout_bo_offset[tmp] = radeon_get_ib_value(p, idx) << 8; 12818c2ecf20Sopenharmony_ci ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff); 12828c2ecf20Sopenharmony_ci track->vgt_strmout_bo[tmp] = reloc->robj; 12838c2ecf20Sopenharmony_ci track->streamout_dirty = true; 12848c2ecf20Sopenharmony_ci break; 12858c2ecf20Sopenharmony_ci case VGT_STRMOUT_BUFFER_SIZE_0: 12868c2ecf20Sopenharmony_ci case VGT_STRMOUT_BUFFER_SIZE_1: 12878c2ecf20Sopenharmony_ci case VGT_STRMOUT_BUFFER_SIZE_2: 12888c2ecf20Sopenharmony_ci case VGT_STRMOUT_BUFFER_SIZE_3: 12898c2ecf20Sopenharmony_ci tmp = (reg - VGT_STRMOUT_BUFFER_SIZE_0) / 16; 12908c2ecf20Sopenharmony_ci /* size in register is DWs, convert to bytes */ 12918c2ecf20Sopenharmony_ci track->vgt_strmout_size[tmp] = radeon_get_ib_value(p, idx) * 4; 12928c2ecf20Sopenharmony_ci track->streamout_dirty = true; 12938c2ecf20Sopenharmony_ci break; 12948c2ecf20Sopenharmony_ci case CP_COHER_BASE: 12958c2ecf20Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 12968c2ecf20Sopenharmony_ci if (r) { 12978c2ecf20Sopenharmony_ci dev_warn(p->dev, "missing reloc for CP_COHER_BASE " 12988c2ecf20Sopenharmony_ci "0x%04X\n", reg); 12998c2ecf20Sopenharmony_ci return -EINVAL; 13008c2ecf20Sopenharmony_ci } 13018c2ecf20Sopenharmony_ci ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff); 13028c2ecf20Sopenharmony_ci break; 13038c2ecf20Sopenharmony_ci case CB_TARGET_MASK: 13048c2ecf20Sopenharmony_ci track->cb_target_mask = radeon_get_ib_value(p, idx); 13058c2ecf20Sopenharmony_ci track->cb_dirty = true; 13068c2ecf20Sopenharmony_ci break; 13078c2ecf20Sopenharmony_ci case CB_SHADER_MASK: 13088c2ecf20Sopenharmony_ci track->cb_shader_mask = radeon_get_ib_value(p, idx); 13098c2ecf20Sopenharmony_ci track->cb_dirty = true; 13108c2ecf20Sopenharmony_ci break; 13118c2ecf20Sopenharmony_ci case PA_SC_AA_CONFIG: 13128c2ecf20Sopenharmony_ci if (p->rdev->family >= CHIP_CAYMAN) { 13138c2ecf20Sopenharmony_ci dev_warn(p->dev, "bad SET_CONTEXT_REG " 13148c2ecf20Sopenharmony_ci "0x%04X\n", reg); 13158c2ecf20Sopenharmony_ci return -EINVAL; 13168c2ecf20Sopenharmony_ci } 13178c2ecf20Sopenharmony_ci tmp = radeon_get_ib_value(p, idx) & MSAA_NUM_SAMPLES_MASK; 13188c2ecf20Sopenharmony_ci track->nsamples = 1 << tmp; 13198c2ecf20Sopenharmony_ci break; 13208c2ecf20Sopenharmony_ci case CAYMAN_PA_SC_AA_CONFIG: 13218c2ecf20Sopenharmony_ci if (p->rdev->family < CHIP_CAYMAN) { 13228c2ecf20Sopenharmony_ci dev_warn(p->dev, "bad SET_CONTEXT_REG " 13238c2ecf20Sopenharmony_ci "0x%04X\n", reg); 13248c2ecf20Sopenharmony_ci return -EINVAL; 13258c2ecf20Sopenharmony_ci } 13268c2ecf20Sopenharmony_ci tmp = radeon_get_ib_value(p, idx) & CAYMAN_MSAA_NUM_SAMPLES_MASK; 13278c2ecf20Sopenharmony_ci track->nsamples = 1 << tmp; 13288c2ecf20Sopenharmony_ci break; 13298c2ecf20Sopenharmony_ci case CB_COLOR0_VIEW: 13308c2ecf20Sopenharmony_ci case CB_COLOR1_VIEW: 13318c2ecf20Sopenharmony_ci case CB_COLOR2_VIEW: 13328c2ecf20Sopenharmony_ci case CB_COLOR3_VIEW: 13338c2ecf20Sopenharmony_ci case CB_COLOR4_VIEW: 13348c2ecf20Sopenharmony_ci case CB_COLOR5_VIEW: 13358c2ecf20Sopenharmony_ci case CB_COLOR6_VIEW: 13368c2ecf20Sopenharmony_ci case CB_COLOR7_VIEW: 13378c2ecf20Sopenharmony_ci tmp = (reg - CB_COLOR0_VIEW) / 0x3c; 13388c2ecf20Sopenharmony_ci track->cb_color_view[tmp] = radeon_get_ib_value(p, idx); 13398c2ecf20Sopenharmony_ci track->cb_dirty = true; 13408c2ecf20Sopenharmony_ci break; 13418c2ecf20Sopenharmony_ci case CB_COLOR8_VIEW: 13428c2ecf20Sopenharmony_ci case CB_COLOR9_VIEW: 13438c2ecf20Sopenharmony_ci case CB_COLOR10_VIEW: 13448c2ecf20Sopenharmony_ci case CB_COLOR11_VIEW: 13458c2ecf20Sopenharmony_ci tmp = ((reg - CB_COLOR8_VIEW) / 0x1c) + 8; 13468c2ecf20Sopenharmony_ci track->cb_color_view[tmp] = radeon_get_ib_value(p, idx); 13478c2ecf20Sopenharmony_ci track->cb_dirty = true; 13488c2ecf20Sopenharmony_ci break; 13498c2ecf20Sopenharmony_ci case CB_COLOR0_INFO: 13508c2ecf20Sopenharmony_ci case CB_COLOR1_INFO: 13518c2ecf20Sopenharmony_ci case CB_COLOR2_INFO: 13528c2ecf20Sopenharmony_ci case CB_COLOR3_INFO: 13538c2ecf20Sopenharmony_ci case CB_COLOR4_INFO: 13548c2ecf20Sopenharmony_ci case CB_COLOR5_INFO: 13558c2ecf20Sopenharmony_ci case CB_COLOR6_INFO: 13568c2ecf20Sopenharmony_ci case CB_COLOR7_INFO: 13578c2ecf20Sopenharmony_ci tmp = (reg - CB_COLOR0_INFO) / 0x3c; 13588c2ecf20Sopenharmony_ci track->cb_color_info[tmp] = radeon_get_ib_value(p, idx); 13598c2ecf20Sopenharmony_ci if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { 13608c2ecf20Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 13618c2ecf20Sopenharmony_ci if (r) { 13628c2ecf20Sopenharmony_ci dev_warn(p->dev, "bad SET_CONTEXT_REG " 13638c2ecf20Sopenharmony_ci "0x%04X\n", reg); 13648c2ecf20Sopenharmony_ci return -EINVAL; 13658c2ecf20Sopenharmony_ci } 13668c2ecf20Sopenharmony_ci ib[idx] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->tiling_flags)); 13678c2ecf20Sopenharmony_ci track->cb_color_info[tmp] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->tiling_flags)); 13688c2ecf20Sopenharmony_ci } 13698c2ecf20Sopenharmony_ci track->cb_dirty = true; 13708c2ecf20Sopenharmony_ci break; 13718c2ecf20Sopenharmony_ci case CB_COLOR8_INFO: 13728c2ecf20Sopenharmony_ci case CB_COLOR9_INFO: 13738c2ecf20Sopenharmony_ci case CB_COLOR10_INFO: 13748c2ecf20Sopenharmony_ci case CB_COLOR11_INFO: 13758c2ecf20Sopenharmony_ci tmp = ((reg - CB_COLOR8_INFO) / 0x1c) + 8; 13768c2ecf20Sopenharmony_ci track->cb_color_info[tmp] = radeon_get_ib_value(p, idx); 13778c2ecf20Sopenharmony_ci if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { 13788c2ecf20Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 13798c2ecf20Sopenharmony_ci if (r) { 13808c2ecf20Sopenharmony_ci dev_warn(p->dev, "bad SET_CONTEXT_REG " 13818c2ecf20Sopenharmony_ci "0x%04X\n", reg); 13828c2ecf20Sopenharmony_ci return -EINVAL; 13838c2ecf20Sopenharmony_ci } 13848c2ecf20Sopenharmony_ci ib[idx] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->tiling_flags)); 13858c2ecf20Sopenharmony_ci track->cb_color_info[tmp] |= CB_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->tiling_flags)); 13868c2ecf20Sopenharmony_ci } 13878c2ecf20Sopenharmony_ci track->cb_dirty = true; 13888c2ecf20Sopenharmony_ci break; 13898c2ecf20Sopenharmony_ci case CB_COLOR0_PITCH: 13908c2ecf20Sopenharmony_ci case CB_COLOR1_PITCH: 13918c2ecf20Sopenharmony_ci case CB_COLOR2_PITCH: 13928c2ecf20Sopenharmony_ci case CB_COLOR3_PITCH: 13938c2ecf20Sopenharmony_ci case CB_COLOR4_PITCH: 13948c2ecf20Sopenharmony_ci case CB_COLOR5_PITCH: 13958c2ecf20Sopenharmony_ci case CB_COLOR6_PITCH: 13968c2ecf20Sopenharmony_ci case CB_COLOR7_PITCH: 13978c2ecf20Sopenharmony_ci tmp = (reg - CB_COLOR0_PITCH) / 0x3c; 13988c2ecf20Sopenharmony_ci track->cb_color_pitch[tmp] = radeon_get_ib_value(p, idx); 13998c2ecf20Sopenharmony_ci track->cb_dirty = true; 14008c2ecf20Sopenharmony_ci break; 14018c2ecf20Sopenharmony_ci case CB_COLOR8_PITCH: 14028c2ecf20Sopenharmony_ci case CB_COLOR9_PITCH: 14038c2ecf20Sopenharmony_ci case CB_COLOR10_PITCH: 14048c2ecf20Sopenharmony_ci case CB_COLOR11_PITCH: 14058c2ecf20Sopenharmony_ci tmp = ((reg - CB_COLOR8_PITCH) / 0x1c) + 8; 14068c2ecf20Sopenharmony_ci track->cb_color_pitch[tmp] = radeon_get_ib_value(p, idx); 14078c2ecf20Sopenharmony_ci track->cb_dirty = true; 14088c2ecf20Sopenharmony_ci break; 14098c2ecf20Sopenharmony_ci case CB_COLOR0_SLICE: 14108c2ecf20Sopenharmony_ci case CB_COLOR1_SLICE: 14118c2ecf20Sopenharmony_ci case CB_COLOR2_SLICE: 14128c2ecf20Sopenharmony_ci case CB_COLOR3_SLICE: 14138c2ecf20Sopenharmony_ci case CB_COLOR4_SLICE: 14148c2ecf20Sopenharmony_ci case CB_COLOR5_SLICE: 14158c2ecf20Sopenharmony_ci case CB_COLOR6_SLICE: 14168c2ecf20Sopenharmony_ci case CB_COLOR7_SLICE: 14178c2ecf20Sopenharmony_ci tmp = (reg - CB_COLOR0_SLICE) / 0x3c; 14188c2ecf20Sopenharmony_ci track->cb_color_slice[tmp] = radeon_get_ib_value(p, idx); 14198c2ecf20Sopenharmony_ci track->cb_color_slice_idx[tmp] = idx; 14208c2ecf20Sopenharmony_ci track->cb_dirty = true; 14218c2ecf20Sopenharmony_ci break; 14228c2ecf20Sopenharmony_ci case CB_COLOR8_SLICE: 14238c2ecf20Sopenharmony_ci case CB_COLOR9_SLICE: 14248c2ecf20Sopenharmony_ci case CB_COLOR10_SLICE: 14258c2ecf20Sopenharmony_ci case CB_COLOR11_SLICE: 14268c2ecf20Sopenharmony_ci tmp = ((reg - CB_COLOR8_SLICE) / 0x1c) + 8; 14278c2ecf20Sopenharmony_ci track->cb_color_slice[tmp] = radeon_get_ib_value(p, idx); 14288c2ecf20Sopenharmony_ci track->cb_color_slice_idx[tmp] = idx; 14298c2ecf20Sopenharmony_ci track->cb_dirty = true; 14308c2ecf20Sopenharmony_ci break; 14318c2ecf20Sopenharmony_ci case CB_COLOR0_ATTRIB: 14328c2ecf20Sopenharmony_ci case CB_COLOR1_ATTRIB: 14338c2ecf20Sopenharmony_ci case CB_COLOR2_ATTRIB: 14348c2ecf20Sopenharmony_ci case CB_COLOR3_ATTRIB: 14358c2ecf20Sopenharmony_ci case CB_COLOR4_ATTRIB: 14368c2ecf20Sopenharmony_ci case CB_COLOR5_ATTRIB: 14378c2ecf20Sopenharmony_ci case CB_COLOR6_ATTRIB: 14388c2ecf20Sopenharmony_ci case CB_COLOR7_ATTRIB: 14398c2ecf20Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 14408c2ecf20Sopenharmony_ci if (r) { 14418c2ecf20Sopenharmony_ci dev_warn(p->dev, "bad SET_CONTEXT_REG " 14428c2ecf20Sopenharmony_ci "0x%04X\n", reg); 14438c2ecf20Sopenharmony_ci return -EINVAL; 14448c2ecf20Sopenharmony_ci } 14458c2ecf20Sopenharmony_ci if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { 14468c2ecf20Sopenharmony_ci if (reloc->tiling_flags & RADEON_TILING_MACRO) { 14478c2ecf20Sopenharmony_ci unsigned bankw, bankh, mtaspect, tile_split; 14488c2ecf20Sopenharmony_ci 14498c2ecf20Sopenharmony_ci evergreen_tiling_fields(reloc->tiling_flags, 14508c2ecf20Sopenharmony_ci &bankw, &bankh, &mtaspect, 14518c2ecf20Sopenharmony_ci &tile_split); 14528c2ecf20Sopenharmony_ci ib[idx] |= CB_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks)); 14538c2ecf20Sopenharmony_ci ib[idx] |= CB_TILE_SPLIT(tile_split) | 14548c2ecf20Sopenharmony_ci CB_BANK_WIDTH(bankw) | 14558c2ecf20Sopenharmony_ci CB_BANK_HEIGHT(bankh) | 14568c2ecf20Sopenharmony_ci CB_MACRO_TILE_ASPECT(mtaspect); 14578c2ecf20Sopenharmony_ci } 14588c2ecf20Sopenharmony_ci } 14598c2ecf20Sopenharmony_ci tmp = ((reg - CB_COLOR0_ATTRIB) / 0x3c); 14608c2ecf20Sopenharmony_ci track->cb_color_attrib[tmp] = ib[idx]; 14618c2ecf20Sopenharmony_ci track->cb_dirty = true; 14628c2ecf20Sopenharmony_ci break; 14638c2ecf20Sopenharmony_ci case CB_COLOR8_ATTRIB: 14648c2ecf20Sopenharmony_ci case CB_COLOR9_ATTRIB: 14658c2ecf20Sopenharmony_ci case CB_COLOR10_ATTRIB: 14668c2ecf20Sopenharmony_ci case CB_COLOR11_ATTRIB: 14678c2ecf20Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 14688c2ecf20Sopenharmony_ci if (r) { 14698c2ecf20Sopenharmony_ci dev_warn(p->dev, "bad SET_CONTEXT_REG " 14708c2ecf20Sopenharmony_ci "0x%04X\n", reg); 14718c2ecf20Sopenharmony_ci return -EINVAL; 14728c2ecf20Sopenharmony_ci } 14738c2ecf20Sopenharmony_ci if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { 14748c2ecf20Sopenharmony_ci if (reloc->tiling_flags & RADEON_TILING_MACRO) { 14758c2ecf20Sopenharmony_ci unsigned bankw, bankh, mtaspect, tile_split; 14768c2ecf20Sopenharmony_ci 14778c2ecf20Sopenharmony_ci evergreen_tiling_fields(reloc->tiling_flags, 14788c2ecf20Sopenharmony_ci &bankw, &bankh, &mtaspect, 14798c2ecf20Sopenharmony_ci &tile_split); 14808c2ecf20Sopenharmony_ci ib[idx] |= CB_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks)); 14818c2ecf20Sopenharmony_ci ib[idx] |= CB_TILE_SPLIT(tile_split) | 14828c2ecf20Sopenharmony_ci CB_BANK_WIDTH(bankw) | 14838c2ecf20Sopenharmony_ci CB_BANK_HEIGHT(bankh) | 14848c2ecf20Sopenharmony_ci CB_MACRO_TILE_ASPECT(mtaspect); 14858c2ecf20Sopenharmony_ci } 14868c2ecf20Sopenharmony_ci } 14878c2ecf20Sopenharmony_ci tmp = ((reg - CB_COLOR8_ATTRIB) / 0x1c) + 8; 14888c2ecf20Sopenharmony_ci track->cb_color_attrib[tmp] = ib[idx]; 14898c2ecf20Sopenharmony_ci track->cb_dirty = true; 14908c2ecf20Sopenharmony_ci break; 14918c2ecf20Sopenharmony_ci case CB_COLOR0_FMASK: 14928c2ecf20Sopenharmony_ci case CB_COLOR1_FMASK: 14938c2ecf20Sopenharmony_ci case CB_COLOR2_FMASK: 14948c2ecf20Sopenharmony_ci case CB_COLOR3_FMASK: 14958c2ecf20Sopenharmony_ci case CB_COLOR4_FMASK: 14968c2ecf20Sopenharmony_ci case CB_COLOR5_FMASK: 14978c2ecf20Sopenharmony_ci case CB_COLOR6_FMASK: 14988c2ecf20Sopenharmony_ci case CB_COLOR7_FMASK: 14998c2ecf20Sopenharmony_ci tmp = (reg - CB_COLOR0_FMASK) / 0x3c; 15008c2ecf20Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 15018c2ecf20Sopenharmony_ci if (r) { 15028c2ecf20Sopenharmony_ci dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg); 15038c2ecf20Sopenharmony_ci return -EINVAL; 15048c2ecf20Sopenharmony_ci } 15058c2ecf20Sopenharmony_ci ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff); 15068c2ecf20Sopenharmony_ci track->cb_color_fmask_bo[tmp] = reloc->robj; 15078c2ecf20Sopenharmony_ci break; 15088c2ecf20Sopenharmony_ci case CB_COLOR0_CMASK: 15098c2ecf20Sopenharmony_ci case CB_COLOR1_CMASK: 15108c2ecf20Sopenharmony_ci case CB_COLOR2_CMASK: 15118c2ecf20Sopenharmony_ci case CB_COLOR3_CMASK: 15128c2ecf20Sopenharmony_ci case CB_COLOR4_CMASK: 15138c2ecf20Sopenharmony_ci case CB_COLOR5_CMASK: 15148c2ecf20Sopenharmony_ci case CB_COLOR6_CMASK: 15158c2ecf20Sopenharmony_ci case CB_COLOR7_CMASK: 15168c2ecf20Sopenharmony_ci tmp = (reg - CB_COLOR0_CMASK) / 0x3c; 15178c2ecf20Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 15188c2ecf20Sopenharmony_ci if (r) { 15198c2ecf20Sopenharmony_ci dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg); 15208c2ecf20Sopenharmony_ci return -EINVAL; 15218c2ecf20Sopenharmony_ci } 15228c2ecf20Sopenharmony_ci ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff); 15238c2ecf20Sopenharmony_ci track->cb_color_cmask_bo[tmp] = reloc->robj; 15248c2ecf20Sopenharmony_ci break; 15258c2ecf20Sopenharmony_ci case CB_COLOR0_FMASK_SLICE: 15268c2ecf20Sopenharmony_ci case CB_COLOR1_FMASK_SLICE: 15278c2ecf20Sopenharmony_ci case CB_COLOR2_FMASK_SLICE: 15288c2ecf20Sopenharmony_ci case CB_COLOR3_FMASK_SLICE: 15298c2ecf20Sopenharmony_ci case CB_COLOR4_FMASK_SLICE: 15308c2ecf20Sopenharmony_ci case CB_COLOR5_FMASK_SLICE: 15318c2ecf20Sopenharmony_ci case CB_COLOR6_FMASK_SLICE: 15328c2ecf20Sopenharmony_ci case CB_COLOR7_FMASK_SLICE: 15338c2ecf20Sopenharmony_ci tmp = (reg - CB_COLOR0_FMASK_SLICE) / 0x3c; 15348c2ecf20Sopenharmony_ci track->cb_color_fmask_slice[tmp] = radeon_get_ib_value(p, idx); 15358c2ecf20Sopenharmony_ci break; 15368c2ecf20Sopenharmony_ci case CB_COLOR0_CMASK_SLICE: 15378c2ecf20Sopenharmony_ci case CB_COLOR1_CMASK_SLICE: 15388c2ecf20Sopenharmony_ci case CB_COLOR2_CMASK_SLICE: 15398c2ecf20Sopenharmony_ci case CB_COLOR3_CMASK_SLICE: 15408c2ecf20Sopenharmony_ci case CB_COLOR4_CMASK_SLICE: 15418c2ecf20Sopenharmony_ci case CB_COLOR5_CMASK_SLICE: 15428c2ecf20Sopenharmony_ci case CB_COLOR6_CMASK_SLICE: 15438c2ecf20Sopenharmony_ci case CB_COLOR7_CMASK_SLICE: 15448c2ecf20Sopenharmony_ci tmp = (reg - CB_COLOR0_CMASK_SLICE) / 0x3c; 15458c2ecf20Sopenharmony_ci track->cb_color_cmask_slice[tmp] = radeon_get_ib_value(p, idx); 15468c2ecf20Sopenharmony_ci break; 15478c2ecf20Sopenharmony_ci case CB_COLOR0_BASE: 15488c2ecf20Sopenharmony_ci case CB_COLOR1_BASE: 15498c2ecf20Sopenharmony_ci case CB_COLOR2_BASE: 15508c2ecf20Sopenharmony_ci case CB_COLOR3_BASE: 15518c2ecf20Sopenharmony_ci case CB_COLOR4_BASE: 15528c2ecf20Sopenharmony_ci case CB_COLOR5_BASE: 15538c2ecf20Sopenharmony_ci case CB_COLOR6_BASE: 15548c2ecf20Sopenharmony_ci case CB_COLOR7_BASE: 15558c2ecf20Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 15568c2ecf20Sopenharmony_ci if (r) { 15578c2ecf20Sopenharmony_ci dev_warn(p->dev, "bad SET_CONTEXT_REG " 15588c2ecf20Sopenharmony_ci "0x%04X\n", reg); 15598c2ecf20Sopenharmony_ci return -EINVAL; 15608c2ecf20Sopenharmony_ci } 15618c2ecf20Sopenharmony_ci tmp = (reg - CB_COLOR0_BASE) / 0x3c; 15628c2ecf20Sopenharmony_ci track->cb_color_bo_offset[tmp] = radeon_get_ib_value(p, idx); 15638c2ecf20Sopenharmony_ci ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff); 15648c2ecf20Sopenharmony_ci track->cb_color_bo[tmp] = reloc->robj; 15658c2ecf20Sopenharmony_ci track->cb_dirty = true; 15668c2ecf20Sopenharmony_ci break; 15678c2ecf20Sopenharmony_ci case CB_COLOR8_BASE: 15688c2ecf20Sopenharmony_ci case CB_COLOR9_BASE: 15698c2ecf20Sopenharmony_ci case CB_COLOR10_BASE: 15708c2ecf20Sopenharmony_ci case CB_COLOR11_BASE: 15718c2ecf20Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 15728c2ecf20Sopenharmony_ci if (r) { 15738c2ecf20Sopenharmony_ci dev_warn(p->dev, "bad SET_CONTEXT_REG " 15748c2ecf20Sopenharmony_ci "0x%04X\n", reg); 15758c2ecf20Sopenharmony_ci return -EINVAL; 15768c2ecf20Sopenharmony_ci } 15778c2ecf20Sopenharmony_ci tmp = ((reg - CB_COLOR8_BASE) / 0x1c) + 8; 15788c2ecf20Sopenharmony_ci track->cb_color_bo_offset[tmp] = radeon_get_ib_value(p, idx); 15798c2ecf20Sopenharmony_ci ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff); 15808c2ecf20Sopenharmony_ci track->cb_color_bo[tmp] = reloc->robj; 15818c2ecf20Sopenharmony_ci track->cb_dirty = true; 15828c2ecf20Sopenharmony_ci break; 15838c2ecf20Sopenharmony_ci case DB_HTILE_DATA_BASE: 15848c2ecf20Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 15858c2ecf20Sopenharmony_ci if (r) { 15868c2ecf20Sopenharmony_ci dev_warn(p->dev, "bad SET_CONTEXT_REG " 15878c2ecf20Sopenharmony_ci "0x%04X\n", reg); 15888c2ecf20Sopenharmony_ci return -EINVAL; 15898c2ecf20Sopenharmony_ci } 15908c2ecf20Sopenharmony_ci track->htile_offset = radeon_get_ib_value(p, idx); 15918c2ecf20Sopenharmony_ci ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff); 15928c2ecf20Sopenharmony_ci track->htile_bo = reloc->robj; 15938c2ecf20Sopenharmony_ci track->db_dirty = true; 15948c2ecf20Sopenharmony_ci break; 15958c2ecf20Sopenharmony_ci case DB_HTILE_SURFACE: 15968c2ecf20Sopenharmony_ci /* 8x8 only */ 15978c2ecf20Sopenharmony_ci track->htile_surface = radeon_get_ib_value(p, idx); 15988c2ecf20Sopenharmony_ci /* force 8x8 htile width and height */ 15998c2ecf20Sopenharmony_ci ib[idx] |= 3; 16008c2ecf20Sopenharmony_ci track->db_dirty = true; 16018c2ecf20Sopenharmony_ci break; 16028c2ecf20Sopenharmony_ci case CB_IMMED0_BASE: 16038c2ecf20Sopenharmony_ci case CB_IMMED1_BASE: 16048c2ecf20Sopenharmony_ci case CB_IMMED2_BASE: 16058c2ecf20Sopenharmony_ci case CB_IMMED3_BASE: 16068c2ecf20Sopenharmony_ci case CB_IMMED4_BASE: 16078c2ecf20Sopenharmony_ci case CB_IMMED5_BASE: 16088c2ecf20Sopenharmony_ci case CB_IMMED6_BASE: 16098c2ecf20Sopenharmony_ci case CB_IMMED7_BASE: 16108c2ecf20Sopenharmony_ci case CB_IMMED8_BASE: 16118c2ecf20Sopenharmony_ci case CB_IMMED9_BASE: 16128c2ecf20Sopenharmony_ci case CB_IMMED10_BASE: 16138c2ecf20Sopenharmony_ci case CB_IMMED11_BASE: 16148c2ecf20Sopenharmony_ci case SQ_PGM_START_FS: 16158c2ecf20Sopenharmony_ci case SQ_PGM_START_ES: 16168c2ecf20Sopenharmony_ci case SQ_PGM_START_VS: 16178c2ecf20Sopenharmony_ci case SQ_PGM_START_GS: 16188c2ecf20Sopenharmony_ci case SQ_PGM_START_PS: 16198c2ecf20Sopenharmony_ci case SQ_PGM_START_HS: 16208c2ecf20Sopenharmony_ci case SQ_PGM_START_LS: 16218c2ecf20Sopenharmony_ci case SQ_CONST_MEM_BASE: 16228c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_GS_0: 16238c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_GS_1: 16248c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_GS_2: 16258c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_GS_3: 16268c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_GS_4: 16278c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_GS_5: 16288c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_GS_6: 16298c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_GS_7: 16308c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_GS_8: 16318c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_GS_9: 16328c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_GS_10: 16338c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_GS_11: 16348c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_GS_12: 16358c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_GS_13: 16368c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_GS_14: 16378c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_GS_15: 16388c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_PS_0: 16398c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_PS_1: 16408c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_PS_2: 16418c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_PS_3: 16428c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_PS_4: 16438c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_PS_5: 16448c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_PS_6: 16458c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_PS_7: 16468c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_PS_8: 16478c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_PS_9: 16488c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_PS_10: 16498c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_PS_11: 16508c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_PS_12: 16518c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_PS_13: 16528c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_PS_14: 16538c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_PS_15: 16548c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_VS_0: 16558c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_VS_1: 16568c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_VS_2: 16578c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_VS_3: 16588c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_VS_4: 16598c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_VS_5: 16608c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_VS_6: 16618c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_VS_7: 16628c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_VS_8: 16638c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_VS_9: 16648c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_VS_10: 16658c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_VS_11: 16668c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_VS_12: 16678c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_VS_13: 16688c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_VS_14: 16698c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_VS_15: 16708c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_HS_0: 16718c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_HS_1: 16728c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_HS_2: 16738c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_HS_3: 16748c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_HS_4: 16758c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_HS_5: 16768c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_HS_6: 16778c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_HS_7: 16788c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_HS_8: 16798c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_HS_9: 16808c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_HS_10: 16818c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_HS_11: 16828c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_HS_12: 16838c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_HS_13: 16848c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_HS_14: 16858c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_HS_15: 16868c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_LS_0: 16878c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_LS_1: 16888c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_LS_2: 16898c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_LS_3: 16908c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_LS_4: 16918c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_LS_5: 16928c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_LS_6: 16938c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_LS_7: 16948c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_LS_8: 16958c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_LS_9: 16968c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_LS_10: 16978c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_LS_11: 16988c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_LS_12: 16998c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_LS_13: 17008c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_LS_14: 17018c2ecf20Sopenharmony_ci case SQ_ALU_CONST_CACHE_LS_15: 17028c2ecf20Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 17038c2ecf20Sopenharmony_ci if (r) { 17048c2ecf20Sopenharmony_ci dev_warn(p->dev, "bad SET_CONTEXT_REG " 17058c2ecf20Sopenharmony_ci "0x%04X\n", reg); 17068c2ecf20Sopenharmony_ci return -EINVAL; 17078c2ecf20Sopenharmony_ci } 17088c2ecf20Sopenharmony_ci ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff); 17098c2ecf20Sopenharmony_ci break; 17108c2ecf20Sopenharmony_ci case SX_MEMORY_EXPORT_BASE: 17118c2ecf20Sopenharmony_ci if (p->rdev->family >= CHIP_CAYMAN) { 17128c2ecf20Sopenharmony_ci dev_warn(p->dev, "bad SET_CONFIG_REG " 17138c2ecf20Sopenharmony_ci "0x%04X\n", reg); 17148c2ecf20Sopenharmony_ci return -EINVAL; 17158c2ecf20Sopenharmony_ci } 17168c2ecf20Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 17178c2ecf20Sopenharmony_ci if (r) { 17188c2ecf20Sopenharmony_ci dev_warn(p->dev, "bad SET_CONFIG_REG " 17198c2ecf20Sopenharmony_ci "0x%04X\n", reg); 17208c2ecf20Sopenharmony_ci return -EINVAL; 17218c2ecf20Sopenharmony_ci } 17228c2ecf20Sopenharmony_ci ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff); 17238c2ecf20Sopenharmony_ci break; 17248c2ecf20Sopenharmony_ci case CAYMAN_SX_SCATTER_EXPORT_BASE: 17258c2ecf20Sopenharmony_ci if (p->rdev->family < CHIP_CAYMAN) { 17268c2ecf20Sopenharmony_ci dev_warn(p->dev, "bad SET_CONTEXT_REG " 17278c2ecf20Sopenharmony_ci "0x%04X\n", reg); 17288c2ecf20Sopenharmony_ci return -EINVAL; 17298c2ecf20Sopenharmony_ci } 17308c2ecf20Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 17318c2ecf20Sopenharmony_ci if (r) { 17328c2ecf20Sopenharmony_ci dev_warn(p->dev, "bad SET_CONTEXT_REG " 17338c2ecf20Sopenharmony_ci "0x%04X\n", reg); 17348c2ecf20Sopenharmony_ci return -EINVAL; 17358c2ecf20Sopenharmony_ci } 17368c2ecf20Sopenharmony_ci ib[idx] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff); 17378c2ecf20Sopenharmony_ci break; 17388c2ecf20Sopenharmony_ci case SX_MISC: 17398c2ecf20Sopenharmony_ci track->sx_misc_kill_all_prims = (radeon_get_ib_value(p, idx) & 0x1) != 0; 17408c2ecf20Sopenharmony_ci break; 17418c2ecf20Sopenharmony_ci default: 17428c2ecf20Sopenharmony_ci dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx); 17438c2ecf20Sopenharmony_ci return -EINVAL; 17448c2ecf20Sopenharmony_ci } 17458c2ecf20Sopenharmony_ci return 0; 17468c2ecf20Sopenharmony_ci} 17478c2ecf20Sopenharmony_ci 17488c2ecf20Sopenharmony_ci/** 17498c2ecf20Sopenharmony_ci * evergreen_is_safe_reg() - check if register is authorized or not 17508c2ecf20Sopenharmony_ci * @parser: parser structure holding parsing context 17518c2ecf20Sopenharmony_ci * @reg: register we are testing 17528c2ecf20Sopenharmony_ci * 17538c2ecf20Sopenharmony_ci * This function will test against reg_safe_bm and return true 17548c2ecf20Sopenharmony_ci * if register is safe or false otherwise. 17558c2ecf20Sopenharmony_ci */ 17568c2ecf20Sopenharmony_cistatic inline bool evergreen_is_safe_reg(struct radeon_cs_parser *p, u32 reg) 17578c2ecf20Sopenharmony_ci{ 17588c2ecf20Sopenharmony_ci struct evergreen_cs_track *track = p->track; 17598c2ecf20Sopenharmony_ci u32 m, i; 17608c2ecf20Sopenharmony_ci 17618c2ecf20Sopenharmony_ci i = (reg >> 7); 17628c2ecf20Sopenharmony_ci if (unlikely(i >= REG_SAFE_BM_SIZE)) { 17638c2ecf20Sopenharmony_ci return false; 17648c2ecf20Sopenharmony_ci } 17658c2ecf20Sopenharmony_ci m = 1 << ((reg >> 2) & 31); 17668c2ecf20Sopenharmony_ci if (!(track->reg_safe_bm[i] & m)) 17678c2ecf20Sopenharmony_ci return true; 17688c2ecf20Sopenharmony_ci 17698c2ecf20Sopenharmony_ci return false; 17708c2ecf20Sopenharmony_ci} 17718c2ecf20Sopenharmony_ci 17728c2ecf20Sopenharmony_cistatic int evergreen_packet3_check(struct radeon_cs_parser *p, 17738c2ecf20Sopenharmony_ci struct radeon_cs_packet *pkt) 17748c2ecf20Sopenharmony_ci{ 17758c2ecf20Sopenharmony_ci struct radeon_bo_list *reloc; 17768c2ecf20Sopenharmony_ci struct evergreen_cs_track *track; 17778c2ecf20Sopenharmony_ci uint32_t *ib; 17788c2ecf20Sopenharmony_ci unsigned idx; 17798c2ecf20Sopenharmony_ci unsigned i; 17808c2ecf20Sopenharmony_ci unsigned start_reg, end_reg, reg; 17818c2ecf20Sopenharmony_ci int r; 17828c2ecf20Sopenharmony_ci u32 idx_value; 17838c2ecf20Sopenharmony_ci 17848c2ecf20Sopenharmony_ci track = (struct evergreen_cs_track *)p->track; 17858c2ecf20Sopenharmony_ci ib = p->ib.ptr; 17868c2ecf20Sopenharmony_ci idx = pkt->idx + 1; 17878c2ecf20Sopenharmony_ci idx_value = radeon_get_ib_value(p, idx); 17888c2ecf20Sopenharmony_ci 17898c2ecf20Sopenharmony_ci switch (pkt->opcode) { 17908c2ecf20Sopenharmony_ci case PACKET3_SET_PREDICATION: 17918c2ecf20Sopenharmony_ci { 17928c2ecf20Sopenharmony_ci int pred_op; 17938c2ecf20Sopenharmony_ci int tmp; 17948c2ecf20Sopenharmony_ci uint64_t offset; 17958c2ecf20Sopenharmony_ci 17968c2ecf20Sopenharmony_ci if (pkt->count != 1) { 17978c2ecf20Sopenharmony_ci DRM_ERROR("bad SET PREDICATION\n"); 17988c2ecf20Sopenharmony_ci return -EINVAL; 17998c2ecf20Sopenharmony_ci } 18008c2ecf20Sopenharmony_ci 18018c2ecf20Sopenharmony_ci tmp = radeon_get_ib_value(p, idx + 1); 18028c2ecf20Sopenharmony_ci pred_op = (tmp >> 16) & 0x7; 18038c2ecf20Sopenharmony_ci 18048c2ecf20Sopenharmony_ci /* for the clear predicate operation */ 18058c2ecf20Sopenharmony_ci if (pred_op == 0) 18068c2ecf20Sopenharmony_ci return 0; 18078c2ecf20Sopenharmony_ci 18088c2ecf20Sopenharmony_ci if (pred_op > 2) { 18098c2ecf20Sopenharmony_ci DRM_ERROR("bad SET PREDICATION operation %d\n", pred_op); 18108c2ecf20Sopenharmony_ci return -EINVAL; 18118c2ecf20Sopenharmony_ci } 18128c2ecf20Sopenharmony_ci 18138c2ecf20Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 18148c2ecf20Sopenharmony_ci if (r) { 18158c2ecf20Sopenharmony_ci DRM_ERROR("bad SET PREDICATION\n"); 18168c2ecf20Sopenharmony_ci return -EINVAL; 18178c2ecf20Sopenharmony_ci } 18188c2ecf20Sopenharmony_ci 18198c2ecf20Sopenharmony_ci offset = reloc->gpu_offset + 18208c2ecf20Sopenharmony_ci (idx_value & 0xfffffff0) + 18218c2ecf20Sopenharmony_ci ((u64)(tmp & 0xff) << 32); 18228c2ecf20Sopenharmony_ci 18238c2ecf20Sopenharmony_ci ib[idx + 0] = offset; 18248c2ecf20Sopenharmony_ci ib[idx + 1] = (tmp & 0xffffff00) | (upper_32_bits(offset) & 0xff); 18258c2ecf20Sopenharmony_ci } 18268c2ecf20Sopenharmony_ci break; 18278c2ecf20Sopenharmony_ci case PACKET3_CONTEXT_CONTROL: 18288c2ecf20Sopenharmony_ci if (pkt->count != 1) { 18298c2ecf20Sopenharmony_ci DRM_ERROR("bad CONTEXT_CONTROL\n"); 18308c2ecf20Sopenharmony_ci return -EINVAL; 18318c2ecf20Sopenharmony_ci } 18328c2ecf20Sopenharmony_ci break; 18338c2ecf20Sopenharmony_ci case PACKET3_INDEX_TYPE: 18348c2ecf20Sopenharmony_ci case PACKET3_NUM_INSTANCES: 18358c2ecf20Sopenharmony_ci case PACKET3_CLEAR_STATE: 18368c2ecf20Sopenharmony_ci if (pkt->count) { 18378c2ecf20Sopenharmony_ci DRM_ERROR("bad INDEX_TYPE/NUM_INSTANCES/CLEAR_STATE\n"); 18388c2ecf20Sopenharmony_ci return -EINVAL; 18398c2ecf20Sopenharmony_ci } 18408c2ecf20Sopenharmony_ci break; 18418c2ecf20Sopenharmony_ci case CAYMAN_PACKET3_DEALLOC_STATE: 18428c2ecf20Sopenharmony_ci if (p->rdev->family < CHIP_CAYMAN) { 18438c2ecf20Sopenharmony_ci DRM_ERROR("bad PACKET3_DEALLOC_STATE\n"); 18448c2ecf20Sopenharmony_ci return -EINVAL; 18458c2ecf20Sopenharmony_ci } 18468c2ecf20Sopenharmony_ci if (pkt->count) { 18478c2ecf20Sopenharmony_ci DRM_ERROR("bad INDEX_TYPE/NUM_INSTANCES/CLEAR_STATE\n"); 18488c2ecf20Sopenharmony_ci return -EINVAL; 18498c2ecf20Sopenharmony_ci } 18508c2ecf20Sopenharmony_ci break; 18518c2ecf20Sopenharmony_ci case PACKET3_INDEX_BASE: 18528c2ecf20Sopenharmony_ci { 18538c2ecf20Sopenharmony_ci uint64_t offset; 18548c2ecf20Sopenharmony_ci 18558c2ecf20Sopenharmony_ci if (pkt->count != 1) { 18568c2ecf20Sopenharmony_ci DRM_ERROR("bad INDEX_BASE\n"); 18578c2ecf20Sopenharmony_ci return -EINVAL; 18588c2ecf20Sopenharmony_ci } 18598c2ecf20Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 18608c2ecf20Sopenharmony_ci if (r) { 18618c2ecf20Sopenharmony_ci DRM_ERROR("bad INDEX_BASE\n"); 18628c2ecf20Sopenharmony_ci return -EINVAL; 18638c2ecf20Sopenharmony_ci } 18648c2ecf20Sopenharmony_ci 18658c2ecf20Sopenharmony_ci offset = reloc->gpu_offset + 18668c2ecf20Sopenharmony_ci idx_value + 18678c2ecf20Sopenharmony_ci ((u64)(radeon_get_ib_value(p, idx+1) & 0xff) << 32); 18688c2ecf20Sopenharmony_ci 18698c2ecf20Sopenharmony_ci ib[idx+0] = offset; 18708c2ecf20Sopenharmony_ci ib[idx+1] = upper_32_bits(offset) & 0xff; 18718c2ecf20Sopenharmony_ci 18728c2ecf20Sopenharmony_ci r = evergreen_cs_track_check(p); 18738c2ecf20Sopenharmony_ci if (r) { 18748c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__); 18758c2ecf20Sopenharmony_ci return r; 18768c2ecf20Sopenharmony_ci } 18778c2ecf20Sopenharmony_ci break; 18788c2ecf20Sopenharmony_ci } 18798c2ecf20Sopenharmony_ci case PACKET3_INDEX_BUFFER_SIZE: 18808c2ecf20Sopenharmony_ci { 18818c2ecf20Sopenharmony_ci if (pkt->count != 0) { 18828c2ecf20Sopenharmony_ci DRM_ERROR("bad INDEX_BUFFER_SIZE\n"); 18838c2ecf20Sopenharmony_ci return -EINVAL; 18848c2ecf20Sopenharmony_ci } 18858c2ecf20Sopenharmony_ci break; 18868c2ecf20Sopenharmony_ci } 18878c2ecf20Sopenharmony_ci case PACKET3_DRAW_INDEX: 18888c2ecf20Sopenharmony_ci { 18898c2ecf20Sopenharmony_ci uint64_t offset; 18908c2ecf20Sopenharmony_ci if (pkt->count != 3) { 18918c2ecf20Sopenharmony_ci DRM_ERROR("bad DRAW_INDEX\n"); 18928c2ecf20Sopenharmony_ci return -EINVAL; 18938c2ecf20Sopenharmony_ci } 18948c2ecf20Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 18958c2ecf20Sopenharmony_ci if (r) { 18968c2ecf20Sopenharmony_ci DRM_ERROR("bad DRAW_INDEX\n"); 18978c2ecf20Sopenharmony_ci return -EINVAL; 18988c2ecf20Sopenharmony_ci } 18998c2ecf20Sopenharmony_ci 19008c2ecf20Sopenharmony_ci offset = reloc->gpu_offset + 19018c2ecf20Sopenharmony_ci idx_value + 19028c2ecf20Sopenharmony_ci ((u64)(radeon_get_ib_value(p, idx+1) & 0xff) << 32); 19038c2ecf20Sopenharmony_ci 19048c2ecf20Sopenharmony_ci ib[idx+0] = offset; 19058c2ecf20Sopenharmony_ci ib[idx+1] = upper_32_bits(offset) & 0xff; 19068c2ecf20Sopenharmony_ci 19078c2ecf20Sopenharmony_ci r = evergreen_cs_track_check(p); 19088c2ecf20Sopenharmony_ci if (r) { 19098c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__); 19108c2ecf20Sopenharmony_ci return r; 19118c2ecf20Sopenharmony_ci } 19128c2ecf20Sopenharmony_ci break; 19138c2ecf20Sopenharmony_ci } 19148c2ecf20Sopenharmony_ci case PACKET3_DRAW_INDEX_2: 19158c2ecf20Sopenharmony_ci { 19168c2ecf20Sopenharmony_ci uint64_t offset; 19178c2ecf20Sopenharmony_ci 19188c2ecf20Sopenharmony_ci if (pkt->count != 4) { 19198c2ecf20Sopenharmony_ci DRM_ERROR("bad DRAW_INDEX_2\n"); 19208c2ecf20Sopenharmony_ci return -EINVAL; 19218c2ecf20Sopenharmony_ci } 19228c2ecf20Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 19238c2ecf20Sopenharmony_ci if (r) { 19248c2ecf20Sopenharmony_ci DRM_ERROR("bad DRAW_INDEX_2\n"); 19258c2ecf20Sopenharmony_ci return -EINVAL; 19268c2ecf20Sopenharmony_ci } 19278c2ecf20Sopenharmony_ci 19288c2ecf20Sopenharmony_ci offset = reloc->gpu_offset + 19298c2ecf20Sopenharmony_ci radeon_get_ib_value(p, idx+1) + 19308c2ecf20Sopenharmony_ci ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32); 19318c2ecf20Sopenharmony_ci 19328c2ecf20Sopenharmony_ci ib[idx+1] = offset; 19338c2ecf20Sopenharmony_ci ib[idx+2] = upper_32_bits(offset) & 0xff; 19348c2ecf20Sopenharmony_ci 19358c2ecf20Sopenharmony_ci r = evergreen_cs_track_check(p); 19368c2ecf20Sopenharmony_ci if (r) { 19378c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__); 19388c2ecf20Sopenharmony_ci return r; 19398c2ecf20Sopenharmony_ci } 19408c2ecf20Sopenharmony_ci break; 19418c2ecf20Sopenharmony_ci } 19428c2ecf20Sopenharmony_ci case PACKET3_DRAW_INDEX_AUTO: 19438c2ecf20Sopenharmony_ci if (pkt->count != 1) { 19448c2ecf20Sopenharmony_ci DRM_ERROR("bad DRAW_INDEX_AUTO\n"); 19458c2ecf20Sopenharmony_ci return -EINVAL; 19468c2ecf20Sopenharmony_ci } 19478c2ecf20Sopenharmony_ci r = evergreen_cs_track_check(p); 19488c2ecf20Sopenharmony_ci if (r) { 19498c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d invalid cmd stream %d\n", __func__, __LINE__, idx); 19508c2ecf20Sopenharmony_ci return r; 19518c2ecf20Sopenharmony_ci } 19528c2ecf20Sopenharmony_ci break; 19538c2ecf20Sopenharmony_ci case PACKET3_DRAW_INDEX_MULTI_AUTO: 19548c2ecf20Sopenharmony_ci if (pkt->count != 2) { 19558c2ecf20Sopenharmony_ci DRM_ERROR("bad DRAW_INDEX_MULTI_AUTO\n"); 19568c2ecf20Sopenharmony_ci return -EINVAL; 19578c2ecf20Sopenharmony_ci } 19588c2ecf20Sopenharmony_ci r = evergreen_cs_track_check(p); 19598c2ecf20Sopenharmony_ci if (r) { 19608c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d invalid cmd stream %d\n", __func__, __LINE__, idx); 19618c2ecf20Sopenharmony_ci return r; 19628c2ecf20Sopenharmony_ci } 19638c2ecf20Sopenharmony_ci break; 19648c2ecf20Sopenharmony_ci case PACKET3_DRAW_INDEX_IMMD: 19658c2ecf20Sopenharmony_ci if (pkt->count < 2) { 19668c2ecf20Sopenharmony_ci DRM_ERROR("bad DRAW_INDEX_IMMD\n"); 19678c2ecf20Sopenharmony_ci return -EINVAL; 19688c2ecf20Sopenharmony_ci } 19698c2ecf20Sopenharmony_ci r = evergreen_cs_track_check(p); 19708c2ecf20Sopenharmony_ci if (r) { 19718c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__); 19728c2ecf20Sopenharmony_ci return r; 19738c2ecf20Sopenharmony_ci } 19748c2ecf20Sopenharmony_ci break; 19758c2ecf20Sopenharmony_ci case PACKET3_DRAW_INDEX_OFFSET: 19768c2ecf20Sopenharmony_ci if (pkt->count != 2) { 19778c2ecf20Sopenharmony_ci DRM_ERROR("bad DRAW_INDEX_OFFSET\n"); 19788c2ecf20Sopenharmony_ci return -EINVAL; 19798c2ecf20Sopenharmony_ci } 19808c2ecf20Sopenharmony_ci r = evergreen_cs_track_check(p); 19818c2ecf20Sopenharmony_ci if (r) { 19828c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__); 19838c2ecf20Sopenharmony_ci return r; 19848c2ecf20Sopenharmony_ci } 19858c2ecf20Sopenharmony_ci break; 19868c2ecf20Sopenharmony_ci case PACKET3_DRAW_INDEX_OFFSET_2: 19878c2ecf20Sopenharmony_ci if (pkt->count != 3) { 19888c2ecf20Sopenharmony_ci DRM_ERROR("bad DRAW_INDEX_OFFSET_2\n"); 19898c2ecf20Sopenharmony_ci return -EINVAL; 19908c2ecf20Sopenharmony_ci } 19918c2ecf20Sopenharmony_ci r = evergreen_cs_track_check(p); 19928c2ecf20Sopenharmony_ci if (r) { 19938c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__); 19948c2ecf20Sopenharmony_ci return r; 19958c2ecf20Sopenharmony_ci } 19968c2ecf20Sopenharmony_ci break; 19978c2ecf20Sopenharmony_ci case PACKET3_SET_BASE: 19988c2ecf20Sopenharmony_ci { 19998c2ecf20Sopenharmony_ci /* 20008c2ecf20Sopenharmony_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. 20018c2ecf20Sopenharmony_ci 2 BASE_INDEX Bits [3:0] BASE_INDEX - Base Index specifies which base address is specified in the last two DWs. 20028c2ecf20Sopenharmony_ci 0001: DX11 Draw_Index_Indirect Patch Table Base: Base address for Draw_Index_Indirect data. 20038c2ecf20Sopenharmony_ci 3 ADDRESS_LO Bits [31:3] - Lower bits of QWORD-Aligned Address. Bits [2:0] - Reserved 20048c2ecf20Sopenharmony_ci 4 ADDRESS_HI Bits [31:8] - Reserved. Bits [7:0] - Upper bits of Address [47:32] 20058c2ecf20Sopenharmony_ci */ 20068c2ecf20Sopenharmony_ci if (pkt->count != 2) { 20078c2ecf20Sopenharmony_ci DRM_ERROR("bad SET_BASE\n"); 20088c2ecf20Sopenharmony_ci return -EINVAL; 20098c2ecf20Sopenharmony_ci } 20108c2ecf20Sopenharmony_ci 20118c2ecf20Sopenharmony_ci /* currently only supporting setting indirect draw buffer base address */ 20128c2ecf20Sopenharmony_ci if (idx_value != 1) { 20138c2ecf20Sopenharmony_ci DRM_ERROR("bad SET_BASE\n"); 20148c2ecf20Sopenharmony_ci return -EINVAL; 20158c2ecf20Sopenharmony_ci } 20168c2ecf20Sopenharmony_ci 20178c2ecf20Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 20188c2ecf20Sopenharmony_ci if (r) { 20198c2ecf20Sopenharmony_ci DRM_ERROR("bad SET_BASE\n"); 20208c2ecf20Sopenharmony_ci return -EINVAL; 20218c2ecf20Sopenharmony_ci } 20228c2ecf20Sopenharmony_ci 20238c2ecf20Sopenharmony_ci track->indirect_draw_buffer_size = radeon_bo_size(reloc->robj); 20248c2ecf20Sopenharmony_ci 20258c2ecf20Sopenharmony_ci ib[idx+1] = reloc->gpu_offset; 20268c2ecf20Sopenharmony_ci ib[idx+2] = upper_32_bits(reloc->gpu_offset) & 0xff; 20278c2ecf20Sopenharmony_ci 20288c2ecf20Sopenharmony_ci break; 20298c2ecf20Sopenharmony_ci } 20308c2ecf20Sopenharmony_ci case PACKET3_DRAW_INDIRECT: 20318c2ecf20Sopenharmony_ci case PACKET3_DRAW_INDEX_INDIRECT: 20328c2ecf20Sopenharmony_ci { 20338c2ecf20Sopenharmony_ci u64 size = pkt->opcode == PACKET3_DRAW_INDIRECT ? 16 : 20; 20348c2ecf20Sopenharmony_ci 20358c2ecf20Sopenharmony_ci /* 20368c2ecf20Sopenharmony_ci DW 1 HEADER 20378c2ecf20Sopenharmony_ci 2 DATA_OFFSET Bits [31:0] + byte aligned offset where the required data structure starts. Bits 1:0 are zero 20388c2ecf20Sopenharmony_ci 3 DRAW_INITIATOR Draw Initiator Register. Written to the VGT_DRAW_INITIATOR register for the assigned context 20398c2ecf20Sopenharmony_ci */ 20408c2ecf20Sopenharmony_ci if (pkt->count != 1) { 20418c2ecf20Sopenharmony_ci DRM_ERROR("bad DRAW_INDIRECT\n"); 20428c2ecf20Sopenharmony_ci return -EINVAL; 20438c2ecf20Sopenharmony_ci } 20448c2ecf20Sopenharmony_ci 20458c2ecf20Sopenharmony_ci if (idx_value + size > track->indirect_draw_buffer_size) { 20468c2ecf20Sopenharmony_ci dev_warn(p->dev, "DRAW_INDIRECT buffer too small %u + %llu > %lu\n", 20478c2ecf20Sopenharmony_ci idx_value, size, track->indirect_draw_buffer_size); 20488c2ecf20Sopenharmony_ci return -EINVAL; 20498c2ecf20Sopenharmony_ci } 20508c2ecf20Sopenharmony_ci 20518c2ecf20Sopenharmony_ci r = evergreen_cs_track_check(p); 20528c2ecf20Sopenharmony_ci if (r) { 20538c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__); 20548c2ecf20Sopenharmony_ci return r; 20558c2ecf20Sopenharmony_ci } 20568c2ecf20Sopenharmony_ci break; 20578c2ecf20Sopenharmony_ci } 20588c2ecf20Sopenharmony_ci case PACKET3_DISPATCH_DIRECT: 20598c2ecf20Sopenharmony_ci if (pkt->count != 3) { 20608c2ecf20Sopenharmony_ci DRM_ERROR("bad DISPATCH_DIRECT\n"); 20618c2ecf20Sopenharmony_ci return -EINVAL; 20628c2ecf20Sopenharmony_ci } 20638c2ecf20Sopenharmony_ci r = evergreen_cs_track_check(p); 20648c2ecf20Sopenharmony_ci if (r) { 20658c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d invalid cmd stream %d\n", __func__, __LINE__, idx); 20668c2ecf20Sopenharmony_ci return r; 20678c2ecf20Sopenharmony_ci } 20688c2ecf20Sopenharmony_ci break; 20698c2ecf20Sopenharmony_ci case PACKET3_DISPATCH_INDIRECT: 20708c2ecf20Sopenharmony_ci if (pkt->count != 1) { 20718c2ecf20Sopenharmony_ci DRM_ERROR("bad DISPATCH_INDIRECT\n"); 20728c2ecf20Sopenharmony_ci return -EINVAL; 20738c2ecf20Sopenharmony_ci } 20748c2ecf20Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 20758c2ecf20Sopenharmony_ci if (r) { 20768c2ecf20Sopenharmony_ci DRM_ERROR("bad DISPATCH_INDIRECT\n"); 20778c2ecf20Sopenharmony_ci return -EINVAL; 20788c2ecf20Sopenharmony_ci } 20798c2ecf20Sopenharmony_ci ib[idx+0] = idx_value + (u32)(reloc->gpu_offset & 0xffffffff); 20808c2ecf20Sopenharmony_ci r = evergreen_cs_track_check(p); 20818c2ecf20Sopenharmony_ci if (r) { 20828c2ecf20Sopenharmony_ci dev_warn(p->dev, "%s:%d invalid cmd stream\n", __func__, __LINE__); 20838c2ecf20Sopenharmony_ci return r; 20848c2ecf20Sopenharmony_ci } 20858c2ecf20Sopenharmony_ci break; 20868c2ecf20Sopenharmony_ci case PACKET3_WAIT_REG_MEM: 20878c2ecf20Sopenharmony_ci if (pkt->count != 5) { 20888c2ecf20Sopenharmony_ci DRM_ERROR("bad WAIT_REG_MEM\n"); 20898c2ecf20Sopenharmony_ci return -EINVAL; 20908c2ecf20Sopenharmony_ci } 20918c2ecf20Sopenharmony_ci /* bit 4 is reg (0) or mem (1) */ 20928c2ecf20Sopenharmony_ci if (idx_value & 0x10) { 20938c2ecf20Sopenharmony_ci uint64_t offset; 20948c2ecf20Sopenharmony_ci 20958c2ecf20Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 20968c2ecf20Sopenharmony_ci if (r) { 20978c2ecf20Sopenharmony_ci DRM_ERROR("bad WAIT_REG_MEM\n"); 20988c2ecf20Sopenharmony_ci return -EINVAL; 20998c2ecf20Sopenharmony_ci } 21008c2ecf20Sopenharmony_ci 21018c2ecf20Sopenharmony_ci offset = reloc->gpu_offset + 21028c2ecf20Sopenharmony_ci (radeon_get_ib_value(p, idx+1) & 0xfffffffc) + 21038c2ecf20Sopenharmony_ci ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32); 21048c2ecf20Sopenharmony_ci 21058c2ecf20Sopenharmony_ci ib[idx+1] = (ib[idx+1] & 0x3) | (offset & 0xfffffffc); 21068c2ecf20Sopenharmony_ci ib[idx+2] = upper_32_bits(offset) & 0xff; 21078c2ecf20Sopenharmony_ci } else if (idx_value & 0x100) { 21088c2ecf20Sopenharmony_ci DRM_ERROR("cannot use PFP on REG wait\n"); 21098c2ecf20Sopenharmony_ci return -EINVAL; 21108c2ecf20Sopenharmony_ci } 21118c2ecf20Sopenharmony_ci break; 21128c2ecf20Sopenharmony_ci case PACKET3_CP_DMA: 21138c2ecf20Sopenharmony_ci { 21148c2ecf20Sopenharmony_ci u32 command, size, info; 21158c2ecf20Sopenharmony_ci u64 offset, tmp; 21168c2ecf20Sopenharmony_ci if (pkt->count != 4) { 21178c2ecf20Sopenharmony_ci DRM_ERROR("bad CP DMA\n"); 21188c2ecf20Sopenharmony_ci return -EINVAL; 21198c2ecf20Sopenharmony_ci } 21208c2ecf20Sopenharmony_ci command = radeon_get_ib_value(p, idx+4); 21218c2ecf20Sopenharmony_ci size = command & 0x1fffff; 21228c2ecf20Sopenharmony_ci info = radeon_get_ib_value(p, idx+1); 21238c2ecf20Sopenharmony_ci if ((((info & 0x60000000) >> 29) != 0) || /* src = GDS or DATA */ 21248c2ecf20Sopenharmony_ci (((info & 0x00300000) >> 20) != 0) || /* dst = GDS */ 21258c2ecf20Sopenharmony_ci ((((info & 0x00300000) >> 20) == 0) && 21268c2ecf20Sopenharmony_ci (command & PACKET3_CP_DMA_CMD_DAS)) || /* dst = register */ 21278c2ecf20Sopenharmony_ci ((((info & 0x60000000) >> 29) == 0) && 21288c2ecf20Sopenharmony_ci (command & PACKET3_CP_DMA_CMD_SAS))) { /* src = register */ 21298c2ecf20Sopenharmony_ci /* non mem to mem copies requires dw aligned count */ 21308c2ecf20Sopenharmony_ci if (size % 4) { 21318c2ecf20Sopenharmony_ci DRM_ERROR("CP DMA command requires dw count alignment\n"); 21328c2ecf20Sopenharmony_ci return -EINVAL; 21338c2ecf20Sopenharmony_ci } 21348c2ecf20Sopenharmony_ci } 21358c2ecf20Sopenharmony_ci if (command & PACKET3_CP_DMA_CMD_SAS) { 21368c2ecf20Sopenharmony_ci /* src address space is register */ 21378c2ecf20Sopenharmony_ci /* GDS is ok */ 21388c2ecf20Sopenharmony_ci if (((info & 0x60000000) >> 29) != 1) { 21398c2ecf20Sopenharmony_ci DRM_ERROR("CP DMA SAS not supported\n"); 21408c2ecf20Sopenharmony_ci return -EINVAL; 21418c2ecf20Sopenharmony_ci } 21428c2ecf20Sopenharmony_ci } else { 21438c2ecf20Sopenharmony_ci if (command & PACKET3_CP_DMA_CMD_SAIC) { 21448c2ecf20Sopenharmony_ci DRM_ERROR("CP DMA SAIC only supported for registers\n"); 21458c2ecf20Sopenharmony_ci return -EINVAL; 21468c2ecf20Sopenharmony_ci } 21478c2ecf20Sopenharmony_ci /* src address space is memory */ 21488c2ecf20Sopenharmony_ci if (((info & 0x60000000) >> 29) == 0) { 21498c2ecf20Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 21508c2ecf20Sopenharmony_ci if (r) { 21518c2ecf20Sopenharmony_ci DRM_ERROR("bad CP DMA SRC\n"); 21528c2ecf20Sopenharmony_ci return -EINVAL; 21538c2ecf20Sopenharmony_ci } 21548c2ecf20Sopenharmony_ci 21558c2ecf20Sopenharmony_ci tmp = radeon_get_ib_value(p, idx) + 21568c2ecf20Sopenharmony_ci ((u64)(radeon_get_ib_value(p, idx+1) & 0xff) << 32); 21578c2ecf20Sopenharmony_ci 21588c2ecf20Sopenharmony_ci offset = reloc->gpu_offset + tmp; 21598c2ecf20Sopenharmony_ci 21608c2ecf20Sopenharmony_ci if ((tmp + size) > radeon_bo_size(reloc->robj)) { 21618c2ecf20Sopenharmony_ci dev_warn(p->dev, "CP DMA src buffer too small (%llu %lu)\n", 21628c2ecf20Sopenharmony_ci tmp + size, radeon_bo_size(reloc->robj)); 21638c2ecf20Sopenharmony_ci return -EINVAL; 21648c2ecf20Sopenharmony_ci } 21658c2ecf20Sopenharmony_ci 21668c2ecf20Sopenharmony_ci ib[idx] = offset; 21678c2ecf20Sopenharmony_ci ib[idx+1] = (ib[idx+1] & 0xffffff00) | (upper_32_bits(offset) & 0xff); 21688c2ecf20Sopenharmony_ci } else if (((info & 0x60000000) >> 29) != 2) { 21698c2ecf20Sopenharmony_ci DRM_ERROR("bad CP DMA SRC_SEL\n"); 21708c2ecf20Sopenharmony_ci return -EINVAL; 21718c2ecf20Sopenharmony_ci } 21728c2ecf20Sopenharmony_ci } 21738c2ecf20Sopenharmony_ci if (command & PACKET3_CP_DMA_CMD_DAS) { 21748c2ecf20Sopenharmony_ci /* dst address space is register */ 21758c2ecf20Sopenharmony_ci /* GDS is ok */ 21768c2ecf20Sopenharmony_ci if (((info & 0x00300000) >> 20) != 1) { 21778c2ecf20Sopenharmony_ci DRM_ERROR("CP DMA DAS not supported\n"); 21788c2ecf20Sopenharmony_ci return -EINVAL; 21798c2ecf20Sopenharmony_ci } 21808c2ecf20Sopenharmony_ci } else { 21818c2ecf20Sopenharmony_ci /* dst address space is memory */ 21828c2ecf20Sopenharmony_ci if (command & PACKET3_CP_DMA_CMD_DAIC) { 21838c2ecf20Sopenharmony_ci DRM_ERROR("CP DMA DAIC only supported for registers\n"); 21848c2ecf20Sopenharmony_ci return -EINVAL; 21858c2ecf20Sopenharmony_ci } 21868c2ecf20Sopenharmony_ci if (((info & 0x00300000) >> 20) == 0) { 21878c2ecf20Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 21888c2ecf20Sopenharmony_ci if (r) { 21898c2ecf20Sopenharmony_ci DRM_ERROR("bad CP DMA DST\n"); 21908c2ecf20Sopenharmony_ci return -EINVAL; 21918c2ecf20Sopenharmony_ci } 21928c2ecf20Sopenharmony_ci 21938c2ecf20Sopenharmony_ci tmp = radeon_get_ib_value(p, idx+2) + 21948c2ecf20Sopenharmony_ci ((u64)(radeon_get_ib_value(p, idx+3) & 0xff) << 32); 21958c2ecf20Sopenharmony_ci 21968c2ecf20Sopenharmony_ci offset = reloc->gpu_offset + tmp; 21978c2ecf20Sopenharmony_ci 21988c2ecf20Sopenharmony_ci if ((tmp + size) > radeon_bo_size(reloc->robj)) { 21998c2ecf20Sopenharmony_ci dev_warn(p->dev, "CP DMA dst buffer too small (%llu %lu)\n", 22008c2ecf20Sopenharmony_ci tmp + size, radeon_bo_size(reloc->robj)); 22018c2ecf20Sopenharmony_ci return -EINVAL; 22028c2ecf20Sopenharmony_ci } 22038c2ecf20Sopenharmony_ci 22048c2ecf20Sopenharmony_ci ib[idx+2] = offset; 22058c2ecf20Sopenharmony_ci ib[idx+3] = upper_32_bits(offset) & 0xff; 22068c2ecf20Sopenharmony_ci } else { 22078c2ecf20Sopenharmony_ci DRM_ERROR("bad CP DMA DST_SEL\n"); 22088c2ecf20Sopenharmony_ci return -EINVAL; 22098c2ecf20Sopenharmony_ci } 22108c2ecf20Sopenharmony_ci } 22118c2ecf20Sopenharmony_ci break; 22128c2ecf20Sopenharmony_ci } 22138c2ecf20Sopenharmony_ci case PACKET3_PFP_SYNC_ME: 22148c2ecf20Sopenharmony_ci if (pkt->count) { 22158c2ecf20Sopenharmony_ci DRM_ERROR("bad PFP_SYNC_ME\n"); 22168c2ecf20Sopenharmony_ci return -EINVAL; 22178c2ecf20Sopenharmony_ci } 22188c2ecf20Sopenharmony_ci break; 22198c2ecf20Sopenharmony_ci case PACKET3_SURFACE_SYNC: 22208c2ecf20Sopenharmony_ci if (pkt->count != 3) { 22218c2ecf20Sopenharmony_ci DRM_ERROR("bad SURFACE_SYNC\n"); 22228c2ecf20Sopenharmony_ci return -EINVAL; 22238c2ecf20Sopenharmony_ci } 22248c2ecf20Sopenharmony_ci /* 0xffffffff/0x0 is flush all cache flag */ 22258c2ecf20Sopenharmony_ci if (radeon_get_ib_value(p, idx + 1) != 0xffffffff || 22268c2ecf20Sopenharmony_ci radeon_get_ib_value(p, idx + 2) != 0) { 22278c2ecf20Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 22288c2ecf20Sopenharmony_ci if (r) { 22298c2ecf20Sopenharmony_ci DRM_ERROR("bad SURFACE_SYNC\n"); 22308c2ecf20Sopenharmony_ci return -EINVAL; 22318c2ecf20Sopenharmony_ci } 22328c2ecf20Sopenharmony_ci ib[idx+2] += (u32)((reloc->gpu_offset >> 8) & 0xffffffff); 22338c2ecf20Sopenharmony_ci } 22348c2ecf20Sopenharmony_ci break; 22358c2ecf20Sopenharmony_ci case PACKET3_EVENT_WRITE: 22368c2ecf20Sopenharmony_ci if (pkt->count != 2 && pkt->count != 0) { 22378c2ecf20Sopenharmony_ci DRM_ERROR("bad EVENT_WRITE\n"); 22388c2ecf20Sopenharmony_ci return -EINVAL; 22398c2ecf20Sopenharmony_ci } 22408c2ecf20Sopenharmony_ci if (pkt->count) { 22418c2ecf20Sopenharmony_ci uint64_t offset; 22428c2ecf20Sopenharmony_ci 22438c2ecf20Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 22448c2ecf20Sopenharmony_ci if (r) { 22458c2ecf20Sopenharmony_ci DRM_ERROR("bad EVENT_WRITE\n"); 22468c2ecf20Sopenharmony_ci return -EINVAL; 22478c2ecf20Sopenharmony_ci } 22488c2ecf20Sopenharmony_ci offset = reloc->gpu_offset + 22498c2ecf20Sopenharmony_ci (radeon_get_ib_value(p, idx+1) & 0xfffffff8) + 22508c2ecf20Sopenharmony_ci ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32); 22518c2ecf20Sopenharmony_ci 22528c2ecf20Sopenharmony_ci ib[idx+1] = offset & 0xfffffff8; 22538c2ecf20Sopenharmony_ci ib[idx+2] = upper_32_bits(offset) & 0xff; 22548c2ecf20Sopenharmony_ci } 22558c2ecf20Sopenharmony_ci break; 22568c2ecf20Sopenharmony_ci case PACKET3_EVENT_WRITE_EOP: 22578c2ecf20Sopenharmony_ci { 22588c2ecf20Sopenharmony_ci uint64_t offset; 22598c2ecf20Sopenharmony_ci 22608c2ecf20Sopenharmony_ci if (pkt->count != 4) { 22618c2ecf20Sopenharmony_ci DRM_ERROR("bad EVENT_WRITE_EOP\n"); 22628c2ecf20Sopenharmony_ci return -EINVAL; 22638c2ecf20Sopenharmony_ci } 22648c2ecf20Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 22658c2ecf20Sopenharmony_ci if (r) { 22668c2ecf20Sopenharmony_ci DRM_ERROR("bad EVENT_WRITE_EOP\n"); 22678c2ecf20Sopenharmony_ci return -EINVAL; 22688c2ecf20Sopenharmony_ci } 22698c2ecf20Sopenharmony_ci 22708c2ecf20Sopenharmony_ci offset = reloc->gpu_offset + 22718c2ecf20Sopenharmony_ci (radeon_get_ib_value(p, idx+1) & 0xfffffffc) + 22728c2ecf20Sopenharmony_ci ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32); 22738c2ecf20Sopenharmony_ci 22748c2ecf20Sopenharmony_ci ib[idx+1] = offset & 0xfffffffc; 22758c2ecf20Sopenharmony_ci ib[idx+2] = (ib[idx+2] & 0xffffff00) | (upper_32_bits(offset) & 0xff); 22768c2ecf20Sopenharmony_ci break; 22778c2ecf20Sopenharmony_ci } 22788c2ecf20Sopenharmony_ci case PACKET3_EVENT_WRITE_EOS: 22798c2ecf20Sopenharmony_ci { 22808c2ecf20Sopenharmony_ci uint64_t offset; 22818c2ecf20Sopenharmony_ci 22828c2ecf20Sopenharmony_ci if (pkt->count != 3) { 22838c2ecf20Sopenharmony_ci DRM_ERROR("bad EVENT_WRITE_EOS\n"); 22848c2ecf20Sopenharmony_ci return -EINVAL; 22858c2ecf20Sopenharmony_ci } 22868c2ecf20Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 22878c2ecf20Sopenharmony_ci if (r) { 22888c2ecf20Sopenharmony_ci DRM_ERROR("bad EVENT_WRITE_EOS\n"); 22898c2ecf20Sopenharmony_ci return -EINVAL; 22908c2ecf20Sopenharmony_ci } 22918c2ecf20Sopenharmony_ci 22928c2ecf20Sopenharmony_ci offset = reloc->gpu_offset + 22938c2ecf20Sopenharmony_ci (radeon_get_ib_value(p, idx+1) & 0xfffffffc) + 22948c2ecf20Sopenharmony_ci ((u64)(radeon_get_ib_value(p, idx+2) & 0xff) << 32); 22958c2ecf20Sopenharmony_ci 22968c2ecf20Sopenharmony_ci ib[idx+1] = offset & 0xfffffffc; 22978c2ecf20Sopenharmony_ci ib[idx+2] = (ib[idx+2] & 0xffffff00) | (upper_32_bits(offset) & 0xff); 22988c2ecf20Sopenharmony_ci break; 22998c2ecf20Sopenharmony_ci } 23008c2ecf20Sopenharmony_ci case PACKET3_SET_CONFIG_REG: 23018c2ecf20Sopenharmony_ci start_reg = (idx_value << 2) + PACKET3_SET_CONFIG_REG_START; 23028c2ecf20Sopenharmony_ci end_reg = 4 * pkt->count + start_reg - 4; 23038c2ecf20Sopenharmony_ci if ((start_reg < PACKET3_SET_CONFIG_REG_START) || 23048c2ecf20Sopenharmony_ci (start_reg >= PACKET3_SET_CONFIG_REG_END) || 23058c2ecf20Sopenharmony_ci (end_reg >= PACKET3_SET_CONFIG_REG_END)) { 23068c2ecf20Sopenharmony_ci DRM_ERROR("bad PACKET3_SET_CONFIG_REG\n"); 23078c2ecf20Sopenharmony_ci return -EINVAL; 23088c2ecf20Sopenharmony_ci } 23098c2ecf20Sopenharmony_ci for (reg = start_reg, idx++; reg <= end_reg; reg += 4, idx++) { 23108c2ecf20Sopenharmony_ci if (evergreen_is_safe_reg(p, reg)) 23118c2ecf20Sopenharmony_ci continue; 23128c2ecf20Sopenharmony_ci r = evergreen_cs_handle_reg(p, reg, idx); 23138c2ecf20Sopenharmony_ci if (r) 23148c2ecf20Sopenharmony_ci return r; 23158c2ecf20Sopenharmony_ci } 23168c2ecf20Sopenharmony_ci break; 23178c2ecf20Sopenharmony_ci case PACKET3_SET_CONTEXT_REG: 23188c2ecf20Sopenharmony_ci start_reg = (idx_value << 2) + PACKET3_SET_CONTEXT_REG_START; 23198c2ecf20Sopenharmony_ci end_reg = 4 * pkt->count + start_reg - 4; 23208c2ecf20Sopenharmony_ci if ((start_reg < PACKET3_SET_CONTEXT_REG_START) || 23218c2ecf20Sopenharmony_ci (start_reg >= PACKET3_SET_CONTEXT_REG_END) || 23228c2ecf20Sopenharmony_ci (end_reg >= PACKET3_SET_CONTEXT_REG_END)) { 23238c2ecf20Sopenharmony_ci DRM_ERROR("bad PACKET3_SET_CONTEXT_REG\n"); 23248c2ecf20Sopenharmony_ci return -EINVAL; 23258c2ecf20Sopenharmony_ci } 23268c2ecf20Sopenharmony_ci for (reg = start_reg, idx++; reg <= end_reg; reg += 4, idx++) { 23278c2ecf20Sopenharmony_ci if (evergreen_is_safe_reg(p, reg)) 23288c2ecf20Sopenharmony_ci continue; 23298c2ecf20Sopenharmony_ci r = evergreen_cs_handle_reg(p, reg, idx); 23308c2ecf20Sopenharmony_ci if (r) 23318c2ecf20Sopenharmony_ci return r; 23328c2ecf20Sopenharmony_ci } 23338c2ecf20Sopenharmony_ci break; 23348c2ecf20Sopenharmony_ci case PACKET3_SET_RESOURCE: 23358c2ecf20Sopenharmony_ci if (pkt->count % 8) { 23368c2ecf20Sopenharmony_ci DRM_ERROR("bad SET_RESOURCE\n"); 23378c2ecf20Sopenharmony_ci return -EINVAL; 23388c2ecf20Sopenharmony_ci } 23398c2ecf20Sopenharmony_ci start_reg = (idx_value << 2) + PACKET3_SET_RESOURCE_START; 23408c2ecf20Sopenharmony_ci end_reg = 4 * pkt->count + start_reg - 4; 23418c2ecf20Sopenharmony_ci if ((start_reg < PACKET3_SET_RESOURCE_START) || 23428c2ecf20Sopenharmony_ci (start_reg >= PACKET3_SET_RESOURCE_END) || 23438c2ecf20Sopenharmony_ci (end_reg >= PACKET3_SET_RESOURCE_END)) { 23448c2ecf20Sopenharmony_ci DRM_ERROR("bad SET_RESOURCE\n"); 23458c2ecf20Sopenharmony_ci return -EINVAL; 23468c2ecf20Sopenharmony_ci } 23478c2ecf20Sopenharmony_ci for (i = 0; i < (pkt->count / 8); i++) { 23488c2ecf20Sopenharmony_ci struct radeon_bo *texture, *mipmap; 23498c2ecf20Sopenharmony_ci u32 toffset, moffset; 23508c2ecf20Sopenharmony_ci u32 size, offset, mip_address, tex_dim; 23518c2ecf20Sopenharmony_ci 23528c2ecf20Sopenharmony_ci switch (G__SQ_CONSTANT_TYPE(radeon_get_ib_value(p, idx+1+(i*8)+7))) { 23538c2ecf20Sopenharmony_ci case SQ_TEX_VTX_VALID_TEXTURE: 23548c2ecf20Sopenharmony_ci /* tex base */ 23558c2ecf20Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 23568c2ecf20Sopenharmony_ci if (r) { 23578c2ecf20Sopenharmony_ci DRM_ERROR("bad SET_RESOURCE (tex)\n"); 23588c2ecf20Sopenharmony_ci return -EINVAL; 23598c2ecf20Sopenharmony_ci } 23608c2ecf20Sopenharmony_ci if (!(p->cs_flags & RADEON_CS_KEEP_TILING_FLAGS)) { 23618c2ecf20Sopenharmony_ci ib[idx+1+(i*8)+1] |= 23628c2ecf20Sopenharmony_ci TEX_ARRAY_MODE(evergreen_cs_get_aray_mode(reloc->tiling_flags)); 23638c2ecf20Sopenharmony_ci if (reloc->tiling_flags & RADEON_TILING_MACRO) { 23648c2ecf20Sopenharmony_ci unsigned bankw, bankh, mtaspect, tile_split; 23658c2ecf20Sopenharmony_ci 23668c2ecf20Sopenharmony_ci evergreen_tiling_fields(reloc->tiling_flags, 23678c2ecf20Sopenharmony_ci &bankw, &bankh, &mtaspect, 23688c2ecf20Sopenharmony_ci &tile_split); 23698c2ecf20Sopenharmony_ci ib[idx+1+(i*8)+6] |= TEX_TILE_SPLIT(tile_split); 23708c2ecf20Sopenharmony_ci ib[idx+1+(i*8)+7] |= 23718c2ecf20Sopenharmony_ci TEX_BANK_WIDTH(bankw) | 23728c2ecf20Sopenharmony_ci TEX_BANK_HEIGHT(bankh) | 23738c2ecf20Sopenharmony_ci MACRO_TILE_ASPECT(mtaspect) | 23748c2ecf20Sopenharmony_ci TEX_NUM_BANKS(evergreen_cs_get_num_banks(track->nbanks)); 23758c2ecf20Sopenharmony_ci } 23768c2ecf20Sopenharmony_ci } 23778c2ecf20Sopenharmony_ci texture = reloc->robj; 23788c2ecf20Sopenharmony_ci toffset = (u32)((reloc->gpu_offset >> 8) & 0xffffffff); 23798c2ecf20Sopenharmony_ci 23808c2ecf20Sopenharmony_ci /* tex mip base */ 23818c2ecf20Sopenharmony_ci tex_dim = ib[idx+1+(i*8)+0] & 0x7; 23828c2ecf20Sopenharmony_ci mip_address = ib[idx+1+(i*8)+3]; 23838c2ecf20Sopenharmony_ci 23848c2ecf20Sopenharmony_ci if ((tex_dim == SQ_TEX_DIM_2D_MSAA || tex_dim == SQ_TEX_DIM_2D_ARRAY_MSAA) && 23858c2ecf20Sopenharmony_ci !mip_address && 23868c2ecf20Sopenharmony_ci !radeon_cs_packet_next_is_pkt3_nop(p)) { 23878c2ecf20Sopenharmony_ci /* MIP_ADDRESS should point to FMASK for an MSAA texture. 23888c2ecf20Sopenharmony_ci * It should be 0 if FMASK is disabled. */ 23898c2ecf20Sopenharmony_ci moffset = 0; 23908c2ecf20Sopenharmony_ci mipmap = NULL; 23918c2ecf20Sopenharmony_ci } else { 23928c2ecf20Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 23938c2ecf20Sopenharmony_ci if (r) { 23948c2ecf20Sopenharmony_ci DRM_ERROR("bad SET_RESOURCE (tex)\n"); 23958c2ecf20Sopenharmony_ci return -EINVAL; 23968c2ecf20Sopenharmony_ci } 23978c2ecf20Sopenharmony_ci moffset = (u32)((reloc->gpu_offset >> 8) & 0xffffffff); 23988c2ecf20Sopenharmony_ci mipmap = reloc->robj; 23998c2ecf20Sopenharmony_ci } 24008c2ecf20Sopenharmony_ci 24018c2ecf20Sopenharmony_ci r = evergreen_cs_track_validate_texture(p, texture, mipmap, idx+1+(i*8)); 24028c2ecf20Sopenharmony_ci if (r) 24038c2ecf20Sopenharmony_ci return r; 24048c2ecf20Sopenharmony_ci ib[idx+1+(i*8)+2] += toffset; 24058c2ecf20Sopenharmony_ci ib[idx+1+(i*8)+3] += moffset; 24068c2ecf20Sopenharmony_ci break; 24078c2ecf20Sopenharmony_ci case SQ_TEX_VTX_VALID_BUFFER: 24088c2ecf20Sopenharmony_ci { 24098c2ecf20Sopenharmony_ci uint64_t offset64; 24108c2ecf20Sopenharmony_ci /* vtx base */ 24118c2ecf20Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 24128c2ecf20Sopenharmony_ci if (r) { 24138c2ecf20Sopenharmony_ci DRM_ERROR("bad SET_RESOURCE (vtx)\n"); 24148c2ecf20Sopenharmony_ci return -EINVAL; 24158c2ecf20Sopenharmony_ci } 24168c2ecf20Sopenharmony_ci offset = radeon_get_ib_value(p, idx+1+(i*8)+0); 24178c2ecf20Sopenharmony_ci size = radeon_get_ib_value(p, idx+1+(i*8)+1); 24188c2ecf20Sopenharmony_ci if (p->rdev && (size + offset) > radeon_bo_size(reloc->robj)) { 24198c2ecf20Sopenharmony_ci /* force size to size of the buffer */ 24208c2ecf20Sopenharmony_ci dev_warn_ratelimited(p->dev, "vbo resource seems too big for the bo\n"); 24218c2ecf20Sopenharmony_ci ib[idx+1+(i*8)+1] = radeon_bo_size(reloc->robj) - offset; 24228c2ecf20Sopenharmony_ci } 24238c2ecf20Sopenharmony_ci 24248c2ecf20Sopenharmony_ci offset64 = reloc->gpu_offset + offset; 24258c2ecf20Sopenharmony_ci ib[idx+1+(i*8)+0] = offset64; 24268c2ecf20Sopenharmony_ci ib[idx+1+(i*8)+2] = (ib[idx+1+(i*8)+2] & 0xffffff00) | 24278c2ecf20Sopenharmony_ci (upper_32_bits(offset64) & 0xff); 24288c2ecf20Sopenharmony_ci break; 24298c2ecf20Sopenharmony_ci } 24308c2ecf20Sopenharmony_ci case SQ_TEX_VTX_INVALID_TEXTURE: 24318c2ecf20Sopenharmony_ci case SQ_TEX_VTX_INVALID_BUFFER: 24328c2ecf20Sopenharmony_ci default: 24338c2ecf20Sopenharmony_ci DRM_ERROR("bad SET_RESOURCE\n"); 24348c2ecf20Sopenharmony_ci return -EINVAL; 24358c2ecf20Sopenharmony_ci } 24368c2ecf20Sopenharmony_ci } 24378c2ecf20Sopenharmony_ci break; 24388c2ecf20Sopenharmony_ci case PACKET3_SET_ALU_CONST: 24398c2ecf20Sopenharmony_ci /* XXX fix me ALU const buffers only */ 24408c2ecf20Sopenharmony_ci break; 24418c2ecf20Sopenharmony_ci case PACKET3_SET_BOOL_CONST: 24428c2ecf20Sopenharmony_ci start_reg = (idx_value << 2) + PACKET3_SET_BOOL_CONST_START; 24438c2ecf20Sopenharmony_ci end_reg = 4 * pkt->count + start_reg - 4; 24448c2ecf20Sopenharmony_ci if ((start_reg < PACKET3_SET_BOOL_CONST_START) || 24458c2ecf20Sopenharmony_ci (start_reg >= PACKET3_SET_BOOL_CONST_END) || 24468c2ecf20Sopenharmony_ci (end_reg >= PACKET3_SET_BOOL_CONST_END)) { 24478c2ecf20Sopenharmony_ci DRM_ERROR("bad SET_BOOL_CONST\n"); 24488c2ecf20Sopenharmony_ci return -EINVAL; 24498c2ecf20Sopenharmony_ci } 24508c2ecf20Sopenharmony_ci break; 24518c2ecf20Sopenharmony_ci case PACKET3_SET_LOOP_CONST: 24528c2ecf20Sopenharmony_ci start_reg = (idx_value << 2) + PACKET3_SET_LOOP_CONST_START; 24538c2ecf20Sopenharmony_ci end_reg = 4 * pkt->count + start_reg - 4; 24548c2ecf20Sopenharmony_ci if ((start_reg < PACKET3_SET_LOOP_CONST_START) || 24558c2ecf20Sopenharmony_ci (start_reg >= PACKET3_SET_LOOP_CONST_END) || 24568c2ecf20Sopenharmony_ci (end_reg >= PACKET3_SET_LOOP_CONST_END)) { 24578c2ecf20Sopenharmony_ci DRM_ERROR("bad SET_LOOP_CONST\n"); 24588c2ecf20Sopenharmony_ci return -EINVAL; 24598c2ecf20Sopenharmony_ci } 24608c2ecf20Sopenharmony_ci break; 24618c2ecf20Sopenharmony_ci case PACKET3_SET_CTL_CONST: 24628c2ecf20Sopenharmony_ci start_reg = (idx_value << 2) + PACKET3_SET_CTL_CONST_START; 24638c2ecf20Sopenharmony_ci end_reg = 4 * pkt->count + start_reg - 4; 24648c2ecf20Sopenharmony_ci if ((start_reg < PACKET3_SET_CTL_CONST_START) || 24658c2ecf20Sopenharmony_ci (start_reg >= PACKET3_SET_CTL_CONST_END) || 24668c2ecf20Sopenharmony_ci (end_reg >= PACKET3_SET_CTL_CONST_END)) { 24678c2ecf20Sopenharmony_ci DRM_ERROR("bad SET_CTL_CONST\n"); 24688c2ecf20Sopenharmony_ci return -EINVAL; 24698c2ecf20Sopenharmony_ci } 24708c2ecf20Sopenharmony_ci break; 24718c2ecf20Sopenharmony_ci case PACKET3_SET_SAMPLER: 24728c2ecf20Sopenharmony_ci if (pkt->count % 3) { 24738c2ecf20Sopenharmony_ci DRM_ERROR("bad SET_SAMPLER\n"); 24748c2ecf20Sopenharmony_ci return -EINVAL; 24758c2ecf20Sopenharmony_ci } 24768c2ecf20Sopenharmony_ci start_reg = (idx_value << 2) + PACKET3_SET_SAMPLER_START; 24778c2ecf20Sopenharmony_ci end_reg = 4 * pkt->count + start_reg - 4; 24788c2ecf20Sopenharmony_ci if ((start_reg < PACKET3_SET_SAMPLER_START) || 24798c2ecf20Sopenharmony_ci (start_reg >= PACKET3_SET_SAMPLER_END) || 24808c2ecf20Sopenharmony_ci (end_reg >= PACKET3_SET_SAMPLER_END)) { 24818c2ecf20Sopenharmony_ci DRM_ERROR("bad SET_SAMPLER\n"); 24828c2ecf20Sopenharmony_ci return -EINVAL; 24838c2ecf20Sopenharmony_ci } 24848c2ecf20Sopenharmony_ci break; 24858c2ecf20Sopenharmony_ci case PACKET3_STRMOUT_BUFFER_UPDATE: 24868c2ecf20Sopenharmony_ci if (pkt->count != 4) { 24878c2ecf20Sopenharmony_ci DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (invalid count)\n"); 24888c2ecf20Sopenharmony_ci return -EINVAL; 24898c2ecf20Sopenharmony_ci } 24908c2ecf20Sopenharmony_ci /* Updating memory at DST_ADDRESS. */ 24918c2ecf20Sopenharmony_ci if (idx_value & 0x1) { 24928c2ecf20Sopenharmony_ci u64 offset; 24938c2ecf20Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 24948c2ecf20Sopenharmony_ci if (r) { 24958c2ecf20Sopenharmony_ci DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing dst reloc)\n"); 24968c2ecf20Sopenharmony_ci return -EINVAL; 24978c2ecf20Sopenharmony_ci } 24988c2ecf20Sopenharmony_ci offset = radeon_get_ib_value(p, idx+1); 24998c2ecf20Sopenharmony_ci offset += ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32; 25008c2ecf20Sopenharmony_ci if ((offset + 4) > radeon_bo_size(reloc->robj)) { 25018c2ecf20Sopenharmony_ci DRM_ERROR("bad STRMOUT_BUFFER_UPDATE dst bo too small: 0x%llx, 0x%lx\n", 25028c2ecf20Sopenharmony_ci offset + 4, radeon_bo_size(reloc->robj)); 25038c2ecf20Sopenharmony_ci return -EINVAL; 25048c2ecf20Sopenharmony_ci } 25058c2ecf20Sopenharmony_ci offset += reloc->gpu_offset; 25068c2ecf20Sopenharmony_ci ib[idx+1] = offset; 25078c2ecf20Sopenharmony_ci ib[idx+2] = upper_32_bits(offset) & 0xff; 25088c2ecf20Sopenharmony_ci } 25098c2ecf20Sopenharmony_ci /* Reading data from SRC_ADDRESS. */ 25108c2ecf20Sopenharmony_ci if (((idx_value >> 1) & 0x3) == 2) { 25118c2ecf20Sopenharmony_ci u64 offset; 25128c2ecf20Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 25138c2ecf20Sopenharmony_ci if (r) { 25148c2ecf20Sopenharmony_ci DRM_ERROR("bad STRMOUT_BUFFER_UPDATE (missing src reloc)\n"); 25158c2ecf20Sopenharmony_ci return -EINVAL; 25168c2ecf20Sopenharmony_ci } 25178c2ecf20Sopenharmony_ci offset = radeon_get_ib_value(p, idx+3); 25188c2ecf20Sopenharmony_ci offset += ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32; 25198c2ecf20Sopenharmony_ci if ((offset + 4) > radeon_bo_size(reloc->robj)) { 25208c2ecf20Sopenharmony_ci DRM_ERROR("bad STRMOUT_BUFFER_UPDATE src bo too small: 0x%llx, 0x%lx\n", 25218c2ecf20Sopenharmony_ci offset + 4, radeon_bo_size(reloc->robj)); 25228c2ecf20Sopenharmony_ci return -EINVAL; 25238c2ecf20Sopenharmony_ci } 25248c2ecf20Sopenharmony_ci offset += reloc->gpu_offset; 25258c2ecf20Sopenharmony_ci ib[idx+3] = offset; 25268c2ecf20Sopenharmony_ci ib[idx+4] = upper_32_bits(offset) & 0xff; 25278c2ecf20Sopenharmony_ci } 25288c2ecf20Sopenharmony_ci break; 25298c2ecf20Sopenharmony_ci case PACKET3_MEM_WRITE: 25308c2ecf20Sopenharmony_ci { 25318c2ecf20Sopenharmony_ci u64 offset; 25328c2ecf20Sopenharmony_ci 25338c2ecf20Sopenharmony_ci if (pkt->count != 3) { 25348c2ecf20Sopenharmony_ci DRM_ERROR("bad MEM_WRITE (invalid count)\n"); 25358c2ecf20Sopenharmony_ci return -EINVAL; 25368c2ecf20Sopenharmony_ci } 25378c2ecf20Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 25388c2ecf20Sopenharmony_ci if (r) { 25398c2ecf20Sopenharmony_ci DRM_ERROR("bad MEM_WRITE (missing reloc)\n"); 25408c2ecf20Sopenharmony_ci return -EINVAL; 25418c2ecf20Sopenharmony_ci } 25428c2ecf20Sopenharmony_ci offset = radeon_get_ib_value(p, idx+0); 25438c2ecf20Sopenharmony_ci offset += ((u64)(radeon_get_ib_value(p, idx+1) & 0xff)) << 32UL; 25448c2ecf20Sopenharmony_ci if (offset & 0x7) { 25458c2ecf20Sopenharmony_ci DRM_ERROR("bad MEM_WRITE (address not qwords aligned)\n"); 25468c2ecf20Sopenharmony_ci return -EINVAL; 25478c2ecf20Sopenharmony_ci } 25488c2ecf20Sopenharmony_ci if ((offset + 8) > radeon_bo_size(reloc->robj)) { 25498c2ecf20Sopenharmony_ci DRM_ERROR("bad MEM_WRITE bo too small: 0x%llx, 0x%lx\n", 25508c2ecf20Sopenharmony_ci offset + 8, radeon_bo_size(reloc->robj)); 25518c2ecf20Sopenharmony_ci return -EINVAL; 25528c2ecf20Sopenharmony_ci } 25538c2ecf20Sopenharmony_ci offset += reloc->gpu_offset; 25548c2ecf20Sopenharmony_ci ib[idx+0] = offset; 25558c2ecf20Sopenharmony_ci ib[idx+1] = upper_32_bits(offset) & 0xff; 25568c2ecf20Sopenharmony_ci break; 25578c2ecf20Sopenharmony_ci } 25588c2ecf20Sopenharmony_ci case PACKET3_COPY_DW: 25598c2ecf20Sopenharmony_ci if (pkt->count != 4) { 25608c2ecf20Sopenharmony_ci DRM_ERROR("bad COPY_DW (invalid count)\n"); 25618c2ecf20Sopenharmony_ci return -EINVAL; 25628c2ecf20Sopenharmony_ci } 25638c2ecf20Sopenharmony_ci if (idx_value & 0x1) { 25648c2ecf20Sopenharmony_ci u64 offset; 25658c2ecf20Sopenharmony_ci /* SRC is memory. */ 25668c2ecf20Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 25678c2ecf20Sopenharmony_ci if (r) { 25688c2ecf20Sopenharmony_ci DRM_ERROR("bad COPY_DW (missing src reloc)\n"); 25698c2ecf20Sopenharmony_ci return -EINVAL; 25708c2ecf20Sopenharmony_ci } 25718c2ecf20Sopenharmony_ci offset = radeon_get_ib_value(p, idx+1); 25728c2ecf20Sopenharmony_ci offset += ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32; 25738c2ecf20Sopenharmony_ci if ((offset + 4) > radeon_bo_size(reloc->robj)) { 25748c2ecf20Sopenharmony_ci DRM_ERROR("bad COPY_DW src bo too small: 0x%llx, 0x%lx\n", 25758c2ecf20Sopenharmony_ci offset + 4, radeon_bo_size(reloc->robj)); 25768c2ecf20Sopenharmony_ci return -EINVAL; 25778c2ecf20Sopenharmony_ci } 25788c2ecf20Sopenharmony_ci offset += reloc->gpu_offset; 25798c2ecf20Sopenharmony_ci ib[idx+1] = offset; 25808c2ecf20Sopenharmony_ci ib[idx+2] = upper_32_bits(offset) & 0xff; 25818c2ecf20Sopenharmony_ci } else { 25828c2ecf20Sopenharmony_ci /* SRC is a reg. */ 25838c2ecf20Sopenharmony_ci reg = radeon_get_ib_value(p, idx+1) << 2; 25848c2ecf20Sopenharmony_ci if (!evergreen_is_safe_reg(p, reg)) { 25858c2ecf20Sopenharmony_ci dev_warn(p->dev, "forbidden register 0x%08x at %d\n", 25868c2ecf20Sopenharmony_ci reg, idx + 1); 25878c2ecf20Sopenharmony_ci return -EINVAL; 25888c2ecf20Sopenharmony_ci } 25898c2ecf20Sopenharmony_ci } 25908c2ecf20Sopenharmony_ci if (idx_value & 0x2) { 25918c2ecf20Sopenharmony_ci u64 offset; 25928c2ecf20Sopenharmony_ci /* DST is memory. */ 25938c2ecf20Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 25948c2ecf20Sopenharmony_ci if (r) { 25958c2ecf20Sopenharmony_ci DRM_ERROR("bad COPY_DW (missing dst reloc)\n"); 25968c2ecf20Sopenharmony_ci return -EINVAL; 25978c2ecf20Sopenharmony_ci } 25988c2ecf20Sopenharmony_ci offset = radeon_get_ib_value(p, idx+3); 25998c2ecf20Sopenharmony_ci offset += ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32; 26008c2ecf20Sopenharmony_ci if ((offset + 4) > radeon_bo_size(reloc->robj)) { 26018c2ecf20Sopenharmony_ci DRM_ERROR("bad COPY_DW dst bo too small: 0x%llx, 0x%lx\n", 26028c2ecf20Sopenharmony_ci offset + 4, radeon_bo_size(reloc->robj)); 26038c2ecf20Sopenharmony_ci return -EINVAL; 26048c2ecf20Sopenharmony_ci } 26058c2ecf20Sopenharmony_ci offset += reloc->gpu_offset; 26068c2ecf20Sopenharmony_ci ib[idx+3] = offset; 26078c2ecf20Sopenharmony_ci ib[idx+4] = upper_32_bits(offset) & 0xff; 26088c2ecf20Sopenharmony_ci } else { 26098c2ecf20Sopenharmony_ci /* DST is a reg. */ 26108c2ecf20Sopenharmony_ci reg = radeon_get_ib_value(p, idx+3) << 2; 26118c2ecf20Sopenharmony_ci if (!evergreen_is_safe_reg(p, reg)) { 26128c2ecf20Sopenharmony_ci dev_warn(p->dev, "forbidden register 0x%08x at %d\n", 26138c2ecf20Sopenharmony_ci reg, idx + 3); 26148c2ecf20Sopenharmony_ci return -EINVAL; 26158c2ecf20Sopenharmony_ci } 26168c2ecf20Sopenharmony_ci } 26178c2ecf20Sopenharmony_ci break; 26188c2ecf20Sopenharmony_ci case PACKET3_SET_APPEND_CNT: 26198c2ecf20Sopenharmony_ci { 26208c2ecf20Sopenharmony_ci uint32_t areg; 26218c2ecf20Sopenharmony_ci uint32_t allowed_reg_base; 26228c2ecf20Sopenharmony_ci uint32_t source_sel; 26238c2ecf20Sopenharmony_ci if (pkt->count != 2) { 26248c2ecf20Sopenharmony_ci DRM_ERROR("bad SET_APPEND_CNT (invalid count)\n"); 26258c2ecf20Sopenharmony_ci return -EINVAL; 26268c2ecf20Sopenharmony_ci } 26278c2ecf20Sopenharmony_ci 26288c2ecf20Sopenharmony_ci allowed_reg_base = GDS_APPEND_COUNT_0; 26298c2ecf20Sopenharmony_ci allowed_reg_base -= PACKET3_SET_CONTEXT_REG_START; 26308c2ecf20Sopenharmony_ci allowed_reg_base >>= 2; 26318c2ecf20Sopenharmony_ci 26328c2ecf20Sopenharmony_ci areg = idx_value >> 16; 26338c2ecf20Sopenharmony_ci if (areg < allowed_reg_base || areg > (allowed_reg_base + 11)) { 26348c2ecf20Sopenharmony_ci dev_warn(p->dev, "forbidden register for append cnt 0x%08x at %d\n", 26358c2ecf20Sopenharmony_ci areg, idx); 26368c2ecf20Sopenharmony_ci return -EINVAL; 26378c2ecf20Sopenharmony_ci } 26388c2ecf20Sopenharmony_ci 26398c2ecf20Sopenharmony_ci source_sel = G_PACKET3_SET_APPEND_CNT_SRC_SELECT(idx_value); 26408c2ecf20Sopenharmony_ci if (source_sel == PACKET3_SAC_SRC_SEL_MEM) { 26418c2ecf20Sopenharmony_ci uint64_t offset; 26428c2ecf20Sopenharmony_ci uint32_t swap; 26438c2ecf20Sopenharmony_ci r = radeon_cs_packet_next_reloc(p, &reloc, 0); 26448c2ecf20Sopenharmony_ci if (r) { 26458c2ecf20Sopenharmony_ci DRM_ERROR("bad SET_APPEND_CNT (missing reloc)\n"); 26468c2ecf20Sopenharmony_ci return -EINVAL; 26478c2ecf20Sopenharmony_ci } 26488c2ecf20Sopenharmony_ci offset = radeon_get_ib_value(p, idx + 1); 26498c2ecf20Sopenharmony_ci swap = offset & 0x3; 26508c2ecf20Sopenharmony_ci offset &= ~0x3; 26518c2ecf20Sopenharmony_ci 26528c2ecf20Sopenharmony_ci offset += ((u64)(radeon_get_ib_value(p, idx + 2) & 0xff)) << 32; 26538c2ecf20Sopenharmony_ci 26548c2ecf20Sopenharmony_ci offset += reloc->gpu_offset; 26558c2ecf20Sopenharmony_ci ib[idx+1] = (offset & 0xfffffffc) | swap; 26568c2ecf20Sopenharmony_ci ib[idx+2] = upper_32_bits(offset) & 0xff; 26578c2ecf20Sopenharmony_ci } else { 26588c2ecf20Sopenharmony_ci DRM_ERROR("bad SET_APPEND_CNT (unsupported operation)\n"); 26598c2ecf20Sopenharmony_ci return -EINVAL; 26608c2ecf20Sopenharmony_ci } 26618c2ecf20Sopenharmony_ci break; 26628c2ecf20Sopenharmony_ci } 26638c2ecf20Sopenharmony_ci case PACKET3_NOP: 26648c2ecf20Sopenharmony_ci break; 26658c2ecf20Sopenharmony_ci default: 26668c2ecf20Sopenharmony_ci DRM_ERROR("Packet3 opcode %x not supported\n", pkt->opcode); 26678c2ecf20Sopenharmony_ci return -EINVAL; 26688c2ecf20Sopenharmony_ci } 26698c2ecf20Sopenharmony_ci return 0; 26708c2ecf20Sopenharmony_ci} 26718c2ecf20Sopenharmony_ci 26728c2ecf20Sopenharmony_ciint evergreen_cs_parse(struct radeon_cs_parser *p) 26738c2ecf20Sopenharmony_ci{ 26748c2ecf20Sopenharmony_ci struct radeon_cs_packet pkt; 26758c2ecf20Sopenharmony_ci struct evergreen_cs_track *track; 26768c2ecf20Sopenharmony_ci u32 tmp; 26778c2ecf20Sopenharmony_ci int r; 26788c2ecf20Sopenharmony_ci 26798c2ecf20Sopenharmony_ci if (p->track == NULL) { 26808c2ecf20Sopenharmony_ci /* initialize tracker, we are in kms */ 26818c2ecf20Sopenharmony_ci track = kzalloc(sizeof(*track), GFP_KERNEL); 26828c2ecf20Sopenharmony_ci if (track == NULL) 26838c2ecf20Sopenharmony_ci return -ENOMEM; 26848c2ecf20Sopenharmony_ci evergreen_cs_track_init(track); 26858c2ecf20Sopenharmony_ci if (p->rdev->family >= CHIP_CAYMAN) { 26868c2ecf20Sopenharmony_ci tmp = p->rdev->config.cayman.tile_config; 26878c2ecf20Sopenharmony_ci track->reg_safe_bm = cayman_reg_safe_bm; 26888c2ecf20Sopenharmony_ci } else { 26898c2ecf20Sopenharmony_ci tmp = p->rdev->config.evergreen.tile_config; 26908c2ecf20Sopenharmony_ci track->reg_safe_bm = evergreen_reg_safe_bm; 26918c2ecf20Sopenharmony_ci } 26928c2ecf20Sopenharmony_ci BUILD_BUG_ON(ARRAY_SIZE(cayman_reg_safe_bm) != REG_SAFE_BM_SIZE); 26938c2ecf20Sopenharmony_ci BUILD_BUG_ON(ARRAY_SIZE(evergreen_reg_safe_bm) != REG_SAFE_BM_SIZE); 26948c2ecf20Sopenharmony_ci switch (tmp & 0xf) { 26958c2ecf20Sopenharmony_ci case 0: 26968c2ecf20Sopenharmony_ci track->npipes = 1; 26978c2ecf20Sopenharmony_ci break; 26988c2ecf20Sopenharmony_ci case 1: 26998c2ecf20Sopenharmony_ci default: 27008c2ecf20Sopenharmony_ci track->npipes = 2; 27018c2ecf20Sopenharmony_ci break; 27028c2ecf20Sopenharmony_ci case 2: 27038c2ecf20Sopenharmony_ci track->npipes = 4; 27048c2ecf20Sopenharmony_ci break; 27058c2ecf20Sopenharmony_ci case 3: 27068c2ecf20Sopenharmony_ci track->npipes = 8; 27078c2ecf20Sopenharmony_ci break; 27088c2ecf20Sopenharmony_ci } 27098c2ecf20Sopenharmony_ci 27108c2ecf20Sopenharmony_ci switch ((tmp & 0xf0) >> 4) { 27118c2ecf20Sopenharmony_ci case 0: 27128c2ecf20Sopenharmony_ci track->nbanks = 4; 27138c2ecf20Sopenharmony_ci break; 27148c2ecf20Sopenharmony_ci case 1: 27158c2ecf20Sopenharmony_ci default: 27168c2ecf20Sopenharmony_ci track->nbanks = 8; 27178c2ecf20Sopenharmony_ci break; 27188c2ecf20Sopenharmony_ci case 2: 27198c2ecf20Sopenharmony_ci track->nbanks = 16; 27208c2ecf20Sopenharmony_ci break; 27218c2ecf20Sopenharmony_ci } 27228c2ecf20Sopenharmony_ci 27238c2ecf20Sopenharmony_ci switch ((tmp & 0xf00) >> 8) { 27248c2ecf20Sopenharmony_ci case 0: 27258c2ecf20Sopenharmony_ci track->group_size = 256; 27268c2ecf20Sopenharmony_ci break; 27278c2ecf20Sopenharmony_ci case 1: 27288c2ecf20Sopenharmony_ci default: 27298c2ecf20Sopenharmony_ci track->group_size = 512; 27308c2ecf20Sopenharmony_ci break; 27318c2ecf20Sopenharmony_ci } 27328c2ecf20Sopenharmony_ci 27338c2ecf20Sopenharmony_ci switch ((tmp & 0xf000) >> 12) { 27348c2ecf20Sopenharmony_ci case 0: 27358c2ecf20Sopenharmony_ci track->row_size = 1; 27368c2ecf20Sopenharmony_ci break; 27378c2ecf20Sopenharmony_ci case 1: 27388c2ecf20Sopenharmony_ci default: 27398c2ecf20Sopenharmony_ci track->row_size = 2; 27408c2ecf20Sopenharmony_ci break; 27418c2ecf20Sopenharmony_ci case 2: 27428c2ecf20Sopenharmony_ci track->row_size = 4; 27438c2ecf20Sopenharmony_ci break; 27448c2ecf20Sopenharmony_ci } 27458c2ecf20Sopenharmony_ci 27468c2ecf20Sopenharmony_ci p->track = track; 27478c2ecf20Sopenharmony_ci } 27488c2ecf20Sopenharmony_ci do { 27498c2ecf20Sopenharmony_ci r = radeon_cs_packet_parse(p, &pkt, p->idx); 27508c2ecf20Sopenharmony_ci if (r) { 27518c2ecf20Sopenharmony_ci kfree(p->track); 27528c2ecf20Sopenharmony_ci p->track = NULL; 27538c2ecf20Sopenharmony_ci return r; 27548c2ecf20Sopenharmony_ci } 27558c2ecf20Sopenharmony_ci p->idx += pkt.count + 2; 27568c2ecf20Sopenharmony_ci switch (pkt.type) { 27578c2ecf20Sopenharmony_ci case RADEON_PACKET_TYPE0: 27588c2ecf20Sopenharmony_ci r = evergreen_cs_parse_packet0(p, &pkt); 27598c2ecf20Sopenharmony_ci break; 27608c2ecf20Sopenharmony_ci case RADEON_PACKET_TYPE2: 27618c2ecf20Sopenharmony_ci break; 27628c2ecf20Sopenharmony_ci case RADEON_PACKET_TYPE3: 27638c2ecf20Sopenharmony_ci r = evergreen_packet3_check(p, &pkt); 27648c2ecf20Sopenharmony_ci break; 27658c2ecf20Sopenharmony_ci default: 27668c2ecf20Sopenharmony_ci DRM_ERROR("Unknown packet type %d !\n", pkt.type); 27678c2ecf20Sopenharmony_ci kfree(p->track); 27688c2ecf20Sopenharmony_ci p->track = NULL; 27698c2ecf20Sopenharmony_ci return -EINVAL; 27708c2ecf20Sopenharmony_ci } 27718c2ecf20Sopenharmony_ci if (r) { 27728c2ecf20Sopenharmony_ci kfree(p->track); 27738c2ecf20Sopenharmony_ci p->track = NULL; 27748c2ecf20Sopenharmony_ci return r; 27758c2ecf20Sopenharmony_ci } 27768c2ecf20Sopenharmony_ci } while (p->idx < p->chunk_ib->length_dw); 27778c2ecf20Sopenharmony_ci#if 0 27788c2ecf20Sopenharmony_ci for (r = 0; r < p->ib.length_dw; r++) { 27798c2ecf20Sopenharmony_ci pr_info("%05d 0x%08X\n", r, p->ib.ptr[r]); 27808c2ecf20Sopenharmony_ci mdelay(1); 27818c2ecf20Sopenharmony_ci } 27828c2ecf20Sopenharmony_ci#endif 27838c2ecf20Sopenharmony_ci kfree(p->track); 27848c2ecf20Sopenharmony_ci p->track = NULL; 27858c2ecf20Sopenharmony_ci return 0; 27868c2ecf20Sopenharmony_ci} 27878c2ecf20Sopenharmony_ci 27888c2ecf20Sopenharmony_ci/** 27898c2ecf20Sopenharmony_ci * evergreen_dma_cs_parse() - parse the DMA IB 27908c2ecf20Sopenharmony_ci * @p: parser structure holding parsing context. 27918c2ecf20Sopenharmony_ci * 27928c2ecf20Sopenharmony_ci * Parses the DMA IB from the CS ioctl and updates 27938c2ecf20Sopenharmony_ci * the GPU addresses based on the reloc information and 27948c2ecf20Sopenharmony_ci * checks for errors. (Evergreen-Cayman) 27958c2ecf20Sopenharmony_ci * Returns 0 for success and an error on failure. 27968c2ecf20Sopenharmony_ci **/ 27978c2ecf20Sopenharmony_ciint evergreen_dma_cs_parse(struct radeon_cs_parser *p) 27988c2ecf20Sopenharmony_ci{ 27998c2ecf20Sopenharmony_ci struct radeon_cs_chunk *ib_chunk = p->chunk_ib; 28008c2ecf20Sopenharmony_ci struct radeon_bo_list *src_reloc, *dst_reloc, *dst2_reloc; 28018c2ecf20Sopenharmony_ci u32 header, cmd, count, sub_cmd; 28028c2ecf20Sopenharmony_ci uint32_t *ib = p->ib.ptr; 28038c2ecf20Sopenharmony_ci u32 idx; 28048c2ecf20Sopenharmony_ci u64 src_offset, dst_offset, dst2_offset; 28058c2ecf20Sopenharmony_ci int r; 28068c2ecf20Sopenharmony_ci 28078c2ecf20Sopenharmony_ci do { 28088c2ecf20Sopenharmony_ci if (p->idx >= ib_chunk->length_dw) { 28098c2ecf20Sopenharmony_ci DRM_ERROR("Can not parse packet at %d after CS end %d !\n", 28108c2ecf20Sopenharmony_ci p->idx, ib_chunk->length_dw); 28118c2ecf20Sopenharmony_ci return -EINVAL; 28128c2ecf20Sopenharmony_ci } 28138c2ecf20Sopenharmony_ci idx = p->idx; 28148c2ecf20Sopenharmony_ci header = radeon_get_ib_value(p, idx); 28158c2ecf20Sopenharmony_ci cmd = GET_DMA_CMD(header); 28168c2ecf20Sopenharmony_ci count = GET_DMA_COUNT(header); 28178c2ecf20Sopenharmony_ci sub_cmd = GET_DMA_SUB_CMD(header); 28188c2ecf20Sopenharmony_ci 28198c2ecf20Sopenharmony_ci switch (cmd) { 28208c2ecf20Sopenharmony_ci case DMA_PACKET_WRITE: 28218c2ecf20Sopenharmony_ci r = r600_dma_cs_next_reloc(p, &dst_reloc); 28228c2ecf20Sopenharmony_ci if (r) { 28238c2ecf20Sopenharmony_ci DRM_ERROR("bad DMA_PACKET_WRITE\n"); 28248c2ecf20Sopenharmony_ci return -EINVAL; 28258c2ecf20Sopenharmony_ci } 28268c2ecf20Sopenharmony_ci switch (sub_cmd) { 28278c2ecf20Sopenharmony_ci /* tiled */ 28288c2ecf20Sopenharmony_ci case 8: 28298c2ecf20Sopenharmony_ci dst_offset = radeon_get_ib_value(p, idx+1); 28308c2ecf20Sopenharmony_ci dst_offset <<= 8; 28318c2ecf20Sopenharmony_ci 28328c2ecf20Sopenharmony_ci ib[idx+1] += (u32)(dst_reloc->gpu_offset >> 8); 28338c2ecf20Sopenharmony_ci p->idx += count + 7; 28348c2ecf20Sopenharmony_ci break; 28358c2ecf20Sopenharmony_ci /* linear */ 28368c2ecf20Sopenharmony_ci case 0: 28378c2ecf20Sopenharmony_ci dst_offset = radeon_get_ib_value(p, idx+1); 28388c2ecf20Sopenharmony_ci dst_offset |= ((u64)(radeon_get_ib_value(p, idx+2) & 0xff)) << 32; 28398c2ecf20Sopenharmony_ci 28408c2ecf20Sopenharmony_ci ib[idx+1] += (u32)(dst_reloc->gpu_offset & 0xfffffffc); 28418c2ecf20Sopenharmony_ci ib[idx+2] += upper_32_bits(dst_reloc->gpu_offset) & 0xff; 28428c2ecf20Sopenharmony_ci p->idx += count + 3; 28438c2ecf20Sopenharmony_ci break; 28448c2ecf20Sopenharmony_ci default: 28458c2ecf20Sopenharmony_ci DRM_ERROR("bad DMA_PACKET_WRITE [%6d] 0x%08x sub cmd is not 0 or 8\n", idx, header); 28468c2ecf20Sopenharmony_ci return -EINVAL; 28478c2ecf20Sopenharmony_ci } 28488c2ecf20Sopenharmony_ci if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { 28498c2ecf20Sopenharmony_ci dev_warn(p->dev, "DMA write buffer too small (%llu %lu)\n", 28508c2ecf20Sopenharmony_ci dst_offset, radeon_bo_size(dst_reloc->robj)); 28518c2ecf20Sopenharmony_ci return -EINVAL; 28528c2ecf20Sopenharmony_ci } 28538c2ecf20Sopenharmony_ci break; 28548c2ecf20Sopenharmony_ci case DMA_PACKET_COPY: 28558c2ecf20Sopenharmony_ci r = r600_dma_cs_next_reloc(p, &src_reloc); 28568c2ecf20Sopenharmony_ci if (r) { 28578c2ecf20Sopenharmony_ci DRM_ERROR("bad DMA_PACKET_COPY\n"); 28588c2ecf20Sopenharmony_ci return -EINVAL; 28598c2ecf20Sopenharmony_ci } 28608c2ecf20Sopenharmony_ci r = r600_dma_cs_next_reloc(p, &dst_reloc); 28618c2ecf20Sopenharmony_ci if (r) { 28628c2ecf20Sopenharmony_ci DRM_ERROR("bad DMA_PACKET_COPY\n"); 28638c2ecf20Sopenharmony_ci return -EINVAL; 28648c2ecf20Sopenharmony_ci } 28658c2ecf20Sopenharmony_ci switch (sub_cmd) { 28668c2ecf20Sopenharmony_ci /* Copy L2L, DW aligned */ 28678c2ecf20Sopenharmony_ci case 0x00: 28688c2ecf20Sopenharmony_ci /* L2L, dw */ 28698c2ecf20Sopenharmony_ci src_offset = radeon_get_ib_value(p, idx+2); 28708c2ecf20Sopenharmony_ci src_offset |= ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32; 28718c2ecf20Sopenharmony_ci dst_offset = radeon_get_ib_value(p, idx+1); 28728c2ecf20Sopenharmony_ci dst_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0xff)) << 32; 28738c2ecf20Sopenharmony_ci if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) { 28748c2ecf20Sopenharmony_ci dev_warn(p->dev, "DMA L2L, dw src buffer too small (%llu %lu)\n", 28758c2ecf20Sopenharmony_ci src_offset + (count * 4), radeon_bo_size(src_reloc->robj)); 28768c2ecf20Sopenharmony_ci return -EINVAL; 28778c2ecf20Sopenharmony_ci } 28788c2ecf20Sopenharmony_ci if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { 28798c2ecf20Sopenharmony_ci dev_warn(p->dev, "DMA L2L, dw dst buffer too small (%llu %lu)\n", 28808c2ecf20Sopenharmony_ci dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj)); 28818c2ecf20Sopenharmony_ci return -EINVAL; 28828c2ecf20Sopenharmony_ci } 28838c2ecf20Sopenharmony_ci ib[idx+1] += (u32)(dst_reloc->gpu_offset & 0xfffffffc); 28848c2ecf20Sopenharmony_ci ib[idx+2] += (u32)(src_reloc->gpu_offset & 0xfffffffc); 28858c2ecf20Sopenharmony_ci ib[idx+3] += upper_32_bits(dst_reloc->gpu_offset) & 0xff; 28868c2ecf20Sopenharmony_ci ib[idx+4] += upper_32_bits(src_reloc->gpu_offset) & 0xff; 28878c2ecf20Sopenharmony_ci p->idx += 5; 28888c2ecf20Sopenharmony_ci break; 28898c2ecf20Sopenharmony_ci /* Copy L2T/T2L */ 28908c2ecf20Sopenharmony_ci case 0x08: 28918c2ecf20Sopenharmony_ci /* detile bit */ 28928c2ecf20Sopenharmony_ci if (radeon_get_ib_value(p, idx + 2) & (1 << 31)) { 28938c2ecf20Sopenharmony_ci /* tiled src, linear dst */ 28948c2ecf20Sopenharmony_ci src_offset = radeon_get_ib_value(p, idx+1); 28958c2ecf20Sopenharmony_ci src_offset <<= 8; 28968c2ecf20Sopenharmony_ci ib[idx+1] += (u32)(src_reloc->gpu_offset >> 8); 28978c2ecf20Sopenharmony_ci 28988c2ecf20Sopenharmony_ci dst_offset = radeon_get_ib_value(p, idx + 7); 28998c2ecf20Sopenharmony_ci dst_offset |= ((u64)(radeon_get_ib_value(p, idx+8) & 0xff)) << 32; 29008c2ecf20Sopenharmony_ci ib[idx+7] += (u32)(dst_reloc->gpu_offset & 0xfffffffc); 29018c2ecf20Sopenharmony_ci ib[idx+8] += upper_32_bits(dst_reloc->gpu_offset) & 0xff; 29028c2ecf20Sopenharmony_ci } else { 29038c2ecf20Sopenharmony_ci /* linear src, tiled dst */ 29048c2ecf20Sopenharmony_ci src_offset = radeon_get_ib_value(p, idx+7); 29058c2ecf20Sopenharmony_ci src_offset |= ((u64)(radeon_get_ib_value(p, idx+8) & 0xff)) << 32; 29068c2ecf20Sopenharmony_ci ib[idx+7] += (u32)(src_reloc->gpu_offset & 0xfffffffc); 29078c2ecf20Sopenharmony_ci ib[idx+8] += upper_32_bits(src_reloc->gpu_offset) & 0xff; 29088c2ecf20Sopenharmony_ci 29098c2ecf20Sopenharmony_ci dst_offset = radeon_get_ib_value(p, idx+1); 29108c2ecf20Sopenharmony_ci dst_offset <<= 8; 29118c2ecf20Sopenharmony_ci ib[idx+1] += (u32)(dst_reloc->gpu_offset >> 8); 29128c2ecf20Sopenharmony_ci } 29138c2ecf20Sopenharmony_ci if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) { 29148c2ecf20Sopenharmony_ci dev_warn(p->dev, "DMA L2T, src buffer too small (%llu %lu)\n", 29158c2ecf20Sopenharmony_ci src_offset + (count * 4), radeon_bo_size(src_reloc->robj)); 29168c2ecf20Sopenharmony_ci return -EINVAL; 29178c2ecf20Sopenharmony_ci } 29188c2ecf20Sopenharmony_ci if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { 29198c2ecf20Sopenharmony_ci dev_warn(p->dev, "DMA L2T, dst buffer too small (%llu %lu)\n", 29208c2ecf20Sopenharmony_ci dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj)); 29218c2ecf20Sopenharmony_ci return -EINVAL; 29228c2ecf20Sopenharmony_ci } 29238c2ecf20Sopenharmony_ci p->idx += 9; 29248c2ecf20Sopenharmony_ci break; 29258c2ecf20Sopenharmony_ci /* Copy L2L, byte aligned */ 29268c2ecf20Sopenharmony_ci case 0x40: 29278c2ecf20Sopenharmony_ci /* L2L, byte */ 29288c2ecf20Sopenharmony_ci src_offset = radeon_get_ib_value(p, idx+2); 29298c2ecf20Sopenharmony_ci src_offset |= ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32; 29308c2ecf20Sopenharmony_ci dst_offset = radeon_get_ib_value(p, idx+1); 29318c2ecf20Sopenharmony_ci dst_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0xff)) << 32; 29328c2ecf20Sopenharmony_ci if ((src_offset + count) > radeon_bo_size(src_reloc->robj)) { 29338c2ecf20Sopenharmony_ci dev_warn(p->dev, "DMA L2L, byte src buffer too small (%llu %lu)\n", 29348c2ecf20Sopenharmony_ci src_offset + count, radeon_bo_size(src_reloc->robj)); 29358c2ecf20Sopenharmony_ci return -EINVAL; 29368c2ecf20Sopenharmony_ci } 29378c2ecf20Sopenharmony_ci if ((dst_offset + count) > radeon_bo_size(dst_reloc->robj)) { 29388c2ecf20Sopenharmony_ci dev_warn(p->dev, "DMA L2L, byte dst buffer too small (%llu %lu)\n", 29398c2ecf20Sopenharmony_ci dst_offset + count, radeon_bo_size(dst_reloc->robj)); 29408c2ecf20Sopenharmony_ci return -EINVAL; 29418c2ecf20Sopenharmony_ci } 29428c2ecf20Sopenharmony_ci ib[idx+1] += (u32)(dst_reloc->gpu_offset & 0xffffffff); 29438c2ecf20Sopenharmony_ci ib[idx+2] += (u32)(src_reloc->gpu_offset & 0xffffffff); 29448c2ecf20Sopenharmony_ci ib[idx+3] += upper_32_bits(dst_reloc->gpu_offset) & 0xff; 29458c2ecf20Sopenharmony_ci ib[idx+4] += upper_32_bits(src_reloc->gpu_offset) & 0xff; 29468c2ecf20Sopenharmony_ci p->idx += 5; 29478c2ecf20Sopenharmony_ci break; 29488c2ecf20Sopenharmony_ci /* Copy L2L, partial */ 29498c2ecf20Sopenharmony_ci case 0x41: 29508c2ecf20Sopenharmony_ci /* L2L, partial */ 29518c2ecf20Sopenharmony_ci if (p->family < CHIP_CAYMAN) { 29528c2ecf20Sopenharmony_ci DRM_ERROR("L2L Partial is cayman only !\n"); 29538c2ecf20Sopenharmony_ci return -EINVAL; 29548c2ecf20Sopenharmony_ci } 29558c2ecf20Sopenharmony_ci ib[idx+1] += (u32)(src_reloc->gpu_offset & 0xffffffff); 29568c2ecf20Sopenharmony_ci ib[idx+2] += upper_32_bits(src_reloc->gpu_offset) & 0xff; 29578c2ecf20Sopenharmony_ci ib[idx+4] += (u32)(dst_reloc->gpu_offset & 0xffffffff); 29588c2ecf20Sopenharmony_ci ib[idx+5] += upper_32_bits(dst_reloc->gpu_offset) & 0xff; 29598c2ecf20Sopenharmony_ci 29608c2ecf20Sopenharmony_ci p->idx += 9; 29618c2ecf20Sopenharmony_ci break; 29628c2ecf20Sopenharmony_ci /* Copy L2L, DW aligned, broadcast */ 29638c2ecf20Sopenharmony_ci case 0x44: 29648c2ecf20Sopenharmony_ci /* L2L, dw, broadcast */ 29658c2ecf20Sopenharmony_ci r = r600_dma_cs_next_reloc(p, &dst2_reloc); 29668c2ecf20Sopenharmony_ci if (r) { 29678c2ecf20Sopenharmony_ci DRM_ERROR("bad L2L, dw, broadcast DMA_PACKET_COPY\n"); 29688c2ecf20Sopenharmony_ci return -EINVAL; 29698c2ecf20Sopenharmony_ci } 29708c2ecf20Sopenharmony_ci dst_offset = radeon_get_ib_value(p, idx+1); 29718c2ecf20Sopenharmony_ci dst_offset |= ((u64)(radeon_get_ib_value(p, idx+4) & 0xff)) << 32; 29728c2ecf20Sopenharmony_ci dst2_offset = radeon_get_ib_value(p, idx+2); 29738c2ecf20Sopenharmony_ci dst2_offset |= ((u64)(radeon_get_ib_value(p, idx+5) & 0xff)) << 32; 29748c2ecf20Sopenharmony_ci src_offset = radeon_get_ib_value(p, idx+3); 29758c2ecf20Sopenharmony_ci src_offset |= ((u64)(radeon_get_ib_value(p, idx+6) & 0xff)) << 32; 29768c2ecf20Sopenharmony_ci if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) { 29778c2ecf20Sopenharmony_ci dev_warn(p->dev, "DMA L2L, dw, broadcast src buffer too small (%llu %lu)\n", 29788c2ecf20Sopenharmony_ci src_offset + (count * 4), radeon_bo_size(src_reloc->robj)); 29798c2ecf20Sopenharmony_ci return -EINVAL; 29808c2ecf20Sopenharmony_ci } 29818c2ecf20Sopenharmony_ci if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { 29828c2ecf20Sopenharmony_ci dev_warn(p->dev, "DMA L2L, dw, broadcast dst buffer too small (%llu %lu)\n", 29838c2ecf20Sopenharmony_ci dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj)); 29848c2ecf20Sopenharmony_ci return -EINVAL; 29858c2ecf20Sopenharmony_ci } 29868c2ecf20Sopenharmony_ci if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) { 29878c2ecf20Sopenharmony_ci dev_warn(p->dev, "DMA L2L, dw, broadcast dst2 buffer too small (%llu %lu)\n", 29888c2ecf20Sopenharmony_ci dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj)); 29898c2ecf20Sopenharmony_ci return -EINVAL; 29908c2ecf20Sopenharmony_ci } 29918c2ecf20Sopenharmony_ci ib[idx+1] += (u32)(dst_reloc->gpu_offset & 0xfffffffc); 29928c2ecf20Sopenharmony_ci ib[idx+2] += (u32)(dst2_reloc->gpu_offset & 0xfffffffc); 29938c2ecf20Sopenharmony_ci ib[idx+3] += (u32)(src_reloc->gpu_offset & 0xfffffffc); 29948c2ecf20Sopenharmony_ci ib[idx+4] += upper_32_bits(dst_reloc->gpu_offset) & 0xff; 29958c2ecf20Sopenharmony_ci ib[idx+5] += upper_32_bits(dst2_reloc->gpu_offset) & 0xff; 29968c2ecf20Sopenharmony_ci ib[idx+6] += upper_32_bits(src_reloc->gpu_offset) & 0xff; 29978c2ecf20Sopenharmony_ci p->idx += 7; 29988c2ecf20Sopenharmony_ci break; 29998c2ecf20Sopenharmony_ci /* Copy L2T Frame to Field */ 30008c2ecf20Sopenharmony_ci case 0x48: 30018c2ecf20Sopenharmony_ci if (radeon_get_ib_value(p, idx + 2) & (1 << 31)) { 30028c2ecf20Sopenharmony_ci DRM_ERROR("bad L2T, frame to fields DMA_PACKET_COPY\n"); 30038c2ecf20Sopenharmony_ci return -EINVAL; 30048c2ecf20Sopenharmony_ci } 30058c2ecf20Sopenharmony_ci r = r600_dma_cs_next_reloc(p, &dst2_reloc); 30068c2ecf20Sopenharmony_ci if (r) { 30078c2ecf20Sopenharmony_ci DRM_ERROR("bad L2T, frame to fields DMA_PACKET_COPY\n"); 30088c2ecf20Sopenharmony_ci return -EINVAL; 30098c2ecf20Sopenharmony_ci } 30108c2ecf20Sopenharmony_ci dst_offset = radeon_get_ib_value(p, idx+1); 30118c2ecf20Sopenharmony_ci dst_offset <<= 8; 30128c2ecf20Sopenharmony_ci dst2_offset = radeon_get_ib_value(p, idx+2); 30138c2ecf20Sopenharmony_ci dst2_offset <<= 8; 30148c2ecf20Sopenharmony_ci src_offset = radeon_get_ib_value(p, idx+8); 30158c2ecf20Sopenharmony_ci src_offset |= ((u64)(radeon_get_ib_value(p, idx+9) & 0xff)) << 32; 30168c2ecf20Sopenharmony_ci if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) { 30178c2ecf20Sopenharmony_ci dev_warn(p->dev, "DMA L2T, frame to fields src buffer too small (%llu %lu)\n", 30188c2ecf20Sopenharmony_ci src_offset + (count * 4), radeon_bo_size(src_reloc->robj)); 30198c2ecf20Sopenharmony_ci return -EINVAL; 30208c2ecf20Sopenharmony_ci } 30218c2ecf20Sopenharmony_ci if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { 30228c2ecf20Sopenharmony_ci dev_warn(p->dev, "DMA L2T, frame to fields buffer too small (%llu %lu)\n", 30238c2ecf20Sopenharmony_ci dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj)); 30248c2ecf20Sopenharmony_ci return -EINVAL; 30258c2ecf20Sopenharmony_ci } 30268c2ecf20Sopenharmony_ci if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) { 30278c2ecf20Sopenharmony_ci dev_warn(p->dev, "DMA L2T, frame to fields buffer too small (%llu %lu)\n", 30288c2ecf20Sopenharmony_ci dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj)); 30298c2ecf20Sopenharmony_ci return -EINVAL; 30308c2ecf20Sopenharmony_ci } 30318c2ecf20Sopenharmony_ci ib[idx+1] += (u32)(dst_reloc->gpu_offset >> 8); 30328c2ecf20Sopenharmony_ci ib[idx+2] += (u32)(dst2_reloc->gpu_offset >> 8); 30338c2ecf20Sopenharmony_ci ib[idx+8] += (u32)(src_reloc->gpu_offset & 0xfffffffc); 30348c2ecf20Sopenharmony_ci ib[idx+9] += upper_32_bits(src_reloc->gpu_offset) & 0xff; 30358c2ecf20Sopenharmony_ci p->idx += 10; 30368c2ecf20Sopenharmony_ci break; 30378c2ecf20Sopenharmony_ci /* Copy L2T/T2L, partial */ 30388c2ecf20Sopenharmony_ci case 0x49: 30398c2ecf20Sopenharmony_ci /* L2T, T2L partial */ 30408c2ecf20Sopenharmony_ci if (p->family < CHIP_CAYMAN) { 30418c2ecf20Sopenharmony_ci DRM_ERROR("L2T, T2L Partial is cayman only !\n"); 30428c2ecf20Sopenharmony_ci return -EINVAL; 30438c2ecf20Sopenharmony_ci } 30448c2ecf20Sopenharmony_ci /* detile bit */ 30458c2ecf20Sopenharmony_ci if (radeon_get_ib_value(p, idx + 2) & (1 << 31)) { 30468c2ecf20Sopenharmony_ci /* tiled src, linear dst */ 30478c2ecf20Sopenharmony_ci ib[idx+1] += (u32)(src_reloc->gpu_offset >> 8); 30488c2ecf20Sopenharmony_ci 30498c2ecf20Sopenharmony_ci ib[idx+7] += (u32)(dst_reloc->gpu_offset & 0xfffffffc); 30508c2ecf20Sopenharmony_ci ib[idx+8] += upper_32_bits(dst_reloc->gpu_offset) & 0xff; 30518c2ecf20Sopenharmony_ci } else { 30528c2ecf20Sopenharmony_ci /* linear src, tiled dst */ 30538c2ecf20Sopenharmony_ci ib[idx+7] += (u32)(src_reloc->gpu_offset & 0xfffffffc); 30548c2ecf20Sopenharmony_ci ib[idx+8] += upper_32_bits(src_reloc->gpu_offset) & 0xff; 30558c2ecf20Sopenharmony_ci 30568c2ecf20Sopenharmony_ci ib[idx+1] += (u32)(dst_reloc->gpu_offset >> 8); 30578c2ecf20Sopenharmony_ci } 30588c2ecf20Sopenharmony_ci p->idx += 12; 30598c2ecf20Sopenharmony_ci break; 30608c2ecf20Sopenharmony_ci /* Copy L2T broadcast */ 30618c2ecf20Sopenharmony_ci case 0x4b: 30628c2ecf20Sopenharmony_ci /* L2T, broadcast */ 30638c2ecf20Sopenharmony_ci if (radeon_get_ib_value(p, idx + 2) & (1 << 31)) { 30648c2ecf20Sopenharmony_ci DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n"); 30658c2ecf20Sopenharmony_ci return -EINVAL; 30668c2ecf20Sopenharmony_ci } 30678c2ecf20Sopenharmony_ci r = r600_dma_cs_next_reloc(p, &dst2_reloc); 30688c2ecf20Sopenharmony_ci if (r) { 30698c2ecf20Sopenharmony_ci DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n"); 30708c2ecf20Sopenharmony_ci return -EINVAL; 30718c2ecf20Sopenharmony_ci } 30728c2ecf20Sopenharmony_ci dst_offset = radeon_get_ib_value(p, idx+1); 30738c2ecf20Sopenharmony_ci dst_offset <<= 8; 30748c2ecf20Sopenharmony_ci dst2_offset = radeon_get_ib_value(p, idx+2); 30758c2ecf20Sopenharmony_ci dst2_offset <<= 8; 30768c2ecf20Sopenharmony_ci src_offset = radeon_get_ib_value(p, idx+8); 30778c2ecf20Sopenharmony_ci src_offset |= ((u64)(radeon_get_ib_value(p, idx+9) & 0xff)) << 32; 30788c2ecf20Sopenharmony_ci if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) { 30798c2ecf20Sopenharmony_ci dev_warn(p->dev, "DMA L2T, broadcast src buffer too small (%llu %lu)\n", 30808c2ecf20Sopenharmony_ci src_offset + (count * 4), radeon_bo_size(src_reloc->robj)); 30818c2ecf20Sopenharmony_ci return -EINVAL; 30828c2ecf20Sopenharmony_ci } 30838c2ecf20Sopenharmony_ci if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { 30848c2ecf20Sopenharmony_ci dev_warn(p->dev, "DMA L2T, broadcast dst buffer too small (%llu %lu)\n", 30858c2ecf20Sopenharmony_ci dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj)); 30868c2ecf20Sopenharmony_ci return -EINVAL; 30878c2ecf20Sopenharmony_ci } 30888c2ecf20Sopenharmony_ci if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) { 30898c2ecf20Sopenharmony_ci dev_warn(p->dev, "DMA L2T, broadcast dst2 buffer too small (%llu %lu)\n", 30908c2ecf20Sopenharmony_ci dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj)); 30918c2ecf20Sopenharmony_ci return -EINVAL; 30928c2ecf20Sopenharmony_ci } 30938c2ecf20Sopenharmony_ci ib[idx+1] += (u32)(dst_reloc->gpu_offset >> 8); 30948c2ecf20Sopenharmony_ci ib[idx+2] += (u32)(dst2_reloc->gpu_offset >> 8); 30958c2ecf20Sopenharmony_ci ib[idx+8] += (u32)(src_reloc->gpu_offset & 0xfffffffc); 30968c2ecf20Sopenharmony_ci ib[idx+9] += upper_32_bits(src_reloc->gpu_offset) & 0xff; 30978c2ecf20Sopenharmony_ci p->idx += 10; 30988c2ecf20Sopenharmony_ci break; 30998c2ecf20Sopenharmony_ci /* Copy L2T/T2L (tile units) */ 31008c2ecf20Sopenharmony_ci case 0x4c: 31018c2ecf20Sopenharmony_ci /* L2T, T2L */ 31028c2ecf20Sopenharmony_ci /* detile bit */ 31038c2ecf20Sopenharmony_ci if (radeon_get_ib_value(p, idx + 2) & (1 << 31)) { 31048c2ecf20Sopenharmony_ci /* tiled src, linear dst */ 31058c2ecf20Sopenharmony_ci src_offset = radeon_get_ib_value(p, idx+1); 31068c2ecf20Sopenharmony_ci src_offset <<= 8; 31078c2ecf20Sopenharmony_ci ib[idx+1] += (u32)(src_reloc->gpu_offset >> 8); 31088c2ecf20Sopenharmony_ci 31098c2ecf20Sopenharmony_ci dst_offset = radeon_get_ib_value(p, idx+7); 31108c2ecf20Sopenharmony_ci dst_offset |= ((u64)(radeon_get_ib_value(p, idx+8) & 0xff)) << 32; 31118c2ecf20Sopenharmony_ci ib[idx+7] += (u32)(dst_reloc->gpu_offset & 0xfffffffc); 31128c2ecf20Sopenharmony_ci ib[idx+8] += upper_32_bits(dst_reloc->gpu_offset) & 0xff; 31138c2ecf20Sopenharmony_ci } else { 31148c2ecf20Sopenharmony_ci /* linear src, tiled dst */ 31158c2ecf20Sopenharmony_ci src_offset = radeon_get_ib_value(p, idx+7); 31168c2ecf20Sopenharmony_ci src_offset |= ((u64)(radeon_get_ib_value(p, idx+8) & 0xff)) << 32; 31178c2ecf20Sopenharmony_ci ib[idx+7] += (u32)(src_reloc->gpu_offset & 0xfffffffc); 31188c2ecf20Sopenharmony_ci ib[idx+8] += upper_32_bits(src_reloc->gpu_offset) & 0xff; 31198c2ecf20Sopenharmony_ci 31208c2ecf20Sopenharmony_ci dst_offset = radeon_get_ib_value(p, idx+1); 31218c2ecf20Sopenharmony_ci dst_offset <<= 8; 31228c2ecf20Sopenharmony_ci ib[idx+1] += (u32)(dst_reloc->gpu_offset >> 8); 31238c2ecf20Sopenharmony_ci } 31248c2ecf20Sopenharmony_ci if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) { 31258c2ecf20Sopenharmony_ci dev_warn(p->dev, "DMA L2T, T2L src buffer too small (%llu %lu)\n", 31268c2ecf20Sopenharmony_ci src_offset + (count * 4), radeon_bo_size(src_reloc->robj)); 31278c2ecf20Sopenharmony_ci return -EINVAL; 31288c2ecf20Sopenharmony_ci } 31298c2ecf20Sopenharmony_ci if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { 31308c2ecf20Sopenharmony_ci dev_warn(p->dev, "DMA L2T, T2L dst buffer too small (%llu %lu)\n", 31318c2ecf20Sopenharmony_ci dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj)); 31328c2ecf20Sopenharmony_ci return -EINVAL; 31338c2ecf20Sopenharmony_ci } 31348c2ecf20Sopenharmony_ci p->idx += 9; 31358c2ecf20Sopenharmony_ci break; 31368c2ecf20Sopenharmony_ci /* Copy T2T, partial (tile units) */ 31378c2ecf20Sopenharmony_ci case 0x4d: 31388c2ecf20Sopenharmony_ci /* T2T partial */ 31398c2ecf20Sopenharmony_ci if (p->family < CHIP_CAYMAN) { 31408c2ecf20Sopenharmony_ci DRM_ERROR("L2T, T2L Partial is cayman only !\n"); 31418c2ecf20Sopenharmony_ci return -EINVAL; 31428c2ecf20Sopenharmony_ci } 31438c2ecf20Sopenharmony_ci ib[idx+1] += (u32)(src_reloc->gpu_offset >> 8); 31448c2ecf20Sopenharmony_ci ib[idx+4] += (u32)(dst_reloc->gpu_offset >> 8); 31458c2ecf20Sopenharmony_ci p->idx += 13; 31468c2ecf20Sopenharmony_ci break; 31478c2ecf20Sopenharmony_ci /* Copy L2T broadcast (tile units) */ 31488c2ecf20Sopenharmony_ci case 0x4f: 31498c2ecf20Sopenharmony_ci /* L2T, broadcast */ 31508c2ecf20Sopenharmony_ci if (radeon_get_ib_value(p, idx + 2) & (1 << 31)) { 31518c2ecf20Sopenharmony_ci DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n"); 31528c2ecf20Sopenharmony_ci return -EINVAL; 31538c2ecf20Sopenharmony_ci } 31548c2ecf20Sopenharmony_ci r = r600_dma_cs_next_reloc(p, &dst2_reloc); 31558c2ecf20Sopenharmony_ci if (r) { 31568c2ecf20Sopenharmony_ci DRM_ERROR("bad L2T, broadcast DMA_PACKET_COPY\n"); 31578c2ecf20Sopenharmony_ci return -EINVAL; 31588c2ecf20Sopenharmony_ci } 31598c2ecf20Sopenharmony_ci dst_offset = radeon_get_ib_value(p, idx+1); 31608c2ecf20Sopenharmony_ci dst_offset <<= 8; 31618c2ecf20Sopenharmony_ci dst2_offset = radeon_get_ib_value(p, idx+2); 31628c2ecf20Sopenharmony_ci dst2_offset <<= 8; 31638c2ecf20Sopenharmony_ci src_offset = radeon_get_ib_value(p, idx+8); 31648c2ecf20Sopenharmony_ci src_offset |= ((u64)(radeon_get_ib_value(p, idx+9) & 0xff)) << 32; 31658c2ecf20Sopenharmony_ci if ((src_offset + (count * 4)) > radeon_bo_size(src_reloc->robj)) { 31668c2ecf20Sopenharmony_ci dev_warn(p->dev, "DMA L2T, broadcast src buffer too small (%llu %lu)\n", 31678c2ecf20Sopenharmony_ci src_offset + (count * 4), radeon_bo_size(src_reloc->robj)); 31688c2ecf20Sopenharmony_ci return -EINVAL; 31698c2ecf20Sopenharmony_ci } 31708c2ecf20Sopenharmony_ci if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { 31718c2ecf20Sopenharmony_ci dev_warn(p->dev, "DMA L2T, broadcast dst buffer too small (%llu %lu)\n", 31728c2ecf20Sopenharmony_ci dst_offset + (count * 4), radeon_bo_size(dst_reloc->robj)); 31738c2ecf20Sopenharmony_ci return -EINVAL; 31748c2ecf20Sopenharmony_ci } 31758c2ecf20Sopenharmony_ci if ((dst2_offset + (count * 4)) > radeon_bo_size(dst2_reloc->robj)) { 31768c2ecf20Sopenharmony_ci dev_warn(p->dev, "DMA L2T, broadcast dst2 buffer too small (%llu %lu)\n", 31778c2ecf20Sopenharmony_ci dst2_offset + (count * 4), radeon_bo_size(dst2_reloc->robj)); 31788c2ecf20Sopenharmony_ci return -EINVAL; 31798c2ecf20Sopenharmony_ci } 31808c2ecf20Sopenharmony_ci ib[idx+1] += (u32)(dst_reloc->gpu_offset >> 8); 31818c2ecf20Sopenharmony_ci ib[idx+2] += (u32)(dst2_reloc->gpu_offset >> 8); 31828c2ecf20Sopenharmony_ci ib[idx+8] += (u32)(src_reloc->gpu_offset & 0xfffffffc); 31838c2ecf20Sopenharmony_ci ib[idx+9] += upper_32_bits(src_reloc->gpu_offset) & 0xff; 31848c2ecf20Sopenharmony_ci p->idx += 10; 31858c2ecf20Sopenharmony_ci break; 31868c2ecf20Sopenharmony_ci default: 31878c2ecf20Sopenharmony_ci DRM_ERROR("bad DMA_PACKET_COPY [%6d] 0x%08x invalid sub cmd\n", idx, header); 31888c2ecf20Sopenharmony_ci return -EINVAL; 31898c2ecf20Sopenharmony_ci } 31908c2ecf20Sopenharmony_ci break; 31918c2ecf20Sopenharmony_ci case DMA_PACKET_CONSTANT_FILL: 31928c2ecf20Sopenharmony_ci r = r600_dma_cs_next_reloc(p, &dst_reloc); 31938c2ecf20Sopenharmony_ci if (r) { 31948c2ecf20Sopenharmony_ci DRM_ERROR("bad DMA_PACKET_CONSTANT_FILL\n"); 31958c2ecf20Sopenharmony_ci return -EINVAL; 31968c2ecf20Sopenharmony_ci } 31978c2ecf20Sopenharmony_ci dst_offset = radeon_get_ib_value(p, idx+1); 31988c2ecf20Sopenharmony_ci dst_offset |= ((u64)(radeon_get_ib_value(p, idx+3) & 0x00ff0000)) << 16; 31998c2ecf20Sopenharmony_ci if ((dst_offset + (count * 4)) > radeon_bo_size(dst_reloc->robj)) { 32008c2ecf20Sopenharmony_ci dev_warn(p->dev, "DMA constant fill buffer too small (%llu %lu)\n", 32018c2ecf20Sopenharmony_ci dst_offset, radeon_bo_size(dst_reloc->robj)); 32028c2ecf20Sopenharmony_ci return -EINVAL; 32038c2ecf20Sopenharmony_ci } 32048c2ecf20Sopenharmony_ci ib[idx+1] += (u32)(dst_reloc->gpu_offset & 0xfffffffc); 32058c2ecf20Sopenharmony_ci ib[idx+3] += (upper_32_bits(dst_reloc->gpu_offset) << 16) & 0x00ff0000; 32068c2ecf20Sopenharmony_ci p->idx += 4; 32078c2ecf20Sopenharmony_ci break; 32088c2ecf20Sopenharmony_ci case DMA_PACKET_NOP: 32098c2ecf20Sopenharmony_ci p->idx += 1; 32108c2ecf20Sopenharmony_ci break; 32118c2ecf20Sopenharmony_ci default: 32128c2ecf20Sopenharmony_ci DRM_ERROR("Unknown packet type %d at %d !\n", cmd, idx); 32138c2ecf20Sopenharmony_ci return -EINVAL; 32148c2ecf20Sopenharmony_ci } 32158c2ecf20Sopenharmony_ci } while (p->idx < p->chunk_ib->length_dw); 32168c2ecf20Sopenharmony_ci#if 0 32178c2ecf20Sopenharmony_ci for (r = 0; r < p->ib->length_dw; r++) { 32188c2ecf20Sopenharmony_ci pr_info("%05d 0x%08X\n", r, p->ib.ptr[r]); 32198c2ecf20Sopenharmony_ci mdelay(1); 32208c2ecf20Sopenharmony_ci } 32218c2ecf20Sopenharmony_ci#endif 32228c2ecf20Sopenharmony_ci return 0; 32238c2ecf20Sopenharmony_ci} 32248c2ecf20Sopenharmony_ci 32258c2ecf20Sopenharmony_ci/* vm parser */ 32268c2ecf20Sopenharmony_cistatic bool evergreen_vm_reg_valid(u32 reg) 32278c2ecf20Sopenharmony_ci{ 32288c2ecf20Sopenharmony_ci /* context regs are fine */ 32298c2ecf20Sopenharmony_ci if (reg >= 0x28000) 32308c2ecf20Sopenharmony_ci return true; 32318c2ecf20Sopenharmony_ci 32328c2ecf20Sopenharmony_ci /* check config regs */ 32338c2ecf20Sopenharmony_ci switch (reg) { 32348c2ecf20Sopenharmony_ci case WAIT_UNTIL: 32358c2ecf20Sopenharmony_ci case GRBM_GFX_INDEX: 32368c2ecf20Sopenharmony_ci case CP_STRMOUT_CNTL: 32378c2ecf20Sopenharmony_ci case CP_COHER_CNTL: 32388c2ecf20Sopenharmony_ci case CP_COHER_SIZE: 32398c2ecf20Sopenharmony_ci case VGT_VTX_VECT_EJECT_REG: 32408c2ecf20Sopenharmony_ci case VGT_CACHE_INVALIDATION: 32418c2ecf20Sopenharmony_ci case VGT_GS_VERTEX_REUSE: 32428c2ecf20Sopenharmony_ci case VGT_PRIMITIVE_TYPE: 32438c2ecf20Sopenharmony_ci case VGT_INDEX_TYPE: 32448c2ecf20Sopenharmony_ci case VGT_NUM_INDICES: 32458c2ecf20Sopenharmony_ci case VGT_NUM_INSTANCES: 32468c2ecf20Sopenharmony_ci case VGT_COMPUTE_DIM_X: 32478c2ecf20Sopenharmony_ci case VGT_COMPUTE_DIM_Y: 32488c2ecf20Sopenharmony_ci case VGT_COMPUTE_DIM_Z: 32498c2ecf20Sopenharmony_ci case VGT_COMPUTE_START_X: 32508c2ecf20Sopenharmony_ci case VGT_COMPUTE_START_Y: 32518c2ecf20Sopenharmony_ci case VGT_COMPUTE_START_Z: 32528c2ecf20Sopenharmony_ci case VGT_COMPUTE_INDEX: 32538c2ecf20Sopenharmony_ci case VGT_COMPUTE_THREAD_GROUP_SIZE: 32548c2ecf20Sopenharmony_ci case VGT_HS_OFFCHIP_PARAM: 32558c2ecf20Sopenharmony_ci case PA_CL_ENHANCE: 32568c2ecf20Sopenharmony_ci case PA_SU_LINE_STIPPLE_VALUE: 32578c2ecf20Sopenharmony_ci case PA_SC_LINE_STIPPLE_STATE: 32588c2ecf20Sopenharmony_ci case PA_SC_ENHANCE: 32598c2ecf20Sopenharmony_ci case SQ_DYN_GPR_CNTL_PS_FLUSH_REQ: 32608c2ecf20Sopenharmony_ci case SQ_DYN_GPR_SIMD_LOCK_EN: 32618c2ecf20Sopenharmony_ci case SQ_CONFIG: 32628c2ecf20Sopenharmony_ci case SQ_GPR_RESOURCE_MGMT_1: 32638c2ecf20Sopenharmony_ci case SQ_GLOBAL_GPR_RESOURCE_MGMT_1: 32648c2ecf20Sopenharmony_ci case SQ_GLOBAL_GPR_RESOURCE_MGMT_2: 32658c2ecf20Sopenharmony_ci case SQ_CONST_MEM_BASE: 32668c2ecf20Sopenharmony_ci case SQ_STATIC_THREAD_MGMT_1: 32678c2ecf20Sopenharmony_ci case SQ_STATIC_THREAD_MGMT_2: 32688c2ecf20Sopenharmony_ci case SQ_STATIC_THREAD_MGMT_3: 32698c2ecf20Sopenharmony_ci case SPI_CONFIG_CNTL: 32708c2ecf20Sopenharmony_ci case SPI_CONFIG_CNTL_1: 32718c2ecf20Sopenharmony_ci case TA_CNTL_AUX: 32728c2ecf20Sopenharmony_ci case DB_DEBUG: 32738c2ecf20Sopenharmony_ci case DB_DEBUG2: 32748c2ecf20Sopenharmony_ci case DB_DEBUG3: 32758c2ecf20Sopenharmony_ci case DB_DEBUG4: 32768c2ecf20Sopenharmony_ci case DB_WATERMARKS: 32778c2ecf20Sopenharmony_ci case TD_PS_BORDER_COLOR_INDEX: 32788c2ecf20Sopenharmony_ci case TD_PS_BORDER_COLOR_RED: 32798c2ecf20Sopenharmony_ci case TD_PS_BORDER_COLOR_GREEN: 32808c2ecf20Sopenharmony_ci case TD_PS_BORDER_COLOR_BLUE: 32818c2ecf20Sopenharmony_ci case TD_PS_BORDER_COLOR_ALPHA: 32828c2ecf20Sopenharmony_ci case TD_VS_BORDER_COLOR_INDEX: 32838c2ecf20Sopenharmony_ci case TD_VS_BORDER_COLOR_RED: 32848c2ecf20Sopenharmony_ci case TD_VS_BORDER_COLOR_GREEN: 32858c2ecf20Sopenharmony_ci case TD_VS_BORDER_COLOR_BLUE: 32868c2ecf20Sopenharmony_ci case TD_VS_BORDER_COLOR_ALPHA: 32878c2ecf20Sopenharmony_ci case TD_GS_BORDER_COLOR_INDEX: 32888c2ecf20Sopenharmony_ci case TD_GS_BORDER_COLOR_RED: 32898c2ecf20Sopenharmony_ci case TD_GS_BORDER_COLOR_GREEN: 32908c2ecf20Sopenharmony_ci case TD_GS_BORDER_COLOR_BLUE: 32918c2ecf20Sopenharmony_ci case TD_GS_BORDER_COLOR_ALPHA: 32928c2ecf20Sopenharmony_ci case TD_HS_BORDER_COLOR_INDEX: 32938c2ecf20Sopenharmony_ci case TD_HS_BORDER_COLOR_RED: 32948c2ecf20Sopenharmony_ci case TD_HS_BORDER_COLOR_GREEN: 32958c2ecf20Sopenharmony_ci case TD_HS_BORDER_COLOR_BLUE: 32968c2ecf20Sopenharmony_ci case TD_HS_BORDER_COLOR_ALPHA: 32978c2ecf20Sopenharmony_ci case TD_LS_BORDER_COLOR_INDEX: 32988c2ecf20Sopenharmony_ci case TD_LS_BORDER_COLOR_RED: 32998c2ecf20Sopenharmony_ci case TD_LS_BORDER_COLOR_GREEN: 33008c2ecf20Sopenharmony_ci case TD_LS_BORDER_COLOR_BLUE: 33018c2ecf20Sopenharmony_ci case TD_LS_BORDER_COLOR_ALPHA: 33028c2ecf20Sopenharmony_ci case TD_CS_BORDER_COLOR_INDEX: 33038c2ecf20Sopenharmony_ci case TD_CS_BORDER_COLOR_RED: 33048c2ecf20Sopenharmony_ci case TD_CS_BORDER_COLOR_GREEN: 33058c2ecf20Sopenharmony_ci case TD_CS_BORDER_COLOR_BLUE: 33068c2ecf20Sopenharmony_ci case TD_CS_BORDER_COLOR_ALPHA: 33078c2ecf20Sopenharmony_ci case SQ_ESGS_RING_SIZE: 33088c2ecf20Sopenharmony_ci case SQ_GSVS_RING_SIZE: 33098c2ecf20Sopenharmony_ci case SQ_ESTMP_RING_SIZE: 33108c2ecf20Sopenharmony_ci case SQ_GSTMP_RING_SIZE: 33118c2ecf20Sopenharmony_ci case SQ_HSTMP_RING_SIZE: 33128c2ecf20Sopenharmony_ci case SQ_LSTMP_RING_SIZE: 33138c2ecf20Sopenharmony_ci case SQ_PSTMP_RING_SIZE: 33148c2ecf20Sopenharmony_ci case SQ_VSTMP_RING_SIZE: 33158c2ecf20Sopenharmony_ci case SQ_ESGS_RING_ITEMSIZE: 33168c2ecf20Sopenharmony_ci case SQ_ESTMP_RING_ITEMSIZE: 33178c2ecf20Sopenharmony_ci case SQ_GSTMP_RING_ITEMSIZE: 33188c2ecf20Sopenharmony_ci case SQ_GSVS_RING_ITEMSIZE: 33198c2ecf20Sopenharmony_ci case SQ_GS_VERT_ITEMSIZE: 33208c2ecf20Sopenharmony_ci case SQ_GS_VERT_ITEMSIZE_1: 33218c2ecf20Sopenharmony_ci case SQ_GS_VERT_ITEMSIZE_2: 33228c2ecf20Sopenharmony_ci case SQ_GS_VERT_ITEMSIZE_3: 33238c2ecf20Sopenharmony_ci case SQ_GSVS_RING_OFFSET_1: 33248c2ecf20Sopenharmony_ci case SQ_GSVS_RING_OFFSET_2: 33258c2ecf20Sopenharmony_ci case SQ_GSVS_RING_OFFSET_3: 33268c2ecf20Sopenharmony_ci case SQ_HSTMP_RING_ITEMSIZE: 33278c2ecf20Sopenharmony_ci case SQ_LSTMP_RING_ITEMSIZE: 33288c2ecf20Sopenharmony_ci case SQ_PSTMP_RING_ITEMSIZE: 33298c2ecf20Sopenharmony_ci case SQ_VSTMP_RING_ITEMSIZE: 33308c2ecf20Sopenharmony_ci case VGT_TF_RING_SIZE: 33318c2ecf20Sopenharmony_ci case SQ_ESGS_RING_BASE: 33328c2ecf20Sopenharmony_ci case SQ_GSVS_RING_BASE: 33338c2ecf20Sopenharmony_ci case SQ_ESTMP_RING_BASE: 33348c2ecf20Sopenharmony_ci case SQ_GSTMP_RING_BASE: 33358c2ecf20Sopenharmony_ci case SQ_HSTMP_RING_BASE: 33368c2ecf20Sopenharmony_ci case SQ_LSTMP_RING_BASE: 33378c2ecf20Sopenharmony_ci case SQ_PSTMP_RING_BASE: 33388c2ecf20Sopenharmony_ci case SQ_VSTMP_RING_BASE: 33398c2ecf20Sopenharmony_ci case CAYMAN_VGT_OFFCHIP_LDS_BASE: 33408c2ecf20Sopenharmony_ci case CAYMAN_SQ_EX_ALLOC_TABLE_SLOTS: 33418c2ecf20Sopenharmony_ci return true; 33428c2ecf20Sopenharmony_ci default: 33438c2ecf20Sopenharmony_ci DRM_ERROR("Invalid register 0x%x in CS\n", reg); 33448c2ecf20Sopenharmony_ci return false; 33458c2ecf20Sopenharmony_ci } 33468c2ecf20Sopenharmony_ci} 33478c2ecf20Sopenharmony_ci 33488c2ecf20Sopenharmony_cistatic int evergreen_vm_packet3_check(struct radeon_device *rdev, 33498c2ecf20Sopenharmony_ci u32 *ib, struct radeon_cs_packet *pkt) 33508c2ecf20Sopenharmony_ci{ 33518c2ecf20Sopenharmony_ci u32 idx = pkt->idx + 1; 33528c2ecf20Sopenharmony_ci u32 idx_value = ib[idx]; 33538c2ecf20Sopenharmony_ci u32 start_reg, end_reg, reg, i; 33548c2ecf20Sopenharmony_ci u32 command, info; 33558c2ecf20Sopenharmony_ci 33568c2ecf20Sopenharmony_ci switch (pkt->opcode) { 33578c2ecf20Sopenharmony_ci case PACKET3_NOP: 33588c2ecf20Sopenharmony_ci break; 33598c2ecf20Sopenharmony_ci case PACKET3_SET_BASE: 33608c2ecf20Sopenharmony_ci if (idx_value != 1) { 33618c2ecf20Sopenharmony_ci DRM_ERROR("bad SET_BASE"); 33628c2ecf20Sopenharmony_ci return -EINVAL; 33638c2ecf20Sopenharmony_ci } 33648c2ecf20Sopenharmony_ci break; 33658c2ecf20Sopenharmony_ci case PACKET3_CLEAR_STATE: 33668c2ecf20Sopenharmony_ci case PACKET3_INDEX_BUFFER_SIZE: 33678c2ecf20Sopenharmony_ci case PACKET3_DISPATCH_DIRECT: 33688c2ecf20Sopenharmony_ci case PACKET3_DISPATCH_INDIRECT: 33698c2ecf20Sopenharmony_ci case PACKET3_MODE_CONTROL: 33708c2ecf20Sopenharmony_ci case PACKET3_SET_PREDICATION: 33718c2ecf20Sopenharmony_ci case PACKET3_COND_EXEC: 33728c2ecf20Sopenharmony_ci case PACKET3_PRED_EXEC: 33738c2ecf20Sopenharmony_ci case PACKET3_DRAW_INDIRECT: 33748c2ecf20Sopenharmony_ci case PACKET3_DRAW_INDEX_INDIRECT: 33758c2ecf20Sopenharmony_ci case PACKET3_INDEX_BASE: 33768c2ecf20Sopenharmony_ci case PACKET3_DRAW_INDEX_2: 33778c2ecf20Sopenharmony_ci case PACKET3_CONTEXT_CONTROL: 33788c2ecf20Sopenharmony_ci case PACKET3_DRAW_INDEX_OFFSET: 33798c2ecf20Sopenharmony_ci case PACKET3_INDEX_TYPE: 33808c2ecf20Sopenharmony_ci case PACKET3_DRAW_INDEX: 33818c2ecf20Sopenharmony_ci case PACKET3_DRAW_INDEX_AUTO: 33828c2ecf20Sopenharmony_ci case PACKET3_DRAW_INDEX_IMMD: 33838c2ecf20Sopenharmony_ci case PACKET3_NUM_INSTANCES: 33848c2ecf20Sopenharmony_ci case PACKET3_DRAW_INDEX_MULTI_AUTO: 33858c2ecf20Sopenharmony_ci case PACKET3_STRMOUT_BUFFER_UPDATE: 33868c2ecf20Sopenharmony_ci case PACKET3_DRAW_INDEX_OFFSET_2: 33878c2ecf20Sopenharmony_ci case PACKET3_DRAW_INDEX_MULTI_ELEMENT: 33888c2ecf20Sopenharmony_ci case PACKET3_MPEG_INDEX: 33898c2ecf20Sopenharmony_ci case PACKET3_WAIT_REG_MEM: 33908c2ecf20Sopenharmony_ci case PACKET3_MEM_WRITE: 33918c2ecf20Sopenharmony_ci case PACKET3_PFP_SYNC_ME: 33928c2ecf20Sopenharmony_ci case PACKET3_SURFACE_SYNC: 33938c2ecf20Sopenharmony_ci case PACKET3_EVENT_WRITE: 33948c2ecf20Sopenharmony_ci case PACKET3_EVENT_WRITE_EOP: 33958c2ecf20Sopenharmony_ci case PACKET3_EVENT_WRITE_EOS: 33968c2ecf20Sopenharmony_ci case PACKET3_SET_CONTEXT_REG: 33978c2ecf20Sopenharmony_ci case PACKET3_SET_BOOL_CONST: 33988c2ecf20Sopenharmony_ci case PACKET3_SET_LOOP_CONST: 33998c2ecf20Sopenharmony_ci case PACKET3_SET_RESOURCE: 34008c2ecf20Sopenharmony_ci case PACKET3_SET_SAMPLER: 34018c2ecf20Sopenharmony_ci case PACKET3_SET_CTL_CONST: 34028c2ecf20Sopenharmony_ci case PACKET3_SET_RESOURCE_OFFSET: 34038c2ecf20Sopenharmony_ci case PACKET3_SET_CONTEXT_REG_INDIRECT: 34048c2ecf20Sopenharmony_ci case PACKET3_SET_RESOURCE_INDIRECT: 34058c2ecf20Sopenharmony_ci case CAYMAN_PACKET3_DEALLOC_STATE: 34068c2ecf20Sopenharmony_ci break; 34078c2ecf20Sopenharmony_ci case PACKET3_COND_WRITE: 34088c2ecf20Sopenharmony_ci if (idx_value & 0x100) { 34098c2ecf20Sopenharmony_ci reg = ib[idx + 5] * 4; 34108c2ecf20Sopenharmony_ci if (!evergreen_vm_reg_valid(reg)) 34118c2ecf20Sopenharmony_ci return -EINVAL; 34128c2ecf20Sopenharmony_ci } 34138c2ecf20Sopenharmony_ci break; 34148c2ecf20Sopenharmony_ci case PACKET3_COPY_DW: 34158c2ecf20Sopenharmony_ci if (idx_value & 0x2) { 34168c2ecf20Sopenharmony_ci reg = ib[idx + 3] * 4; 34178c2ecf20Sopenharmony_ci if (!evergreen_vm_reg_valid(reg)) 34188c2ecf20Sopenharmony_ci return -EINVAL; 34198c2ecf20Sopenharmony_ci } 34208c2ecf20Sopenharmony_ci break; 34218c2ecf20Sopenharmony_ci case PACKET3_SET_CONFIG_REG: 34228c2ecf20Sopenharmony_ci start_reg = (idx_value << 2) + PACKET3_SET_CONFIG_REG_START; 34238c2ecf20Sopenharmony_ci end_reg = 4 * pkt->count + start_reg - 4; 34248c2ecf20Sopenharmony_ci if ((start_reg < PACKET3_SET_CONFIG_REG_START) || 34258c2ecf20Sopenharmony_ci (start_reg >= PACKET3_SET_CONFIG_REG_END) || 34268c2ecf20Sopenharmony_ci (end_reg >= PACKET3_SET_CONFIG_REG_END)) { 34278c2ecf20Sopenharmony_ci DRM_ERROR("bad PACKET3_SET_CONFIG_REG\n"); 34288c2ecf20Sopenharmony_ci return -EINVAL; 34298c2ecf20Sopenharmony_ci } 34308c2ecf20Sopenharmony_ci for (i = 0; i < pkt->count; i++) { 34318c2ecf20Sopenharmony_ci reg = start_reg + (4 * i); 34328c2ecf20Sopenharmony_ci if (!evergreen_vm_reg_valid(reg)) 34338c2ecf20Sopenharmony_ci return -EINVAL; 34348c2ecf20Sopenharmony_ci } 34358c2ecf20Sopenharmony_ci break; 34368c2ecf20Sopenharmony_ci case PACKET3_CP_DMA: 34378c2ecf20Sopenharmony_ci command = ib[idx + 4]; 34388c2ecf20Sopenharmony_ci info = ib[idx + 1]; 34398c2ecf20Sopenharmony_ci if ((((info & 0x60000000) >> 29) != 0) || /* src = GDS or DATA */ 34408c2ecf20Sopenharmony_ci (((info & 0x00300000) >> 20) != 0) || /* dst = GDS */ 34418c2ecf20Sopenharmony_ci ((((info & 0x00300000) >> 20) == 0) && 34428c2ecf20Sopenharmony_ci (command & PACKET3_CP_DMA_CMD_DAS)) || /* dst = register */ 34438c2ecf20Sopenharmony_ci ((((info & 0x60000000) >> 29) == 0) && 34448c2ecf20Sopenharmony_ci (command & PACKET3_CP_DMA_CMD_SAS))) { /* src = register */ 34458c2ecf20Sopenharmony_ci /* non mem to mem copies requires dw aligned count */ 34468c2ecf20Sopenharmony_ci if ((command & 0x1fffff) % 4) { 34478c2ecf20Sopenharmony_ci DRM_ERROR("CP DMA command requires dw count alignment\n"); 34488c2ecf20Sopenharmony_ci return -EINVAL; 34498c2ecf20Sopenharmony_ci } 34508c2ecf20Sopenharmony_ci } 34518c2ecf20Sopenharmony_ci if (command & PACKET3_CP_DMA_CMD_SAS) { 34528c2ecf20Sopenharmony_ci /* src address space is register */ 34538c2ecf20Sopenharmony_ci if (((info & 0x60000000) >> 29) == 0) { 34548c2ecf20Sopenharmony_ci start_reg = idx_value << 2; 34558c2ecf20Sopenharmony_ci if (command & PACKET3_CP_DMA_CMD_SAIC) { 34568c2ecf20Sopenharmony_ci reg = start_reg; 34578c2ecf20Sopenharmony_ci if (!evergreen_vm_reg_valid(reg)) { 34588c2ecf20Sopenharmony_ci DRM_ERROR("CP DMA Bad SRC register\n"); 34598c2ecf20Sopenharmony_ci return -EINVAL; 34608c2ecf20Sopenharmony_ci } 34618c2ecf20Sopenharmony_ci } else { 34628c2ecf20Sopenharmony_ci for (i = 0; i < (command & 0x1fffff); i++) { 34638c2ecf20Sopenharmony_ci reg = start_reg + (4 * i); 34648c2ecf20Sopenharmony_ci if (!evergreen_vm_reg_valid(reg)) { 34658c2ecf20Sopenharmony_ci DRM_ERROR("CP DMA Bad SRC register\n"); 34668c2ecf20Sopenharmony_ci return -EINVAL; 34678c2ecf20Sopenharmony_ci } 34688c2ecf20Sopenharmony_ci } 34698c2ecf20Sopenharmony_ci } 34708c2ecf20Sopenharmony_ci } 34718c2ecf20Sopenharmony_ci } 34728c2ecf20Sopenharmony_ci if (command & PACKET3_CP_DMA_CMD_DAS) { 34738c2ecf20Sopenharmony_ci /* dst address space is register */ 34748c2ecf20Sopenharmony_ci if (((info & 0x00300000) >> 20) == 0) { 34758c2ecf20Sopenharmony_ci start_reg = ib[idx + 2]; 34768c2ecf20Sopenharmony_ci if (command & PACKET3_CP_DMA_CMD_DAIC) { 34778c2ecf20Sopenharmony_ci reg = start_reg; 34788c2ecf20Sopenharmony_ci if (!evergreen_vm_reg_valid(reg)) { 34798c2ecf20Sopenharmony_ci DRM_ERROR("CP DMA Bad DST register\n"); 34808c2ecf20Sopenharmony_ci return -EINVAL; 34818c2ecf20Sopenharmony_ci } 34828c2ecf20Sopenharmony_ci } else { 34838c2ecf20Sopenharmony_ci for (i = 0; i < (command & 0x1fffff); i++) { 34848c2ecf20Sopenharmony_ci reg = start_reg + (4 * i); 34858c2ecf20Sopenharmony_ci if (!evergreen_vm_reg_valid(reg)) { 34868c2ecf20Sopenharmony_ci DRM_ERROR("CP DMA Bad DST register\n"); 34878c2ecf20Sopenharmony_ci return -EINVAL; 34888c2ecf20Sopenharmony_ci } 34898c2ecf20Sopenharmony_ci } 34908c2ecf20Sopenharmony_ci } 34918c2ecf20Sopenharmony_ci } 34928c2ecf20Sopenharmony_ci } 34938c2ecf20Sopenharmony_ci break; 34948c2ecf20Sopenharmony_ci case PACKET3_SET_APPEND_CNT: { 34958c2ecf20Sopenharmony_ci uint32_t areg; 34968c2ecf20Sopenharmony_ci uint32_t allowed_reg_base; 34978c2ecf20Sopenharmony_ci 34988c2ecf20Sopenharmony_ci if (pkt->count != 2) { 34998c2ecf20Sopenharmony_ci DRM_ERROR("bad SET_APPEND_CNT (invalid count)\n"); 35008c2ecf20Sopenharmony_ci return -EINVAL; 35018c2ecf20Sopenharmony_ci } 35028c2ecf20Sopenharmony_ci 35038c2ecf20Sopenharmony_ci allowed_reg_base = GDS_APPEND_COUNT_0; 35048c2ecf20Sopenharmony_ci allowed_reg_base -= PACKET3_SET_CONTEXT_REG_START; 35058c2ecf20Sopenharmony_ci allowed_reg_base >>= 2; 35068c2ecf20Sopenharmony_ci 35078c2ecf20Sopenharmony_ci areg = idx_value >> 16; 35088c2ecf20Sopenharmony_ci if (areg < allowed_reg_base || areg > (allowed_reg_base + 11)) { 35098c2ecf20Sopenharmony_ci DRM_ERROR("forbidden register for append cnt 0x%08x at %d\n", 35108c2ecf20Sopenharmony_ci areg, idx); 35118c2ecf20Sopenharmony_ci return -EINVAL; 35128c2ecf20Sopenharmony_ci } 35138c2ecf20Sopenharmony_ci break; 35148c2ecf20Sopenharmony_ci } 35158c2ecf20Sopenharmony_ci default: 35168c2ecf20Sopenharmony_ci return -EINVAL; 35178c2ecf20Sopenharmony_ci } 35188c2ecf20Sopenharmony_ci return 0; 35198c2ecf20Sopenharmony_ci} 35208c2ecf20Sopenharmony_ci 35218c2ecf20Sopenharmony_ciint evergreen_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib) 35228c2ecf20Sopenharmony_ci{ 35238c2ecf20Sopenharmony_ci int ret = 0; 35248c2ecf20Sopenharmony_ci u32 idx = 0; 35258c2ecf20Sopenharmony_ci struct radeon_cs_packet pkt; 35268c2ecf20Sopenharmony_ci 35278c2ecf20Sopenharmony_ci do { 35288c2ecf20Sopenharmony_ci pkt.idx = idx; 35298c2ecf20Sopenharmony_ci pkt.type = RADEON_CP_PACKET_GET_TYPE(ib->ptr[idx]); 35308c2ecf20Sopenharmony_ci pkt.count = RADEON_CP_PACKET_GET_COUNT(ib->ptr[idx]); 35318c2ecf20Sopenharmony_ci pkt.one_reg_wr = 0; 35328c2ecf20Sopenharmony_ci switch (pkt.type) { 35338c2ecf20Sopenharmony_ci case RADEON_PACKET_TYPE0: 35348c2ecf20Sopenharmony_ci dev_err(rdev->dev, "Packet0 not allowed!\n"); 35358c2ecf20Sopenharmony_ci ret = -EINVAL; 35368c2ecf20Sopenharmony_ci break; 35378c2ecf20Sopenharmony_ci case RADEON_PACKET_TYPE2: 35388c2ecf20Sopenharmony_ci idx += 1; 35398c2ecf20Sopenharmony_ci break; 35408c2ecf20Sopenharmony_ci case RADEON_PACKET_TYPE3: 35418c2ecf20Sopenharmony_ci pkt.opcode = RADEON_CP_PACKET3_GET_OPCODE(ib->ptr[idx]); 35428c2ecf20Sopenharmony_ci ret = evergreen_vm_packet3_check(rdev, ib->ptr, &pkt); 35438c2ecf20Sopenharmony_ci idx += pkt.count + 2; 35448c2ecf20Sopenharmony_ci break; 35458c2ecf20Sopenharmony_ci default: 35468c2ecf20Sopenharmony_ci dev_err(rdev->dev, "Unknown packet type %d !\n", pkt.type); 35478c2ecf20Sopenharmony_ci ret = -EINVAL; 35488c2ecf20Sopenharmony_ci break; 35498c2ecf20Sopenharmony_ci } 35508c2ecf20Sopenharmony_ci if (ret) 35518c2ecf20Sopenharmony_ci break; 35528c2ecf20Sopenharmony_ci } while (idx < ib->length_dw); 35538c2ecf20Sopenharmony_ci 35548c2ecf20Sopenharmony_ci return ret; 35558c2ecf20Sopenharmony_ci} 35568c2ecf20Sopenharmony_ci 35578c2ecf20Sopenharmony_ci/** 35588c2ecf20Sopenharmony_ci * evergreen_dma_ib_parse() - parse the DMA IB for VM 35598c2ecf20Sopenharmony_ci * @rdev: radeon_device pointer 35608c2ecf20Sopenharmony_ci * @ib: radeon_ib pointer 35618c2ecf20Sopenharmony_ci * 35628c2ecf20Sopenharmony_ci * Parses the DMA IB from the VM CS ioctl 35638c2ecf20Sopenharmony_ci * checks for errors. (Cayman-SI) 35648c2ecf20Sopenharmony_ci * Returns 0 for success and an error on failure. 35658c2ecf20Sopenharmony_ci **/ 35668c2ecf20Sopenharmony_ciint evergreen_dma_ib_parse(struct radeon_device *rdev, struct radeon_ib *ib) 35678c2ecf20Sopenharmony_ci{ 35688c2ecf20Sopenharmony_ci u32 idx = 0; 35698c2ecf20Sopenharmony_ci u32 header, cmd, count, sub_cmd; 35708c2ecf20Sopenharmony_ci 35718c2ecf20Sopenharmony_ci do { 35728c2ecf20Sopenharmony_ci header = ib->ptr[idx]; 35738c2ecf20Sopenharmony_ci cmd = GET_DMA_CMD(header); 35748c2ecf20Sopenharmony_ci count = GET_DMA_COUNT(header); 35758c2ecf20Sopenharmony_ci sub_cmd = GET_DMA_SUB_CMD(header); 35768c2ecf20Sopenharmony_ci 35778c2ecf20Sopenharmony_ci switch (cmd) { 35788c2ecf20Sopenharmony_ci case DMA_PACKET_WRITE: 35798c2ecf20Sopenharmony_ci switch (sub_cmd) { 35808c2ecf20Sopenharmony_ci /* tiled */ 35818c2ecf20Sopenharmony_ci case 8: 35828c2ecf20Sopenharmony_ci idx += count + 7; 35838c2ecf20Sopenharmony_ci break; 35848c2ecf20Sopenharmony_ci /* linear */ 35858c2ecf20Sopenharmony_ci case 0: 35868c2ecf20Sopenharmony_ci idx += count + 3; 35878c2ecf20Sopenharmony_ci break; 35888c2ecf20Sopenharmony_ci default: 35898c2ecf20Sopenharmony_ci DRM_ERROR("bad DMA_PACKET_WRITE [%6d] 0x%08x sub cmd is not 0 or 8\n", idx, ib->ptr[idx]); 35908c2ecf20Sopenharmony_ci return -EINVAL; 35918c2ecf20Sopenharmony_ci } 35928c2ecf20Sopenharmony_ci break; 35938c2ecf20Sopenharmony_ci case DMA_PACKET_COPY: 35948c2ecf20Sopenharmony_ci switch (sub_cmd) { 35958c2ecf20Sopenharmony_ci /* Copy L2L, DW aligned */ 35968c2ecf20Sopenharmony_ci case 0x00: 35978c2ecf20Sopenharmony_ci idx += 5; 35988c2ecf20Sopenharmony_ci break; 35998c2ecf20Sopenharmony_ci /* Copy L2T/T2L */ 36008c2ecf20Sopenharmony_ci case 0x08: 36018c2ecf20Sopenharmony_ci idx += 9; 36028c2ecf20Sopenharmony_ci break; 36038c2ecf20Sopenharmony_ci /* Copy L2L, byte aligned */ 36048c2ecf20Sopenharmony_ci case 0x40: 36058c2ecf20Sopenharmony_ci idx += 5; 36068c2ecf20Sopenharmony_ci break; 36078c2ecf20Sopenharmony_ci /* Copy L2L, partial */ 36088c2ecf20Sopenharmony_ci case 0x41: 36098c2ecf20Sopenharmony_ci idx += 9; 36108c2ecf20Sopenharmony_ci break; 36118c2ecf20Sopenharmony_ci /* Copy L2L, DW aligned, broadcast */ 36128c2ecf20Sopenharmony_ci case 0x44: 36138c2ecf20Sopenharmony_ci idx += 7; 36148c2ecf20Sopenharmony_ci break; 36158c2ecf20Sopenharmony_ci /* Copy L2T Frame to Field */ 36168c2ecf20Sopenharmony_ci case 0x48: 36178c2ecf20Sopenharmony_ci idx += 10; 36188c2ecf20Sopenharmony_ci break; 36198c2ecf20Sopenharmony_ci /* Copy L2T/T2L, partial */ 36208c2ecf20Sopenharmony_ci case 0x49: 36218c2ecf20Sopenharmony_ci idx += 12; 36228c2ecf20Sopenharmony_ci break; 36238c2ecf20Sopenharmony_ci /* Copy L2T broadcast */ 36248c2ecf20Sopenharmony_ci case 0x4b: 36258c2ecf20Sopenharmony_ci idx += 10; 36268c2ecf20Sopenharmony_ci break; 36278c2ecf20Sopenharmony_ci /* Copy L2T/T2L (tile units) */ 36288c2ecf20Sopenharmony_ci case 0x4c: 36298c2ecf20Sopenharmony_ci idx += 9; 36308c2ecf20Sopenharmony_ci break; 36318c2ecf20Sopenharmony_ci /* Copy T2T, partial (tile units) */ 36328c2ecf20Sopenharmony_ci case 0x4d: 36338c2ecf20Sopenharmony_ci idx += 13; 36348c2ecf20Sopenharmony_ci break; 36358c2ecf20Sopenharmony_ci /* Copy L2T broadcast (tile units) */ 36368c2ecf20Sopenharmony_ci case 0x4f: 36378c2ecf20Sopenharmony_ci idx += 10; 36388c2ecf20Sopenharmony_ci break; 36398c2ecf20Sopenharmony_ci default: 36408c2ecf20Sopenharmony_ci DRM_ERROR("bad DMA_PACKET_COPY [%6d] 0x%08x invalid sub cmd\n", idx, ib->ptr[idx]); 36418c2ecf20Sopenharmony_ci return -EINVAL; 36428c2ecf20Sopenharmony_ci } 36438c2ecf20Sopenharmony_ci break; 36448c2ecf20Sopenharmony_ci case DMA_PACKET_CONSTANT_FILL: 36458c2ecf20Sopenharmony_ci idx += 4; 36468c2ecf20Sopenharmony_ci break; 36478c2ecf20Sopenharmony_ci case DMA_PACKET_NOP: 36488c2ecf20Sopenharmony_ci idx += 1; 36498c2ecf20Sopenharmony_ci break; 36508c2ecf20Sopenharmony_ci default: 36518c2ecf20Sopenharmony_ci DRM_ERROR("Unknown packet type %d at %d !\n", cmd, idx); 36528c2ecf20Sopenharmony_ci return -EINVAL; 36538c2ecf20Sopenharmony_ci } 36548c2ecf20Sopenharmony_ci } while (idx < ib->length_dw); 36558c2ecf20Sopenharmony_ci 36568c2ecf20Sopenharmony_ci return 0; 36578c2ecf20Sopenharmony_ci} 3658