1 /* 2 * Copyright 2022 Advanced Micro Devices, Inc. 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20 * OTHER DEALINGS IN THE SOFTWARE. 21 * 22 * Authors: AMD 23 */ 24 25 #ifndef DRIVERS_VPELIB_INC_REG_HELPER_H_ 26 #define DRIVERS_VPELIB_INC_REG_HELPER_H_ 27 28 #pragma once 29 30 #include <stdint.h> 31 #include "config_writer.h" 32 #include "vpe_command.h" 33 34 #ifdef __cplusplus 35 extern "C" { 36 #endif 37 38 typedef struct reg_id_val { 39 const uint32_t id; 40 const uint32_t default_value; 41 uint32_t lastWritten_value; 42 bool isWritten; 43 } reg_id_val; 44 45 /** CTX is defined in the .c files */ 46 #define PROGRAM_ENTRY() \ 47 struct vpe_priv *vpe_priv = CTX_BASE->vpe_priv; \ 48 struct CTX *CTX = (struct CTX *)CTX_BASE; \ 49 struct config_writer *config_writer = &vpe_priv->config_writer; \ 50 struct vpep_direct_config_packet packet = {0} 51 52 // for use with reg_id_val struct that stores id, default and current val together 53 #define REG_OFFSET(reg_name) CTX->regs->reg_name.id // Register offset in DWORD 54 #define REG_DEFAULT(reg_name) CTX->regs->reg_name.default_value 55 #define REG_IS_WRITTEN(reg_name) CTX->regs->reg_name.isWritten 56 #define REG_LAST_WRITTEN_VAL(reg_name) CTX->regs->reg_name.lastWritten_value 57 #define REG_CURRENT(reg_name) \ 58 (REG_IS_WRITTEN(reg_name) ? REG_LAST_WRITTEN_VAL(reg_name) : REG_DEFAULT(reg_name)) 59 60 #define REG_FIELD_VALUE(field, value) ((uint32_t)((value) << CTX->shift->field) & CTX->mask->field) 61 #define REG_FIELD_SHIFT(field) CTX->shift->field 62 #define REG_FIELD_MASK(field) CTX->mask->field 63 #define VPEC_FIELD_VALUE(field, data) ((uint32_t)((data) << field##__SHIFT) & field##_MASK) 64 65 /* macro to set register fields. */ 66 #define REG_SET_DEFAULT(reg_name) \ 67 do { \ 68 packet.bits.INC = 0; \ 69 packet.bits.VPEP_CONFIG_DATA_SIZE = 0; \ 70 packet.bits.VPEP_CONFIG_REGISTER_OFFSET = REG_OFFSET(reg_name); \ 71 REG_IS_WRITTEN(reg_name) = true; \ 72 packet.data[0] = REG_LAST_WRITTEN_VAL(reg_name) = REG_DEFAULT(reg_name); \ 73 config_writer_fill_direct_config_packet(config_writer, &packet); \ 74 } while (0) 75 76 #define REG_SET(reg_name, init_val, field, val) \ 77 do { \ 78 packet.bits.INC = 0; \ 79 packet.bits.VPEP_CONFIG_DATA_SIZE = 0; \ 80 packet.bits.VPEP_CONFIG_REGISTER_OFFSET = REG_OFFSET(reg_name); \ 81 REG_IS_WRITTEN(reg_name) = true; \ 82 packet.data[0] = REG_LAST_WRITTEN_VAL(reg_name) = \ 83 (((uint32_t)init_val & ~(REG_FIELD_MASK(field))) | \ 84 REG_FIELD_VALUE(field, (uint32_t)val)); \ 85 config_writer_fill_direct_config_packet(config_writer, &packet); \ 86 } while (0) 87 88 #define REG_SET_2(reg_name, init_val, f1, v1, f2, v2) \ 89 do { \ 90 packet.bits.INC = 0; \ 91 packet.bits.VPEP_CONFIG_DATA_SIZE = 0; \ 92 packet.bits.VPEP_CONFIG_REGISTER_OFFSET = REG_OFFSET(reg_name); \ 93 REG_IS_WRITTEN(reg_name) = true; \ 94 packet.data[0] = REG_LAST_WRITTEN_VAL(reg_name) = \ 95 (((uint32_t)init_val & ~(REG_FIELD_MASK(f1)) & ~(REG_FIELD_MASK(f2))) | \ 96 REG_FIELD_VALUE(f1, (uint32_t)v1) | REG_FIELD_VALUE(f2, (uint32_t)v2)); \ 97 config_writer_fill_direct_config_packet(config_writer, &packet); \ 98 } while (0) 99 100 #define REG_SET_3(reg_name, init_val, f1, v1, f2, v2, f3, v3) \ 101 do { \ 102 packet.bits.INC = 0; \ 103 packet.bits.VPEP_CONFIG_DATA_SIZE = 0; \ 104 packet.bits.VPEP_CONFIG_REGISTER_OFFSET = REG_OFFSET(reg_name); \ 105 REG_IS_WRITTEN(reg_name) = true; \ 106 packet.data[0] = REG_LAST_WRITTEN_VAL(reg_name) = \ 107 (((uint32_t)init_val & ~(REG_FIELD_MASK(f1)) & ~(REG_FIELD_MASK(f2)) & \ 108 ~(REG_FIELD_MASK(f3))) | \ 109 REG_FIELD_VALUE(f1, (uint32_t)v1) | REG_FIELD_VALUE(f2, (uint32_t)v2) | \ 110 REG_FIELD_VALUE(f3, (uint32_t)v3)); \ 111 config_writer_fill_direct_config_packet(config_writer, &packet); \ 112 } while (0) 113 114 #define REG_SET_4(reg_name, init_val, f1, v1, f2, v2, f3, v3, f4, v4) \ 115 do { \ 116 packet.bits.INC = 0; \ 117 packet.bits.VPEP_CONFIG_DATA_SIZE = 0; \ 118 packet.bits.VPEP_CONFIG_REGISTER_OFFSET = REG_OFFSET(reg_name); \ 119 REG_IS_WRITTEN(reg_name) = true; \ 120 packet.data[0] = REG_LAST_WRITTEN_VAL(reg_name) = \ 121 (((uint32_t)init_val & ~(REG_FIELD_MASK(f1)) & ~(REG_FIELD_MASK(f2)) & \ 122 ~(REG_FIELD_MASK(f3)) & ~(REG_FIELD_MASK(f4))) | \ 123 REG_FIELD_VALUE(f1, (uint32_t)v1) | REG_FIELD_VALUE(f2, (uint32_t)v2) | \ 124 REG_FIELD_VALUE(f3, (uint32_t)v3) | REG_FIELD_VALUE(f4, (uint32_t)v4)); \ 125 config_writer_fill_direct_config_packet(config_writer, &packet); \ 126 } while (0) 127 128 #define REG_SET_5(reg_name, init_val, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5) \ 129 do { \ 130 packet.bits.INC = 0; \ 131 packet.bits.VPEP_CONFIG_DATA_SIZE = 0; \ 132 packet.bits.VPEP_CONFIG_REGISTER_OFFSET = REG_OFFSET(reg_name); \ 133 REG_IS_WRITTEN(reg_name) = true; \ 134 packet.data[0] = REG_LAST_WRITTEN_VAL(reg_name) = \ 135 (((uint32_t)init_val & ~(REG_FIELD_MASK(f1)) & ~(REG_FIELD_MASK(f2)) & \ 136 ~(REG_FIELD_MASK(f3)) & ~(REG_FIELD_MASK(f4)) & ~(REG_FIELD_MASK(f5))) | \ 137 REG_FIELD_VALUE(f1, (uint32_t)v1) | REG_FIELD_VALUE(f2, (uint32_t)v2) | \ 138 REG_FIELD_VALUE(f3, (uint32_t)v3) | REG_FIELD_VALUE(f4, (uint32_t)v4) | \ 139 REG_FIELD_VALUE(f5, (uint32_t)v5)); \ 140 config_writer_fill_direct_config_packet(config_writer, &packet); \ 141 } while (0) 142 143 #define REG_SET_6(reg_name, init_val, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6) \ 144 do { \ 145 packet.bits.INC = 0; \ 146 packet.bits.VPEP_CONFIG_DATA_SIZE = 0; \ 147 packet.bits.VPEP_CONFIG_REGISTER_OFFSET = REG_OFFSET(reg_name); \ 148 REG_IS_WRITTEN(reg_name) = true; \ 149 packet.data[0] = REG_LAST_WRITTEN_VAL(reg_name) = \ 150 (((uint32_t)init_val & ~(REG_FIELD_MASK(f1)) & ~(REG_FIELD_MASK(f2)) & \ 151 ~(REG_FIELD_MASK(f3)) & ~(REG_FIELD_MASK(f4)) & ~(REG_FIELD_MASK(f5)) & \ 152 ~(REG_FIELD_MASK(f6))) | \ 153 REG_FIELD_VALUE(f1, (uint32_t)v1) | REG_FIELD_VALUE(f2, (uint32_t)v2) | \ 154 REG_FIELD_VALUE(f3, (uint32_t)v3) | REG_FIELD_VALUE(f4, (uint32_t)v4) | \ 155 REG_FIELD_VALUE(f5, (uint32_t)v5) | REG_FIELD_VALUE(f6, (uint32_t)v6)); \ 156 config_writer_fill_direct_config_packet(config_writer, &packet); \ 157 } while (0) 158 159 #define REG_SET_7(reg_name, init_val, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7) \ 160 do { \ 161 packet.bits.INC = 0; \ 162 packet.bits.VPEP_CONFIG_DATA_SIZE = 0; \ 163 packet.bits.VPEP_CONFIG_REGISTER_OFFSET = REG_OFFSET(reg_name); \ 164 REG_IS_WRITTEN(reg_name) = true; \ 165 packet.data[0] = REG_LAST_WRITTEN_VAL(reg_name) = \ 166 (((uint32_t)init_val & ~(REG_FIELD_MASK(f1)) & ~(REG_FIELD_MASK(f2)) & \ 167 ~(REG_FIELD_MASK(f3)) & ~(REG_FIELD_MASK(f4)) & ~(REG_FIELD_MASK(f5)) & \ 168 ~(REG_FIELD_MASK(f6)) & ~(REG_FIELD_MASK(f7))) | \ 169 REG_FIELD_VALUE(f1, (uint32_t)v1) | REG_FIELD_VALUE(f2, (uint32_t)v2) | \ 170 REG_FIELD_VALUE(f3, (uint32_t)v3) | REG_FIELD_VALUE(f4, (uint32_t)v4) | \ 171 REG_FIELD_VALUE(f5, (uint32_t)v5) | REG_FIELD_VALUE(f6, (uint32_t)v6) | \ 172 REG_FIELD_VALUE(f7, (uint32_t)v7)); \ 173 config_writer_fill_direct_config_packet(config_writer, &packet); \ 174 } while (0) 175 176 #define REG_SET_8( \ 177 reg_name, init_val, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8) \ 178 do { \ 179 packet.bits.INC = 0; \ 180 packet.bits.VPEP_CONFIG_DATA_SIZE = 0; \ 181 packet.bits.VPEP_CONFIG_REGISTER_OFFSET = REG_OFFSET(reg_name); \ 182 REG_IS_WRITTEN(reg_name) = true; \ 183 packet.data[0] = REG_LAST_WRITTEN_VAL(reg_name) = \ 184 (((uint32_t)init_val & ~(REG_FIELD_MASK(f1)) & ~(REG_FIELD_MASK(f2)) & \ 185 ~(REG_FIELD_MASK(f3)) & ~(REG_FIELD_MASK(f4)) & ~(REG_FIELD_MASK(f5)) & \ 186 ~(REG_FIELD_MASK(f6)) & ~(REG_FIELD_MASK(f7)) & ~(REG_FIELD_MASK(f8))) | \ 187 REG_FIELD_VALUE(f1, (uint32_t)v1) | REG_FIELD_VALUE(f2, (uint32_t)v2) | \ 188 REG_FIELD_VALUE(f3, (uint32_t)v3) | REG_FIELD_VALUE(f4, (uint32_t)v4) | \ 189 REG_FIELD_VALUE(f5, (uint32_t)v5) | REG_FIELD_VALUE(f6, (uint32_t)v6) | \ 190 REG_FIELD_VALUE(f7, (uint32_t)v7) | REG_FIELD_VALUE(f8, (uint32_t)v8)); \ 191 config_writer_fill_direct_config_packet(config_writer, &packet); \ 192 } while (0) 193 194 #define REG_SET_9( \ 195 reg_name, init_val, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9) \ 196 do { \ 197 packet.bits.INC = 0; \ 198 packet.bits.VPEP_CONFIG_DATA_SIZE = 0; \ 199 packet.bits.VPEP_CONFIG_REGISTER_OFFSET = REG_OFFSET(reg_name); \ 200 REG_IS_WRITTEN(reg_name) = true; \ 201 packet.data[0] = REG_LAST_WRITTEN_VAL(reg_name) = \ 202 (((uint32_t)init_val & ~(REG_FIELD_MASK(f1)) & ~(REG_FIELD_MASK(f2)) & \ 203 ~(REG_FIELD_MASK(f3)) & ~(REG_FIELD_MASK(f4)) & ~(REG_FIELD_MASK(f5)) & \ 204 ~(REG_FIELD_MASK(f6)) & ~(REG_FIELD_MASK(f7)) & ~(REG_FIELD_MASK(f8)) & \ 205 ~(REG_FIELD_MASK(f9))) | \ 206 REG_FIELD_VALUE(f1, (uint32_t)v1) | REG_FIELD_VALUE(f2, (uint32_t)v2) | \ 207 REG_FIELD_VALUE(f3, (uint32_t)v3) | REG_FIELD_VALUE(f4, (uint32_t)v4) | \ 208 REG_FIELD_VALUE(f5, (uint32_t)v5) | REG_FIELD_VALUE(f6, (uint32_t)v6) | \ 209 REG_FIELD_VALUE(f7, (uint32_t)v7) | REG_FIELD_VALUE(f8, (uint32_t)v8) | \ 210 REG_FIELD_VALUE(f9, (uint32_t)v9)); \ 211 config_writer_fill_direct_config_packet(config_writer, &packet); \ 212 } while (0) 213 214 #define REG_SET_10(reg_name, init_val, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, \ 215 v8, f9, v9, f10, v10) \ 216 do { \ 217 packet.bits.INC = 0; \ 218 packet.bits.VPEP_CONFIG_DATA_SIZE = 0; \ 219 packet.bits.VPEP_CONFIG_REGISTER_OFFSET = REG_OFFSET(reg_name); \ 220 REG_IS_WRITTEN(reg_name) = true; \ 221 packet.data[0] = REG_LAST_WRITTEN_VAL(reg_name) = \ 222 (((uint32_t)init_val & ~(REG_FIELD_MASK(f1)) & ~(REG_FIELD_MASK(f2)) & \ 223 ~(REG_FIELD_MASK(f3)) & ~(REG_FIELD_MASK(f4)) & ~(REG_FIELD_MASK(f5)) & \ 224 ~(REG_FIELD_MASK(f6)) & ~(REG_FIELD_MASK(f7)) & ~(REG_FIELD_MASK(f8)) & \ 225 ~(REG_FIELD_MASK(f9)) & ~(REG_FIELD_MASK(f10))) | \ 226 REG_FIELD_VALUE(f1, (uint32_t)v1) | REG_FIELD_VALUE(f2, (uint32_t)v2) | \ 227 REG_FIELD_VALUE(f3, (uint32_t)v3) | REG_FIELD_VALUE(f4, (uint32_t)v4) | \ 228 REG_FIELD_VALUE(f5, (uint32_t)v5) | REG_FIELD_VALUE(f6, (uint32_t)v6) | \ 229 REG_FIELD_VALUE(f7, (uint32_t)v7) | REG_FIELD_VALUE(f8, (uint32_t)v8) | \ 230 REG_FIELD_VALUE(f9, (uint32_t)v9) | REG_FIELD_VALUE(f10, (uint32_t)v10)); \ 231 config_writer_fill_direct_config_packet(config_writer, &packet); \ 232 } while (0) 233 234 #define REG_UPDATE(reg, field, val) REG_SET(reg, REG_CURRENT(reg), field, val) 235 #define REG_UPDATE_2(reg, f1, v1, f2, v2) REG_SET_2(reg, REG_CURRENT(reg), f1, v1, f2, v2) 236 #define REG_UPDATE_3(reg, f1, v1, f2, v2, f3, v3) \ 237 REG_SET_3(reg, REG_CURRENT(reg), f1, v1, f2, v2, f3, v3) 238 #define REG_UPDATE_4(reg, f1, v1, f2, v2, f3, v3, f4, v4) \ 239 REG_SET_4(reg, REG_CURRENT(reg), f1, v1, f2, v2, f3, v3, f4, v4) 240 #define REG_UPDATE_5(reg, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5) \ 241 REG_SET_5(reg, REG_CURRENT(reg), f1, v1, f2, v2, f3, v3, f4, v4, f5, v5) 242 243 #define REG_UPDATE_6(reg, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6) \ 244 REG_SET_6(reg, REG_CURRENT(reg), f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6) 245 246 #define REG_UPDATE_7(reg, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7) \ 247 REG_SET_7(reg, REG_CURRENT(reg), f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7) 248 249 #define REG_UPDATE_8(reg, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8) \ 250 REG_SET_8(reg, REG_CURRENT(reg), f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8) 251 252 #define REG_UPDATE_9(reg, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9) \ 253 REG_SET_9(reg, REG_CURRENT(reg), f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, \ 254 v8, f9, v9) 255 256 #define REG_UPDATE_10( \ 257 reg, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10, v10) \ 258 REG_SET_10(reg, REG_CURRENT(reg), f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, \ 259 v8, f9, v9, f10, v10) 260 261 #define REG_SET_DEFAULT(reg_name) \ 262 do { \ 263 packet.bits.INC = 0; \ 264 packet.bits.VPEP_CONFIG_DATA_SIZE = 0; \ 265 packet.bits.VPEP_CONFIG_REGISTER_OFFSET = REG_OFFSET(reg_name); \ 266 REG_IS_WRITTEN(reg_name) = true; \ 267 packet.data[0] = REG_LAST_WRITTEN_VAL(reg_name) = REG_DEFAULT(reg_name); \ 268 config_writer_fill_direct_config_packet(config_writer, &packet); \ 269 } while (0) 270 271 #ifdef __cplusplus 272 } 273 #endif 274 275 #endif /* DRIVERS_VPELIB_INC_REG_HELPER_H_ */ 276