xref: /aosp_15_r20/external/mesa3d/src/amd/vpelib/src/core/inc/reg_helper.h (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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