1/* 2 * Copyright © 2016 Red Hat. 3 * Copyright © 2016 Bas Nieuwenhuizen 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice (including the next 13 * paragraph) shall be included in all copies or substantial portions of the 14 * Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 22 * IN THE SOFTWARE. 23 */ 24 25#ifndef RADV_CS_H 26#define RADV_CS_H 27 28#include <assert.h> 29#include <stdint.h> 30#include <string.h> 31#include "radv_private.h" 32#include "sid.h" 33 34static inline unsigned 35radeon_check_space(struct radeon_winsys *ws, struct radeon_cmdbuf *cs, unsigned needed) 36{ 37 if (cs->max_dw - cs->cdw < needed) 38 ws->cs_grow(cs, needed); 39 return cs->cdw + needed; 40} 41 42static inline void 43radeon_set_config_reg_seq(struct radeon_cmdbuf *cs, unsigned reg, unsigned num) 44{ 45 assert(reg >= SI_CONFIG_REG_OFFSET && reg < SI_CONFIG_REG_END); 46 assert(cs->cdw + 2 + num <= cs->max_dw); 47 assert(num); 48 radeon_emit(cs, PKT3(PKT3_SET_CONFIG_REG, num, 0)); 49 radeon_emit(cs, (reg - SI_CONFIG_REG_OFFSET) >> 2); 50} 51 52static inline void 53radeon_set_config_reg(struct radeon_cmdbuf *cs, unsigned reg, unsigned value) 54{ 55 radeon_set_config_reg_seq(cs, reg, 1); 56 radeon_emit(cs, value); 57} 58 59static inline void 60radeon_set_context_reg_seq(struct radeon_cmdbuf *cs, unsigned reg, unsigned num) 61{ 62 assert(reg >= SI_CONTEXT_REG_OFFSET && reg < SI_CONTEXT_REG_END); 63 assert(cs->cdw + 2 + num <= cs->max_dw); 64 assert(num); 65 radeon_emit(cs, PKT3(PKT3_SET_CONTEXT_REG, num, 0)); 66 radeon_emit(cs, (reg - SI_CONTEXT_REG_OFFSET) >> 2); 67} 68 69static inline void 70radeon_set_context_reg(struct radeon_cmdbuf *cs, unsigned reg, unsigned value) 71{ 72 radeon_set_context_reg_seq(cs, reg, 1); 73 radeon_emit(cs, value); 74} 75 76static inline void 77radeon_set_context_reg_idx(struct radeon_cmdbuf *cs, unsigned reg, unsigned idx, unsigned value) 78{ 79 assert(reg >= SI_CONTEXT_REG_OFFSET && reg < SI_CONTEXT_REG_END); 80 assert(cs->cdw + 3 <= cs->max_dw); 81 radeon_emit(cs, PKT3(PKT3_SET_CONTEXT_REG, 1, 0)); 82 radeon_emit(cs, (reg - SI_CONTEXT_REG_OFFSET) >> 2 | (idx << 28)); 83 radeon_emit(cs, value); 84} 85 86static inline void 87radeon_set_context_reg_rmw(struct radeon_cmdbuf *cs, unsigned reg, unsigned value, unsigned mask) 88{ 89 assert(reg >= SI_CONTEXT_REG_OFFSET && reg < SI_CONTEXT_REG_END); 90 assert(cs->cdw + 4 <= cs->max_dw); 91 radeon_emit(cs, PKT3(PKT3_CONTEXT_REG_RMW, 2, 0)); 92 radeon_emit(cs, (reg - SI_CONTEXT_REG_OFFSET) >> 2); 93 radeon_emit(cs, mask); 94 radeon_emit(cs, value); 95} 96 97static inline void 98radeon_set_sh_reg_seq(struct radeon_cmdbuf *cs, unsigned reg, unsigned num) 99{ 100 assert(reg >= SI_SH_REG_OFFSET && reg < SI_SH_REG_END); 101 assert(cs->cdw + 2 + num <= cs->max_dw); 102 assert(num); 103 radeon_emit(cs, PKT3(PKT3_SET_SH_REG, num, 0)); 104 radeon_emit(cs, (reg - SI_SH_REG_OFFSET) >> 2); 105} 106 107static inline void 108radeon_set_sh_reg(struct radeon_cmdbuf *cs, unsigned reg, unsigned value) 109{ 110 radeon_set_sh_reg_seq(cs, reg, 1); 111 radeon_emit(cs, value); 112} 113 114static inline void 115radeon_set_sh_reg_idx(const struct radv_physical_device *pdevice, struct radeon_cmdbuf *cs, 116 unsigned reg, unsigned idx, unsigned value) 117{ 118 assert(reg >= SI_SH_REG_OFFSET && reg < SI_SH_REG_END); 119 assert(cs->cdw + 3 <= cs->max_dw); 120 assert(idx); 121 122 unsigned opcode = PKT3_SET_SH_REG_INDEX; 123 if (pdevice->rad_info.gfx_level < GFX10) 124 opcode = PKT3_SET_SH_REG; 125 126 radeon_emit(cs, PKT3(opcode, 1, 0)); 127 radeon_emit(cs, (reg - SI_SH_REG_OFFSET) >> 2 | (idx << 28)); 128 radeon_emit(cs, value); 129} 130 131static inline void 132gfx10_set_sh_reg_idx3(struct radeon_cmdbuf *cs, unsigned reg, unsigned value) 133{ 134 assert(reg >= SI_SH_REG_OFFSET && reg < SI_SH_REG_END); 135 assert(cs->cdw + 3 <= cs->max_dw); 136 137 radeon_emit(cs, PKT3(PKT3_SET_SH_REG_INDEX, 1, 0)); 138 radeon_emit(cs, (reg - SI_SH_REG_OFFSET) >> 2 | (3 << 28)); 139 radeon_emit(cs, value); 140} 141 142static inline void 143radeon_set_uconfig_reg_seq(struct radeon_cmdbuf *cs, unsigned reg, unsigned num) 144{ 145 assert(reg >= CIK_UCONFIG_REG_OFFSET && reg < CIK_UCONFIG_REG_END); 146 assert(cs->cdw + 2 + num <= cs->max_dw); 147 assert(num); 148 radeon_emit(cs, PKT3(PKT3_SET_UCONFIG_REG, num, 0)); 149 radeon_emit(cs, (reg - CIK_UCONFIG_REG_OFFSET) >> 2); 150} 151 152static inline void 153radeon_set_uconfig_reg_seq_perfctr(struct radeon_cmdbuf *cs, unsigned reg, unsigned num) 154{ 155 assert(reg >= CIK_UCONFIG_REG_OFFSET && reg < CIK_UCONFIG_REG_END); 156 assert(cs->cdw + 2 + num <= cs->max_dw); 157 assert(num); 158 radeon_emit(cs, PKT3(PKT3_SET_UCONFIG_REG, num, 1)); 159 radeon_emit(cs, (reg - CIK_UCONFIG_REG_OFFSET) >> 2); 160} 161 162static inline void 163radeon_set_uconfig_reg(struct radeon_cmdbuf *cs, unsigned reg, unsigned value) 164{ 165 radeon_set_uconfig_reg_seq(cs, reg, 1); 166 radeon_emit(cs, value); 167} 168 169static inline void 170radeon_set_uconfig_reg_idx(const struct radv_physical_device *pdevice, struct radeon_cmdbuf *cs, 171 unsigned reg, unsigned idx, unsigned value) 172{ 173 assert(reg >= CIK_UCONFIG_REG_OFFSET && reg < CIK_UCONFIG_REG_END); 174 assert(cs->cdw + 3 <= cs->max_dw); 175 assert(idx); 176 177 unsigned opcode = PKT3_SET_UCONFIG_REG_INDEX; 178 if (pdevice->rad_info.gfx_level < GFX9 || 179 (pdevice->rad_info.gfx_level == GFX9 && pdevice->rad_info.me_fw_version < 26)) 180 opcode = PKT3_SET_UCONFIG_REG; 181 182 radeon_emit(cs, PKT3(opcode, 1, 0)); 183 radeon_emit(cs, (reg - CIK_UCONFIG_REG_OFFSET) >> 2 | (idx << 28)); 184 radeon_emit(cs, value); 185} 186 187static inline void 188radeon_set_perfctr_reg(struct radv_cmd_buffer *cmd_buffer, unsigned reg, unsigned value) 189{ 190 struct radeon_cmdbuf *cs = cmd_buffer->cs; 191 assert(reg >= CIK_UCONFIG_REG_OFFSET && reg < CIK_UCONFIG_REG_END); 192 assert(cs->cdw + 3 <= cs->max_dw); 193 194 /* 195 * On GFX10, there is a bug with the ME implementation of its content addressable memory (CAM), 196 * that means that it can skip register writes due to not taking correctly into account the 197 * fields from the GRBM_GFX_INDEX. With this bit we can force the write. 198 */ 199 bool filter_cam_workaround = cmd_buffer->device->physical_device->rad_info.gfx_level >= GFX10 && 200 cmd_buffer->qf == RADV_QUEUE_GENERAL; 201 202 radeon_emit(cs, PKT3(PKT3_SET_UCONFIG_REG, 1, 0) | PKT3_RESET_FILTER_CAM(filter_cam_workaround)); 203 radeon_emit(cs, (reg - CIK_UCONFIG_REG_OFFSET) >> 2); 204 radeon_emit(cs, value); 205} 206 207static inline void 208radeon_set_privileged_config_reg(struct radeon_cmdbuf *cs, unsigned reg, unsigned value) 209{ 210 assert(reg < CIK_UCONFIG_REG_OFFSET); 211 assert(cs->cdw + 6 <= cs->max_dw); 212 213 radeon_emit(cs, PKT3(PKT3_COPY_DATA, 4, 0)); 214 radeon_emit(cs, COPY_DATA_SRC_SEL(COPY_DATA_IMM) | COPY_DATA_DST_SEL(COPY_DATA_PERF)); 215 radeon_emit(cs, value); 216 radeon_emit(cs, 0); /* unused */ 217 radeon_emit(cs, reg >> 2); 218 radeon_emit(cs, 0); /* unused */ 219} 220 221#endif /* RADV_CS_H */ 222