1/*
2 * Copyright 2016 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_GPU_DRM_AMD_DC_DEV_DC_INC_REG_HELPER_H_
26#define DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_REG_HELPER_H_
27
28#include "dm_services.h"
29
30/* macro for register read/write
31 * user of macro need to define
32 *
33 * CTX ==> macro to ptr to dc_context
34 *    eg. aud110->base.ctx
35 *
36 * REG ==> macro to location of register offset
37 *    eg. aud110->regs->reg
38 */
39#define REG_READ(reg_name) \
40		dm_read_reg(CTX, REG(reg_name))
41
42#define REG_WRITE(reg_name, value) \
43		dm_write_reg(CTX, REG(reg_name), value)
44
45#ifdef REG_SET
46#undef REG_SET
47#endif
48
49#ifdef REG_GET
50#undef REG_GET
51#endif
52
53/* macro to set register fields. */
54#define REG_SET_N(reg_name, n, initial_val, ...)	\
55		generic_reg_set_ex(CTX, \
56				REG(reg_name), \
57				initial_val, \
58				n, __VA_ARGS__)
59
60#define FN(reg_name, field) \
61	FD(reg_name##__##field)
62
63#define REG_SET(reg_name, initial_val, field, val)	\
64		REG_SET_N(reg_name, 1, initial_val, \
65				FN(reg_name, field), val)
66
67#define REG_SET_2(reg, init_value, f1, v1, f2, v2)	\
68		REG_SET_N(reg, 2, init_value, \
69				FN(reg, f1), v1,\
70				FN(reg, f2), v2)
71
72#define REG_SET_3(reg, init_value, f1, v1, f2, v2, f3, v3)	\
73		REG_SET_N(reg, 3, init_value, \
74				FN(reg, f1), v1,\
75				FN(reg, f2), v2,\
76				FN(reg, f3), v3)
77
78#define REG_SET_4(reg, init_value, f1, v1, f2, v2, f3, v3, f4, v4)	\
79		REG_SET_N(reg, 4, init_value, \
80				FN(reg, f1), v1,\
81				FN(reg, f2), v2,\
82				FN(reg, f3), v3,\
83				FN(reg, f4), v4)
84
85#define REG_SET_5(reg, init_value, f1, v1, f2, v2, f3, v3, f4, v4,	\
86		f5, v5)	\
87		REG_SET_N(reg, 5, init_value, \
88				FN(reg, f1), v1,\
89				FN(reg, f2), v2,\
90				FN(reg, f3), v3,\
91				FN(reg, f4), v4,\
92				FN(reg, f5), v5)
93
94#define REG_SET_6(reg, init_value, f1, v1, f2, v2, f3, v3, f4, v4,	\
95		f5, v5, f6, v6)	\
96		REG_SET_N(reg, 6, init_value, \
97				FN(reg, f1), v1,\
98				FN(reg, f2), v2,\
99				FN(reg, f3), v3,\
100				FN(reg, f4), v4,\
101				FN(reg, f5), v5,\
102				FN(reg, f6), v6)
103
104#define REG_SET_7(reg, init_value, f1, v1, f2, v2, f3, v3, f4, v4,	\
105		f5, v5, f6, v6, f7, v7)	\
106		REG_SET_N(reg, 7, init_value, \
107				FN(reg, f1), v1,\
108				FN(reg, f2), v2,\
109				FN(reg, f3), v3,\
110				FN(reg, f4), v4,\
111				FN(reg, f5), v5,\
112				FN(reg, f6), v6,\
113				FN(reg, f7), v7)
114
115#define REG_SET_8(reg, init_value, f1, v1, f2, v2, f3, v3, f4, v4,	\
116		f5, v5, f6, v6, f7, v7, f8, v8)	\
117		REG_SET_N(reg, 8, init_value, \
118				FN(reg, f1), v1,\
119				FN(reg, f2), v2,\
120				FN(reg, f3), v3,\
121				FN(reg, f4), v4,\
122				FN(reg, f5), v5,\
123				FN(reg, f6), v6,\
124				FN(reg, f7), v7,\
125				FN(reg, f8), v8)
126
127#define REG_SET_9(reg, init_value, f1, v1, f2, v2, f3, v3, f4, v4, f5, \
128		v5, f6, v6, f7, v7, f8, v8, f9, v9)	\
129		REG_SET_N(reg, 9, init_value, \
130				FN(reg, f1), v1,\
131				FN(reg, f2), v2, \
132				FN(reg, f3), v3, \
133				FN(reg, f4), v4, \
134				FN(reg, f5), v5, \
135				FN(reg, f6), v6, \
136				FN(reg, f7), v7, \
137				FN(reg, f8), v8, \
138				FN(reg, f9), v9)
139
140#define REG_SET_10(reg, init_value, f1, v1, f2, v2, f3, v3, f4, v4, f5, \
141		v5, f6, v6, f7, v7, f8, v8, f9, v9, f10, v10)	\
142		REG_SET_N(reg, 10, init_value, \
143				FN(reg, f1), v1,\
144				FN(reg, f2), v2, \
145				FN(reg, f3), v3, \
146				FN(reg, f4), v4, \
147				FN(reg, f5), v5, \
148				FN(reg, f6), v6, \
149				FN(reg, f7), v7, \
150				FN(reg, f8), v8, \
151				FN(reg, f9), v9, \
152				FN(reg, f10), v10)
153
154/* macro to get register fields
155 * read given register and fill in field value in output parameter */
156#define REG_GET(reg_name, field, val)	\
157		generic_reg_get(CTX, REG(reg_name), \
158				FN(reg_name, field), val)
159
160#define REG_GET_2(reg_name, f1, v1, f2, v2)	\
161		generic_reg_get2(CTX, REG(reg_name), \
162				FN(reg_name, f1), v1, \
163				FN(reg_name, f2), v2)
164
165#define REG_GET_3(reg_name, f1, v1, f2, v2, f3, v3)	\
166		generic_reg_get3(CTX, REG(reg_name), \
167				FN(reg_name, f1), v1, \
168				FN(reg_name, f2), v2, \
169				FN(reg_name, f3), v3)
170
171#define REG_GET_4(reg_name, f1, v1, f2, v2, f3, v3, f4, v4)	\
172		generic_reg_get4(CTX, REG(reg_name), \
173				FN(reg_name, f1), v1, \
174				FN(reg_name, f2), v2, \
175				FN(reg_name, f3), v3, \
176				FN(reg_name, f4), v4)
177
178#define REG_GET_5(reg_name, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5)	\
179		generic_reg_get5(CTX, REG(reg_name), \
180				FN(reg_name, f1), v1, \
181				FN(reg_name, f2), v2, \
182				FN(reg_name, f3), v3, \
183				FN(reg_name, f4), v4, \
184				FN(reg_name, f5), v5)
185
186#define REG_GET_6(reg_name, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6)	\
187		generic_reg_get6(CTX, REG(reg_name), \
188				FN(reg_name, f1), v1, \
189				FN(reg_name, f2), v2, \
190				FN(reg_name, f3), v3, \
191				FN(reg_name, f4), v4, \
192				FN(reg_name, f5), v5, \
193				FN(reg_name, f6), v6)
194
195#define REG_GET_7(reg_name, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7)	\
196		generic_reg_get7(CTX, REG(reg_name), \
197				FN(reg_name, f1), v1, \
198				FN(reg_name, f2), v2, \
199				FN(reg_name, f3), v3, \
200				FN(reg_name, f4), v4, \
201				FN(reg_name, f5), v5, \
202				FN(reg_name, f6), v6, \
203				FN(reg_name, f7), v7)
204
205#define REG_GET_8(reg_name, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8)	\
206		generic_reg_get8(CTX, REG(reg_name), \
207				FN(reg_name, f1), v1, \
208				FN(reg_name, f2), v2, \
209				FN(reg_name, f3), v3, \
210				FN(reg_name, f4), v4, \
211				FN(reg_name, f5), v5, \
212				FN(reg_name, f6), v6, \
213				FN(reg_name, f7), v7, \
214				FN(reg_name, f8), v8)
215
216/* macro to poll and wait for a register field to read back given value */
217
218#define REG_WAIT(reg_name, field, val, delay_between_poll_us, max_try)	\
219		generic_reg_wait(CTX, \
220				REG(reg_name), FN(reg_name, field), val,\
221				delay_between_poll_us, max_try, __func__, __LINE__)
222
223/* macro to update (read, modify, write) register fields
224 */
225#define REG_UPDATE_N(reg_name, n, ...)	\
226		generic_reg_update_ex(CTX, \
227				REG(reg_name), \
228				n, __VA_ARGS__)
229
230#define REG_UPDATE(reg_name, field, val)	\
231		REG_UPDATE_N(reg_name, 1, \
232				FN(reg_name, field), val)
233
234#define REG_UPDATE_2(reg, f1, v1, f2, v2)	\
235		REG_UPDATE_N(reg, 2,\
236				FN(reg, f1), v1,\
237				FN(reg, f2), v2)
238
239#define REG_UPDATE_3(reg, f1, v1, f2, v2, f3, v3)	\
240		REG_UPDATE_N(reg, 3, \
241				FN(reg, f1), v1,\
242				FN(reg, f2), v2, \
243				FN(reg, f3), v3)
244
245#define REG_UPDATE_4(reg, f1, v1, f2, v2, f3, v3, f4, v4)	\
246		REG_UPDATE_N(reg, 4, \
247				FN(reg, f1), v1,\
248				FN(reg, f2), v2, \
249				FN(reg, f3), v3, \
250				FN(reg, f4), v4)
251
252#define REG_UPDATE_5(reg, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5)	\
253		REG_UPDATE_N(reg, 5, \
254				FN(reg, f1), v1,\
255				FN(reg, f2), v2, \
256				FN(reg, f3), v3, \
257				FN(reg, f4), v4, \
258				FN(reg, f5), v5)
259
260#define REG_UPDATE_6(reg, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6)	\
261		REG_UPDATE_N(reg, 6, \
262				FN(reg, f1), v1,\
263				FN(reg, f2), v2, \
264				FN(reg, f3), v3, \
265				FN(reg, f4), v4, \
266				FN(reg, f5), v5, \
267				FN(reg, f6), v6)
268
269#define REG_UPDATE_7(reg, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7)	\
270		REG_UPDATE_N(reg, 7, \
271				FN(reg, f1), v1,\
272				FN(reg, f2), v2, \
273				FN(reg, f3), v3, \
274				FN(reg, f4), v4, \
275				FN(reg, f5), v5, \
276				FN(reg, f6), v6, \
277				FN(reg, f7), v7)
278
279#define REG_UPDATE_8(reg, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8)	\
280		REG_UPDATE_N(reg, 8, \
281				FN(reg, f1), v1,\
282				FN(reg, f2), v2, \
283				FN(reg, f3), v3, \
284				FN(reg, f4), v4, \
285				FN(reg, f5), v5, \
286				FN(reg, f6), v6, \
287				FN(reg, f7), v7, \
288				FN(reg, f8), v8)
289
290#define REG_UPDATE_9(reg, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9)	\
291		REG_UPDATE_N(reg, 9, \
292				FN(reg, f1), v1,\
293				FN(reg, f2), v2, \
294				FN(reg, f3), v3, \
295				FN(reg, f4), v4, \
296				FN(reg, f5), v5, \
297				FN(reg, f6), v6, \
298				FN(reg, f7), v7, \
299				FN(reg, f8), v8, \
300				FN(reg, f9), v9)
301
302#define REG_UPDATE_10(reg, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10, v10)\
303		REG_UPDATE_N(reg, 10, \
304				FN(reg, f1), v1,\
305				FN(reg, f2), v2, \
306				FN(reg, f3), v3, \
307				FN(reg, f4), v4, \
308				FN(reg, f5), v5, \
309				FN(reg, f6), v6, \
310				FN(reg, f7), v7, \
311				FN(reg, f8), v8, \
312				FN(reg, f9), v9, \
313				FN(reg, f10), v10)
314
315#define REG_UPDATE_14(reg, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10,\
316		v10, f11, v11, f12, v12, f13, v13, f14, v14)\
317		REG_UPDATE_N(reg, 14, \
318				FN(reg, f1), v1,\
319				FN(reg, f2), v2, \
320				FN(reg, f3), v3, \
321				FN(reg, f4), v4, \
322				FN(reg, f5), v5, \
323				FN(reg, f6), v6, \
324				FN(reg, f7), v7, \
325				FN(reg, f8), v8, \
326				FN(reg, f9), v9, \
327				FN(reg, f10), v10, \
328				FN(reg, f11), v11, \
329				FN(reg, f12), v12, \
330				FN(reg, f13), v13, \
331				FN(reg, f14), v14)
332
333#define REG_UPDATE_19(reg, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10,\
334		v10, f11, v11, f12, v12, f13, v13, f14, v14, f15, v15, f16, v16, f17, v17, f18, v18, f19, v19)\
335		REG_UPDATE_N(reg, 19, \
336				FN(reg, f1), v1,\
337				FN(reg, f2), v2, \
338				FN(reg, f3), v3, \
339				FN(reg, f4), v4, \
340				FN(reg, f5), v5, \
341				FN(reg, f6), v6, \
342				FN(reg, f7), v7, \
343				FN(reg, f8), v8, \
344				FN(reg, f9), v9, \
345				FN(reg, f10), v10, \
346				FN(reg, f11), v11, \
347				FN(reg, f12), v12, \
348				FN(reg, f13), v13, \
349				FN(reg, f14), v14, \
350				FN(reg, f15), v15, \
351				FN(reg, f16), v16, \
352				FN(reg, f17), v17, \
353				FN(reg, f18), v18, \
354				FN(reg, f19), v19)
355
356#define REG_UPDATE_20(reg, f1, v1, f2, v2, f3, v3, f4, v4, f5, v5, f6, v6, f7, v7, f8, v8, f9, v9, f10,\
357		v10, f11, v11, f12, v12, f13, v13, f14, v14, f15, v15, f16, v16, f17, v17, f18, v18, f19, v19, f20, v20)\
358		REG_UPDATE_N(reg, 20, \
359				FN(reg, f1), v1,\
360				FN(reg, f2), v2, \
361				FN(reg, f3), v3, \
362				FN(reg, f4), v4, \
363				FN(reg, f5), v5, \
364				FN(reg, f6), v6, \
365				FN(reg, f7), v7, \
366				FN(reg, f8), v8, \
367				FN(reg, f9), v9, \
368				FN(reg, f10), v10, \
369				FN(reg, f11), v11, \
370				FN(reg, f12), v12, \
371				FN(reg, f13), v13, \
372				FN(reg, f14), v14, \
373				FN(reg, f15), v15, \
374				FN(reg, f16), v16, \
375				FN(reg, f17), v17, \
376				FN(reg, f18), v18, \
377				FN(reg, f19), v19, \
378				FN(reg, f20), v20)
379/* macro to update a register field to specified values in given sequences.
380 * useful when toggling bits
381 */
382#define REG_UPDATE_SEQ_2(reg, f1, v1, f2, v2) \
383{	uint32_t val = REG_UPDATE(reg, f1, v1); \
384	REG_SET(reg, val, f2, v2); }
385
386#define REG_UPDATE_SEQ_3(reg, f1, v1, f2, v2, f3, v3) \
387{	uint32_t val = REG_UPDATE(reg, f1, v1); \
388	val = REG_SET(reg, val, f2, v2); \
389	REG_SET(reg, val, f3, v3); }
390
391uint32_t generic_reg_get(const struct dc_context *ctx, uint32_t addr,
392		uint8_t shift, uint32_t mask, uint32_t *field_value);
393
394uint32_t generic_reg_get2(const struct dc_context *ctx, uint32_t addr,
395		uint8_t shift1, uint32_t mask1, uint32_t *field_value1,
396		uint8_t shift2, uint32_t mask2, uint32_t *field_value2);
397
398uint32_t generic_reg_get3(const struct dc_context *ctx, uint32_t addr,
399		uint8_t shift1, uint32_t mask1, uint32_t *field_value1,
400		uint8_t shift2, uint32_t mask2, uint32_t *field_value2,
401		uint8_t shift3, uint32_t mask3, uint32_t *field_value3);
402
403uint32_t generic_reg_get4(const struct dc_context *ctx, uint32_t addr,
404		uint8_t shift1, uint32_t mask1, uint32_t *field_value1,
405		uint8_t shift2, uint32_t mask2, uint32_t *field_value2,
406		uint8_t shift3, uint32_t mask3, uint32_t *field_value3,
407		uint8_t shift4, uint32_t mask4, uint32_t *field_value4);
408
409uint32_t generic_reg_get5(const struct dc_context *ctx, uint32_t addr,
410		uint8_t shift1, uint32_t mask1, uint32_t *field_value1,
411		uint8_t shift2, uint32_t mask2, uint32_t *field_value2,
412		uint8_t shift3, uint32_t mask3, uint32_t *field_value3,
413		uint8_t shift4, uint32_t mask4, uint32_t *field_value4,
414		uint8_t shift5, uint32_t mask5, uint32_t *field_value5);
415
416uint32_t generic_reg_get6(const struct dc_context *ctx, uint32_t addr,
417		uint8_t shift1, uint32_t mask1, uint32_t *field_value1,
418		uint8_t shift2, uint32_t mask2, uint32_t *field_value2,
419		uint8_t shift3, uint32_t mask3, uint32_t *field_value3,
420		uint8_t shift4, uint32_t mask4, uint32_t *field_value4,
421		uint8_t shift5, uint32_t mask5, uint32_t *field_value5,
422		uint8_t shift6, uint32_t mask6, uint32_t *field_value6);
423
424uint32_t generic_reg_get7(const struct dc_context *ctx, uint32_t addr,
425		uint8_t shift1, uint32_t mask1, uint32_t *field_value1,
426		uint8_t shift2, uint32_t mask2, uint32_t *field_value2,
427		uint8_t shift3, uint32_t mask3, uint32_t *field_value3,
428		uint8_t shift4, uint32_t mask4, uint32_t *field_value4,
429		uint8_t shift5, uint32_t mask5, uint32_t *field_value5,
430		uint8_t shift6, uint32_t mask6, uint32_t *field_value6,
431		uint8_t shift7, uint32_t mask7, uint32_t *field_value7);
432
433uint32_t generic_reg_get8(const struct dc_context *ctx, uint32_t addr,
434		uint8_t shift1, uint32_t mask1, uint32_t *field_value1,
435		uint8_t shift2, uint32_t mask2, uint32_t *field_value2,
436		uint8_t shift3, uint32_t mask3, uint32_t *field_value3,
437		uint8_t shift4, uint32_t mask4, uint32_t *field_value4,
438		uint8_t shift5, uint32_t mask5, uint32_t *field_value5,
439		uint8_t shift6, uint32_t mask6, uint32_t *field_value6,
440		uint8_t shift7, uint32_t mask7, uint32_t *field_value7,
441		uint8_t shift8, uint32_t mask8, uint32_t *field_value8);
442
443
444/* indirect register access */
445
446#define IX_REG_SET_N(index_reg_name, data_reg_name, index, n, initial_val, ...)	\
447		generic_indirect_reg_update_ex(CTX, \
448				REG(index_reg_name), REG(data_reg_name), IND_REG(index), \
449				initial_val, \
450				n, __VA_ARGS__)
451
452#define IX_REG_SET_2(index_reg_name, data_reg_name, index, init_value, f1, v1, f2, v2)	\
453		IX_REG_SET_N(index_reg_name, data_reg_name, index, 2, init_value, \
454				FN(reg, f1), v1,\
455				FN(reg, f2), v2)
456
457
458#define IX_REG_READ(index_reg_name, data_reg_name, index) \
459		generic_read_indirect_reg(CTX, REG(index_reg_name), REG(data_reg_name), IND_REG(index))
460
461#define IX_REG_GET_N(index_reg_name, data_reg_name, index, n, ...) \
462		generic_indirect_reg_get(CTX, REG(index_reg_name), REG(data_reg_name), \
463				IND_REG(index), \
464				n, __VA_ARGS__)
465
466#define IX_REG_GET(index_reg_name, data_reg_name, index, field, val) \
467		IX_REG_GET_N(index_reg_name, data_reg_name, index, 1, \
468				FN(data_reg_name, field), val)
469
470#define IX_REG_UPDATE_N(index_reg_name, data_reg_name, index, n, ...)	\
471		generic_indirect_reg_update_ex(CTX, \
472				REG(index_reg_name), REG(data_reg_name), IND_REG(index), \
473				IX_REG_READ(index_reg_name, data_reg_name, index), \
474				n, __VA_ARGS__)
475
476#define IX_REG_UPDATE_2(index_reg_name, data_reg_name, index, f1, v1, f2, v2)	\
477		IX_REG_UPDATE_N(index_reg_name, data_reg_name, index, 2,\
478				FN(reg, f1), v1,\
479				FN(reg, f2), v2)
480
481void generic_write_indirect_reg(const struct dc_context *ctx,
482		uint32_t addr_index, uint32_t addr_data,
483		uint32_t index, uint32_t data);
484
485uint32_t generic_read_indirect_reg(const struct dc_context *ctx,
486		uint32_t addr_index, uint32_t addr_data,
487		uint32_t index);
488
489uint32_t generic_indirect_reg_get(const struct dc_context *ctx,
490		uint32_t addr_index, uint32_t addr_data,
491		uint32_t index, int n,
492		uint8_t shift1, uint32_t mask1, uint32_t *field_value1,
493		...);
494
495uint32_t generic_indirect_reg_update_ex(const struct dc_context *ctx,
496		uint32_t addr_index, uint32_t addr_data,
497		uint32_t index, uint32_t reg_val, int n,
498		uint8_t shift1, uint32_t mask1, uint32_t field_value1,
499		...);
500
501/* indirect register access
502 * underlying implementation determines which index/data pair to be used
503 * in a synchronous way
504 */
505#define IX_REG_SET_N_SYNC(index, n, initial_val, ...)	\
506		generic_indirect_reg_update_ex_sync(CTX, \
507				IND_REG(index), \
508				initial_val, \
509				n, __VA_ARGS__)
510
511#define IX_REG_SET_2_SYNC(index, init_value, f1, v1, f2, v2)	\
512		IX_REG_SET_N_SYNC(index, 2, init_value, \
513				FN(reg, f1), v1,\
514				FN(reg, f2), v2)
515
516#define IX_REG_GET_N_SYNC(index, n, ...) \
517		generic_indirect_reg_get_sync(CTX, \
518				IND_REG(index), \
519				n, __VA_ARGS__)
520
521#define IX_REG_GET_SYNC(index, field, val) \
522		IX_REG_GET_N_SYNC(index, 1, \
523				FN(data_reg_name, field), val)
524
525uint32_t generic_indirect_reg_get_sync(const struct dc_context *ctx,
526		uint32_t index, int n,
527		uint8_t shift1, uint32_t mask1, uint32_t *field_value1,
528		...);
529
530uint32_t generic_indirect_reg_update_ex_sync(const struct dc_context *ctx,
531		uint32_t index, uint32_t reg_val, int n,
532		uint8_t shift1, uint32_t mask1, uint32_t field_value1,
533		...);
534
535/* register offload macros
536 *
537 * instead of MMIO to register directly, in some cases we want
538 * to gather register sequence and execute the register sequence
539 * from another thread so we optimize time required for lengthy ops
540 */
541
542/* start gathering register sequence */
543#define REG_SEQ_START() \
544	reg_sequence_start_gather(CTX)
545
546/* start execution of register sequence gathered since REG_SEQ_START */
547#define REG_SEQ_SUBMIT() \
548	reg_sequence_start_execute(CTX)
549
550/* wait for the last REG_SEQ_SUBMIT to finish */
551#define REG_SEQ_WAIT_DONE() \
552	reg_sequence_wait_done(CTX)
553
554#endif /* DRIVERS_GPU_DRM_AMD_DC_DEV_DC_INC_REG_HELPER_H_ */
555