xref: /dflybsd-src/sys/dev/drm/amd/display/dc/dc_helper.c (revision b843c749addef9340ee7d4e250b09fdd492602a1)
1*b843c749SSergey Zigachev /*
2*b843c749SSergey Zigachev  * Copyright 2017 Advanced Micro Devices, Inc.
3*b843c749SSergey Zigachev  *
4*b843c749SSergey Zigachev  * Permission is hereby granted, free of charge, to any person obtaining a
5*b843c749SSergey Zigachev  * copy of this software and associated documentation files (the "Software"),
6*b843c749SSergey Zigachev  * to deal in the Software without restriction, including without limitation
7*b843c749SSergey Zigachev  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8*b843c749SSergey Zigachev  * and/or sell copies of the Software, and to permit persons to whom the
9*b843c749SSergey Zigachev  * Software is furnished to do so, subject to the following conditions:
10*b843c749SSergey Zigachev  *
11*b843c749SSergey Zigachev  * The above copyright notice and this permission notice shall be included in
12*b843c749SSergey Zigachev  * all copies or substantial portions of the Software.
13*b843c749SSergey Zigachev  *
14*b843c749SSergey Zigachev  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15*b843c749SSergey Zigachev  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16*b843c749SSergey Zigachev  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17*b843c749SSergey Zigachev  * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18*b843c749SSergey Zigachev  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19*b843c749SSergey Zigachev  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20*b843c749SSergey Zigachev  * OTHER DEALINGS IN THE SOFTWARE.
21*b843c749SSergey Zigachev  *
22*b843c749SSergey Zigachev  */
23*b843c749SSergey Zigachev /*
24*b843c749SSergey Zigachev  * dc_helper.c
25*b843c749SSergey Zigachev  *
26*b843c749SSergey Zigachev  *  Created on: Aug 30, 2016
27*b843c749SSergey Zigachev  *      Author: agrodzov
28*b843c749SSergey Zigachev  */
29*b843c749SSergey Zigachev #include "dm_services.h"
30*b843c749SSergey Zigachev #include <stdarg.h>
31*b843c749SSergey Zigachev 
32*b843c749SSergey Zigachev uint32_t generic_reg_update_ex(const struct dc_context *ctx,
33*b843c749SSergey Zigachev 		uint32_t addr, uint32_t reg_val, int n,
34*b843c749SSergey Zigachev 		uint8_t shift1, uint32_t mask1, uint32_t field_value1,
35*b843c749SSergey Zigachev 		...)
36*b843c749SSergey Zigachev {
37*b843c749SSergey Zigachev 	uint32_t shift, mask, field_value;
38*b843c749SSergey Zigachev 	int i = 1;
39*b843c749SSergey Zigachev 
40*b843c749SSergey Zigachev 	va_list ap;
41*b843c749SSergey Zigachev 	va_start(ap, field_value1);
42*b843c749SSergey Zigachev 
43*b843c749SSergey Zigachev 	reg_val = set_reg_field_value_ex(reg_val, field_value1, mask1, shift1);
44*b843c749SSergey Zigachev 
45*b843c749SSergey Zigachev 	while (i < n) {
46*b843c749SSergey Zigachev 		shift = va_arg(ap, uint32_t);
47*b843c749SSergey Zigachev 		mask = va_arg(ap, uint32_t);
48*b843c749SSergey Zigachev 		field_value = va_arg(ap, uint32_t);
49*b843c749SSergey Zigachev 
50*b843c749SSergey Zigachev 		reg_val = set_reg_field_value_ex(reg_val, field_value, mask, shift);
51*b843c749SSergey Zigachev 		i++;
52*b843c749SSergey Zigachev 	}
53*b843c749SSergey Zigachev 
54*b843c749SSergey Zigachev 	dm_write_reg(ctx, addr, reg_val);
55*b843c749SSergey Zigachev 	va_end(ap);
56*b843c749SSergey Zigachev 
57*b843c749SSergey Zigachev 	return reg_val;
58*b843c749SSergey Zigachev }
59*b843c749SSergey Zigachev 
60*b843c749SSergey Zigachev uint32_t generic_reg_get(const struct dc_context *ctx, uint32_t addr,
61*b843c749SSergey Zigachev 		uint8_t shift, uint32_t mask, uint32_t *field_value)
62*b843c749SSergey Zigachev {
63*b843c749SSergey Zigachev 	uint32_t reg_val = dm_read_reg(ctx, addr);
64*b843c749SSergey Zigachev 	*field_value = get_reg_field_value_ex(reg_val, mask, shift);
65*b843c749SSergey Zigachev 	return reg_val;
66*b843c749SSergey Zigachev }
67*b843c749SSergey Zigachev 
68*b843c749SSergey Zigachev uint32_t generic_reg_get2(const struct dc_context *ctx, uint32_t addr,
69*b843c749SSergey Zigachev 		uint8_t shift1, uint32_t mask1, uint32_t *field_value1,
70*b843c749SSergey Zigachev 		uint8_t shift2, uint32_t mask2, uint32_t *field_value2)
71*b843c749SSergey Zigachev {
72*b843c749SSergey Zigachev 	uint32_t reg_val = dm_read_reg(ctx, addr);
73*b843c749SSergey Zigachev 	*field_value1 = get_reg_field_value_ex(reg_val, mask1, shift1);
74*b843c749SSergey Zigachev 	*field_value2 = get_reg_field_value_ex(reg_val, mask2, shift2);
75*b843c749SSergey Zigachev 	return reg_val;
76*b843c749SSergey Zigachev }
77*b843c749SSergey Zigachev 
78*b843c749SSergey Zigachev uint32_t generic_reg_get3(const struct dc_context *ctx, uint32_t addr,
79*b843c749SSergey Zigachev 		uint8_t shift1, uint32_t mask1, uint32_t *field_value1,
80*b843c749SSergey Zigachev 		uint8_t shift2, uint32_t mask2, uint32_t *field_value2,
81*b843c749SSergey Zigachev 		uint8_t shift3, uint32_t mask3, uint32_t *field_value3)
82*b843c749SSergey Zigachev {
83*b843c749SSergey Zigachev 	uint32_t reg_val = dm_read_reg(ctx, addr);
84*b843c749SSergey Zigachev 	*field_value1 = get_reg_field_value_ex(reg_val, mask1, shift1);
85*b843c749SSergey Zigachev 	*field_value2 = get_reg_field_value_ex(reg_val, mask2, shift2);
86*b843c749SSergey Zigachev 	*field_value3 = get_reg_field_value_ex(reg_val, mask3, shift3);
87*b843c749SSergey Zigachev 	return reg_val;
88*b843c749SSergey Zigachev }
89*b843c749SSergey Zigachev 
90*b843c749SSergey Zigachev uint32_t generic_reg_get4(const struct dc_context *ctx, uint32_t addr,
91*b843c749SSergey Zigachev 		uint8_t shift1, uint32_t mask1, uint32_t *field_value1,
92*b843c749SSergey Zigachev 		uint8_t shift2, uint32_t mask2, uint32_t *field_value2,
93*b843c749SSergey Zigachev 		uint8_t shift3, uint32_t mask3, uint32_t *field_value3,
94*b843c749SSergey Zigachev 		uint8_t shift4, uint32_t mask4, uint32_t *field_value4)
95*b843c749SSergey Zigachev {
96*b843c749SSergey Zigachev 	uint32_t reg_val = dm_read_reg(ctx, addr);
97*b843c749SSergey Zigachev 	*field_value1 = get_reg_field_value_ex(reg_val, mask1, shift1);
98*b843c749SSergey Zigachev 	*field_value2 = get_reg_field_value_ex(reg_val, mask2, shift2);
99*b843c749SSergey Zigachev 	*field_value3 = get_reg_field_value_ex(reg_val, mask3, shift3);
100*b843c749SSergey Zigachev 	*field_value4 = get_reg_field_value_ex(reg_val, mask4, shift4);
101*b843c749SSergey Zigachev 	return reg_val;
102*b843c749SSergey Zigachev }
103*b843c749SSergey Zigachev 
104*b843c749SSergey Zigachev uint32_t generic_reg_get5(const struct dc_context *ctx, uint32_t addr,
105*b843c749SSergey Zigachev 		uint8_t shift1, uint32_t mask1, uint32_t *field_value1,
106*b843c749SSergey Zigachev 		uint8_t shift2, uint32_t mask2, uint32_t *field_value2,
107*b843c749SSergey Zigachev 		uint8_t shift3, uint32_t mask3, uint32_t *field_value3,
108*b843c749SSergey Zigachev 		uint8_t shift4, uint32_t mask4, uint32_t *field_value4,
109*b843c749SSergey Zigachev 		uint8_t shift5, uint32_t mask5, uint32_t *field_value5)
110*b843c749SSergey Zigachev {
111*b843c749SSergey Zigachev 	uint32_t reg_val = dm_read_reg(ctx, addr);
112*b843c749SSergey Zigachev 	*field_value1 = get_reg_field_value_ex(reg_val, mask1, shift1);
113*b843c749SSergey Zigachev 	*field_value2 = get_reg_field_value_ex(reg_val, mask2, shift2);
114*b843c749SSergey Zigachev 	*field_value3 = get_reg_field_value_ex(reg_val, mask3, shift3);
115*b843c749SSergey Zigachev 	*field_value4 = get_reg_field_value_ex(reg_val, mask4, shift4);
116*b843c749SSergey Zigachev 	*field_value5 = get_reg_field_value_ex(reg_val, mask5, shift5);
117*b843c749SSergey Zigachev 	return reg_val;
118*b843c749SSergey Zigachev }
119*b843c749SSergey Zigachev 
120*b843c749SSergey Zigachev uint32_t generic_reg_get6(const struct dc_context *ctx, uint32_t addr,
121*b843c749SSergey Zigachev 		uint8_t shift1, uint32_t mask1, uint32_t *field_value1,
122*b843c749SSergey Zigachev 		uint8_t shift2, uint32_t mask2, uint32_t *field_value2,
123*b843c749SSergey Zigachev 		uint8_t shift3, uint32_t mask3, uint32_t *field_value3,
124*b843c749SSergey Zigachev 		uint8_t shift4, uint32_t mask4, uint32_t *field_value4,
125*b843c749SSergey Zigachev 		uint8_t shift5, uint32_t mask5, uint32_t *field_value5,
126*b843c749SSergey Zigachev 		uint8_t shift6, uint32_t mask6, uint32_t *field_value6)
127*b843c749SSergey Zigachev {
128*b843c749SSergey Zigachev 	uint32_t reg_val = dm_read_reg(ctx, addr);
129*b843c749SSergey Zigachev 	*field_value1 = get_reg_field_value_ex(reg_val, mask1, shift1);
130*b843c749SSergey Zigachev 	*field_value2 = get_reg_field_value_ex(reg_val, mask2, shift2);
131*b843c749SSergey Zigachev 	*field_value3 = get_reg_field_value_ex(reg_val, mask3, shift3);
132*b843c749SSergey Zigachev 	*field_value4 = get_reg_field_value_ex(reg_val, mask4, shift4);
133*b843c749SSergey Zigachev 	*field_value5 = get_reg_field_value_ex(reg_val, mask5, shift5);
134*b843c749SSergey Zigachev 	*field_value6 = get_reg_field_value_ex(reg_val, mask6, shift6);
135*b843c749SSergey Zigachev 	return reg_val;
136*b843c749SSergey Zigachev }
137*b843c749SSergey Zigachev 
138*b843c749SSergey Zigachev uint32_t generic_reg_get7(const struct dc_context *ctx, uint32_t addr,
139*b843c749SSergey Zigachev 		uint8_t shift1, uint32_t mask1, uint32_t *field_value1,
140*b843c749SSergey Zigachev 		uint8_t shift2, uint32_t mask2, uint32_t *field_value2,
141*b843c749SSergey Zigachev 		uint8_t shift3, uint32_t mask3, uint32_t *field_value3,
142*b843c749SSergey Zigachev 		uint8_t shift4, uint32_t mask4, uint32_t *field_value4,
143*b843c749SSergey Zigachev 		uint8_t shift5, uint32_t mask5, uint32_t *field_value5,
144*b843c749SSergey Zigachev 		uint8_t shift6, uint32_t mask6, uint32_t *field_value6,
145*b843c749SSergey Zigachev 		uint8_t shift7, uint32_t mask7, uint32_t *field_value7)
146*b843c749SSergey Zigachev {
147*b843c749SSergey Zigachev 	uint32_t reg_val = dm_read_reg(ctx, addr);
148*b843c749SSergey Zigachev 	*field_value1 = get_reg_field_value_ex(reg_val, mask1, shift1);
149*b843c749SSergey Zigachev 	*field_value2 = get_reg_field_value_ex(reg_val, mask2, shift2);
150*b843c749SSergey Zigachev 	*field_value3 = get_reg_field_value_ex(reg_val, mask3, shift3);
151*b843c749SSergey Zigachev 	*field_value4 = get_reg_field_value_ex(reg_val, mask4, shift4);
152*b843c749SSergey Zigachev 	*field_value5 = get_reg_field_value_ex(reg_val, mask5, shift5);
153*b843c749SSergey Zigachev 	*field_value6 = get_reg_field_value_ex(reg_val, mask6, shift6);
154*b843c749SSergey Zigachev 	*field_value7 = get_reg_field_value_ex(reg_val, mask7, shift7);
155*b843c749SSergey Zigachev 	return reg_val;
156*b843c749SSergey Zigachev }
157*b843c749SSergey Zigachev 
158*b843c749SSergey Zigachev uint32_t generic_reg_get8(const struct dc_context *ctx, uint32_t addr,
159*b843c749SSergey Zigachev 		uint8_t shift1, uint32_t mask1, uint32_t *field_value1,
160*b843c749SSergey Zigachev 		uint8_t shift2, uint32_t mask2, uint32_t *field_value2,
161*b843c749SSergey Zigachev 		uint8_t shift3, uint32_t mask3, uint32_t *field_value3,
162*b843c749SSergey Zigachev 		uint8_t shift4, uint32_t mask4, uint32_t *field_value4,
163*b843c749SSergey Zigachev 		uint8_t shift5, uint32_t mask5, uint32_t *field_value5,
164*b843c749SSergey Zigachev 		uint8_t shift6, uint32_t mask6, uint32_t *field_value6,
165*b843c749SSergey Zigachev 		uint8_t shift7, uint32_t mask7, uint32_t *field_value7,
166*b843c749SSergey Zigachev 		uint8_t shift8, uint32_t mask8, uint32_t *field_value8)
167*b843c749SSergey Zigachev {
168*b843c749SSergey Zigachev 	uint32_t reg_val = dm_read_reg(ctx, addr);
169*b843c749SSergey Zigachev 	*field_value1 = get_reg_field_value_ex(reg_val, mask1, shift1);
170*b843c749SSergey Zigachev 	*field_value2 = get_reg_field_value_ex(reg_val, mask2, shift2);
171*b843c749SSergey Zigachev 	*field_value3 = get_reg_field_value_ex(reg_val, mask3, shift3);
172*b843c749SSergey Zigachev 	*field_value4 = get_reg_field_value_ex(reg_val, mask4, shift4);
173*b843c749SSergey Zigachev 	*field_value5 = get_reg_field_value_ex(reg_val, mask5, shift5);
174*b843c749SSergey Zigachev 	*field_value6 = get_reg_field_value_ex(reg_val, mask6, shift6);
175*b843c749SSergey Zigachev 	*field_value7 = get_reg_field_value_ex(reg_val, mask7, shift7);
176*b843c749SSergey Zigachev 	*field_value8 = get_reg_field_value_ex(reg_val, mask8, shift8);
177*b843c749SSergey Zigachev 	return reg_val;
178*b843c749SSergey Zigachev }
179*b843c749SSergey Zigachev /* note:  va version of this is pretty bad idea, since there is a output parameter pass by pointer
180*b843c749SSergey Zigachev  * compiler won't be able to check for size match and is prone to stack corruption type of bugs
181*b843c749SSergey Zigachev 
182*b843c749SSergey Zigachev uint32_t generic_reg_get(const struct dc_context *ctx,
183*b843c749SSergey Zigachev 		uint32_t addr, int n, ...)
184*b843c749SSergey Zigachev {
185*b843c749SSergey Zigachev 	uint32_t shift, mask;
186*b843c749SSergey Zigachev 	uint32_t *field_value;
187*b843c749SSergey Zigachev 	uint32_t reg_val;
188*b843c749SSergey Zigachev 	int i = 0;
189*b843c749SSergey Zigachev 
190*b843c749SSergey Zigachev 	reg_val = dm_read_reg(ctx, addr);
191*b843c749SSergey Zigachev 
192*b843c749SSergey Zigachev 	va_list ap;
193*b843c749SSergey Zigachev 	va_start(ap, n);
194*b843c749SSergey Zigachev 
195*b843c749SSergey Zigachev 	while (i < n) {
196*b843c749SSergey Zigachev 		shift = va_arg(ap, uint32_t);
197*b843c749SSergey Zigachev 		mask = va_arg(ap, uint32_t);
198*b843c749SSergey Zigachev 		field_value = va_arg(ap, uint32_t *);
199*b843c749SSergey Zigachev 
200*b843c749SSergey Zigachev 		*field_value = get_reg_field_value_ex(reg_val, mask, shift);
201*b843c749SSergey Zigachev 		i++;
202*b843c749SSergey Zigachev 	}
203*b843c749SSergey Zigachev 
204*b843c749SSergey Zigachev 	va_end(ap);
205*b843c749SSergey Zigachev 
206*b843c749SSergey Zigachev 	return reg_val;
207*b843c749SSergey Zigachev }
208*b843c749SSergey Zigachev */
209*b843c749SSergey Zigachev 
210*b843c749SSergey Zigachev uint32_t generic_reg_wait(const struct dc_context *ctx,
211*b843c749SSergey Zigachev 	uint32_t addr, uint32_t shift, uint32_t mask, uint32_t condition_value,
212*b843c749SSergey Zigachev 	unsigned int delay_between_poll_us, unsigned int time_out_num_tries,
213*b843c749SSergey Zigachev 	const char *func_name, int line)
214*b843c749SSergey Zigachev {
215*b843c749SSergey Zigachev 	uint32_t field_value;
216*b843c749SSergey Zigachev 	uint32_t reg_val;
217*b843c749SSergey Zigachev 	int i;
218*b843c749SSergey Zigachev 
219*b843c749SSergey Zigachev 	/* something is terribly wrong if time out is > 200ms. (5Hz) */
220*b843c749SSergey Zigachev 	ASSERT(delay_between_poll_us * time_out_num_tries <= 200000);
221*b843c749SSergey Zigachev 
222*b843c749SSergey Zigachev 	if (IS_FPGA_MAXIMUS_DC(ctx->dce_environment)) {
223*b843c749SSergey Zigachev 		/* 35 seconds */
224*b843c749SSergey Zigachev 		delay_between_poll_us = 35000;
225*b843c749SSergey Zigachev 		time_out_num_tries = 1000;
226*b843c749SSergey Zigachev 	}
227*b843c749SSergey Zigachev 
228*b843c749SSergey Zigachev 	for (i = 0; i <= time_out_num_tries; i++) {
229*b843c749SSergey Zigachev 		if (i) {
230*b843c749SSergey Zigachev 			if (delay_between_poll_us >= 1000)
231*b843c749SSergey Zigachev 				msleep(delay_between_poll_us/1000);
232*b843c749SSergey Zigachev 			else if (delay_between_poll_us > 0)
233*b843c749SSergey Zigachev 				udelay(delay_between_poll_us);
234*b843c749SSergey Zigachev 		}
235*b843c749SSergey Zigachev 
236*b843c749SSergey Zigachev 		reg_val = dm_read_reg(ctx, addr);
237*b843c749SSergey Zigachev 
238*b843c749SSergey Zigachev 		field_value = get_reg_field_value_ex(reg_val, mask, shift);
239*b843c749SSergey Zigachev 
240*b843c749SSergey Zigachev 		if (field_value == condition_value) {
241*b843c749SSergey Zigachev 			if (i * delay_between_poll_us > 1000)
242*b843c749SSergey Zigachev 				dm_output_to_console("REG_WAIT taking a while: %dms in %s line:%d\n",
243*b843c749SSergey Zigachev 						delay_between_poll_us * i / 1000,
244*b843c749SSergey Zigachev 						func_name, line);
245*b843c749SSergey Zigachev 			return reg_val;
246*b843c749SSergey Zigachev 		}
247*b843c749SSergey Zigachev 	}
248*b843c749SSergey Zigachev 
249*b843c749SSergey Zigachev 	dm_error("REG_WAIT timeout %dus * %d tries - %s line:%d\n",
250*b843c749SSergey Zigachev 			delay_between_poll_us, time_out_num_tries,
251*b843c749SSergey Zigachev 			func_name, line);
252*b843c749SSergey Zigachev 
253*b843c749SSergey Zigachev 	if (!IS_FPGA_MAXIMUS_DC(ctx->dce_environment))
254*b843c749SSergey Zigachev 		BREAK_TO_DEBUGGER();
255*b843c749SSergey Zigachev 
256*b843c749SSergey Zigachev 	return reg_val;
257*b843c749SSergey Zigachev }
258*b843c749SSergey Zigachev 
259*b843c749SSergey Zigachev void generic_write_indirect_reg(const struct dc_context *ctx,
260*b843c749SSergey Zigachev 		uint32_t addr_index, uint32_t addr_data,
261*b843c749SSergey Zigachev 		uint32_t index, uint32_t data)
262*b843c749SSergey Zigachev {
263*b843c749SSergey Zigachev 	dm_write_reg(ctx, addr_index, index);
264*b843c749SSergey Zigachev 	dm_write_reg(ctx, addr_data, data);
265*b843c749SSergey Zigachev }
266*b843c749SSergey Zigachev 
267*b843c749SSergey Zigachev uint32_t generic_read_indirect_reg(const struct dc_context *ctx,
268*b843c749SSergey Zigachev 		uint32_t addr_index, uint32_t addr_data,
269*b843c749SSergey Zigachev 		uint32_t index)
270*b843c749SSergey Zigachev {
271*b843c749SSergey Zigachev 	uint32_t value = 0;
272*b843c749SSergey Zigachev 
273*b843c749SSergey Zigachev 	dm_write_reg(ctx, addr_index, index);
274*b843c749SSergey Zigachev 	value = dm_read_reg(ctx, addr_data);
275*b843c749SSergey Zigachev 
276*b843c749SSergey Zigachev 	return value;
277*b843c749SSergey Zigachev }
278*b843c749SSergey Zigachev 
279*b843c749SSergey Zigachev 
280*b843c749SSergey Zigachev uint32_t generic_indirect_reg_update_ex(const struct dc_context *ctx,
281*b843c749SSergey Zigachev 		uint32_t addr_index, uint32_t addr_data,
282*b843c749SSergey Zigachev 		uint32_t index, uint32_t reg_val, int n,
283*b843c749SSergey Zigachev 		uint8_t shift1, uint32_t mask1, uint32_t field_value1,
284*b843c749SSergey Zigachev 		...)
285*b843c749SSergey Zigachev {
286*b843c749SSergey Zigachev 	uint32_t shift, mask, field_value;
287*b843c749SSergey Zigachev 	int i = 1;
288*b843c749SSergey Zigachev 
289*b843c749SSergey Zigachev 	va_list ap;
290*b843c749SSergey Zigachev 
291*b843c749SSergey Zigachev 	va_start(ap, field_value1);
292*b843c749SSergey Zigachev 
293*b843c749SSergey Zigachev 	reg_val = set_reg_field_value_ex(reg_val, field_value1, mask1, shift1);
294*b843c749SSergey Zigachev 
295*b843c749SSergey Zigachev 	while (i < n) {
296*b843c749SSergey Zigachev 		shift = va_arg(ap, uint32_t);
297*b843c749SSergey Zigachev 		mask = va_arg(ap, uint32_t);
298*b843c749SSergey Zigachev 		field_value = va_arg(ap, uint32_t);
299*b843c749SSergey Zigachev 
300*b843c749SSergey Zigachev 		reg_val = set_reg_field_value_ex(reg_val, field_value, mask, shift);
301*b843c749SSergey Zigachev 		i++;
302*b843c749SSergey Zigachev 	}
303*b843c749SSergey Zigachev 
304*b843c749SSergey Zigachev 	generic_write_indirect_reg(ctx, addr_index, addr_data, index, reg_val);
305*b843c749SSergey Zigachev 	va_end(ap);
306*b843c749SSergey Zigachev 
307*b843c749SSergey Zigachev 	return reg_val;
308*b843c749SSergey Zigachev }
309