drm/amd: drop dependencies on drm_os_linux.h
[linux-2.6-microblaze.git] / drivers / gpu / drm / amd / display / dc / dc_helper.c
1 /*
2  * Copyright 2017 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  */
23 /*
24  * dc_helper.c
25  *
26  *  Created on: Aug 30, 2016
27  *      Author: agrodzov
28  */
29
30 #include <linux/delay.h>
31
32 #include "dm_services.h"
33 #include <stdarg.h>
34
35 struct dc_reg_value_masks {
36         uint32_t value;
37         uint32_t mask;
38 };
39
40 struct dc_reg_sequence {
41         uint32_t addr;
42         struct dc_reg_value_masks value_masks;
43 };
44
45 static inline void set_reg_field_value_masks(
46         struct dc_reg_value_masks *field_value_mask,
47         uint32_t value,
48         uint32_t mask,
49         uint8_t shift)
50 {
51         ASSERT(mask != 0);
52
53         field_value_mask->value = (field_value_mask->value & ~mask) | (mask & (value << shift));
54         field_value_mask->mask = field_value_mask->mask | mask;
55 }
56
57 static void set_reg_field_values(struct dc_reg_value_masks *field_value_mask,
58                 uint32_t addr, int n,
59                 uint8_t shift1, uint32_t mask1, uint32_t field_value1,
60                 va_list ap)
61 {
62         uint32_t shift, mask, field_value;
63         int i = 1;
64
65         /* gather all bits value/mask getting updated in this register */
66         set_reg_field_value_masks(field_value_mask,
67                         field_value1, mask1, shift1);
68
69         while (i < n) {
70                 shift = va_arg(ap, uint32_t);
71                 mask = va_arg(ap, uint32_t);
72                 field_value = va_arg(ap, uint32_t);
73
74                 set_reg_field_value_masks(field_value_mask,
75                                 field_value, mask, shift);
76                 i++;
77         }
78 }
79
80 uint32_t generic_reg_update_ex(const struct dc_context *ctx,
81                 uint32_t addr, int n,
82                 uint8_t shift1, uint32_t mask1, uint32_t field_value1,
83                 ...)
84 {
85         struct dc_reg_value_masks field_value_mask = {0};
86         uint32_t reg_val;
87         va_list ap;
88
89         va_start(ap, field_value1);
90
91         set_reg_field_values(&field_value_mask, addr, n, shift1, mask1,
92                         field_value1, ap);
93
94         va_end(ap);
95
96         /* mmio write directly */
97         reg_val = dm_read_reg(ctx, addr);
98         reg_val = (reg_val & ~field_value_mask.mask) | field_value_mask.value;
99         dm_write_reg(ctx, addr, reg_val);
100         return reg_val;
101 }
102
103 uint32_t generic_reg_set_ex(const struct dc_context *ctx,
104                 uint32_t addr, uint32_t reg_val, int n,
105                 uint8_t shift1, uint32_t mask1, uint32_t field_value1,
106                 ...)
107 {
108         struct dc_reg_value_masks field_value_mask = {0};
109         va_list ap;
110
111         va_start(ap, field_value1);
112
113         set_reg_field_values(&field_value_mask, addr, n, shift1, mask1,
114                         field_value1, ap);
115
116         va_end(ap);
117
118
119         /* mmio write directly */
120         reg_val = (reg_val & ~field_value_mask.mask) | field_value_mask.value;
121         dm_write_reg(ctx, addr, reg_val);
122         return reg_val;
123 }
124
125 uint32_t dm_read_reg_func(
126         const struct dc_context *ctx,
127         uint32_t address,
128         const char *func_name)
129 {
130         uint32_t value;
131 #ifdef DM_CHECK_ADDR_0
132         if (address == 0) {
133                 DC_ERR("invalid register read; address = 0\n");
134                 return 0;
135         }
136 #endif
137         value = cgs_read_register(ctx->cgs_device, address);
138         trace_amdgpu_dc_rreg(&ctx->perf_trace->read_count, address, value);
139
140         return value;
141 }
142
143 uint32_t generic_reg_get(const struct dc_context *ctx, uint32_t addr,
144                 uint8_t shift, uint32_t mask, uint32_t *field_value)
145 {
146         uint32_t reg_val = dm_read_reg(ctx, addr);
147         *field_value = get_reg_field_value_ex(reg_val, mask, shift);
148         return reg_val;
149 }
150
151 uint32_t generic_reg_get2(const struct dc_context *ctx, uint32_t addr,
152                 uint8_t shift1, uint32_t mask1, uint32_t *field_value1,
153                 uint8_t shift2, uint32_t mask2, uint32_t *field_value2)
154 {
155         uint32_t reg_val = dm_read_reg(ctx, addr);
156         *field_value1 = get_reg_field_value_ex(reg_val, mask1, shift1);
157         *field_value2 = get_reg_field_value_ex(reg_val, mask2, shift2);
158         return reg_val;
159 }
160
161 uint32_t generic_reg_get3(const struct dc_context *ctx, uint32_t addr,
162                 uint8_t shift1, uint32_t mask1, uint32_t *field_value1,
163                 uint8_t shift2, uint32_t mask2, uint32_t *field_value2,
164                 uint8_t shift3, uint32_t mask3, uint32_t *field_value3)
165 {
166         uint32_t reg_val = dm_read_reg(ctx, addr);
167         *field_value1 = get_reg_field_value_ex(reg_val, mask1, shift1);
168         *field_value2 = get_reg_field_value_ex(reg_val, mask2, shift2);
169         *field_value3 = get_reg_field_value_ex(reg_val, mask3, shift3);
170         return reg_val;
171 }
172
173 uint32_t generic_reg_get4(const struct dc_context *ctx, uint32_t addr,
174                 uint8_t shift1, uint32_t mask1, uint32_t *field_value1,
175                 uint8_t shift2, uint32_t mask2, uint32_t *field_value2,
176                 uint8_t shift3, uint32_t mask3, uint32_t *field_value3,
177                 uint8_t shift4, uint32_t mask4, uint32_t *field_value4)
178 {
179         uint32_t reg_val = dm_read_reg(ctx, addr);
180         *field_value1 = get_reg_field_value_ex(reg_val, mask1, shift1);
181         *field_value2 = get_reg_field_value_ex(reg_val, mask2, shift2);
182         *field_value3 = get_reg_field_value_ex(reg_val, mask3, shift3);
183         *field_value4 = get_reg_field_value_ex(reg_val, mask4, shift4);
184         return reg_val;
185 }
186
187 uint32_t generic_reg_get5(const struct dc_context *ctx, uint32_t addr,
188                 uint8_t shift1, uint32_t mask1, uint32_t *field_value1,
189                 uint8_t shift2, uint32_t mask2, uint32_t *field_value2,
190                 uint8_t shift3, uint32_t mask3, uint32_t *field_value3,
191                 uint8_t shift4, uint32_t mask4, uint32_t *field_value4,
192                 uint8_t shift5, uint32_t mask5, uint32_t *field_value5)
193 {
194         uint32_t reg_val = dm_read_reg(ctx, addr);
195         *field_value1 = get_reg_field_value_ex(reg_val, mask1, shift1);
196         *field_value2 = get_reg_field_value_ex(reg_val, mask2, shift2);
197         *field_value3 = get_reg_field_value_ex(reg_val, mask3, shift3);
198         *field_value4 = get_reg_field_value_ex(reg_val, mask4, shift4);
199         *field_value5 = get_reg_field_value_ex(reg_val, mask5, shift5);
200         return reg_val;
201 }
202
203 uint32_t generic_reg_get6(const struct dc_context *ctx, uint32_t addr,
204                 uint8_t shift1, uint32_t mask1, uint32_t *field_value1,
205                 uint8_t shift2, uint32_t mask2, uint32_t *field_value2,
206                 uint8_t shift3, uint32_t mask3, uint32_t *field_value3,
207                 uint8_t shift4, uint32_t mask4, uint32_t *field_value4,
208                 uint8_t shift5, uint32_t mask5, uint32_t *field_value5,
209                 uint8_t shift6, uint32_t mask6, uint32_t *field_value6)
210 {
211         uint32_t reg_val = dm_read_reg(ctx, addr);
212         *field_value1 = get_reg_field_value_ex(reg_val, mask1, shift1);
213         *field_value2 = get_reg_field_value_ex(reg_val, mask2, shift2);
214         *field_value3 = get_reg_field_value_ex(reg_val, mask3, shift3);
215         *field_value4 = get_reg_field_value_ex(reg_val, mask4, shift4);
216         *field_value5 = get_reg_field_value_ex(reg_val, mask5, shift5);
217         *field_value6 = get_reg_field_value_ex(reg_val, mask6, shift6);
218         return reg_val;
219 }
220
221 uint32_t generic_reg_get7(const struct dc_context *ctx, uint32_t addr,
222                 uint8_t shift1, uint32_t mask1, uint32_t *field_value1,
223                 uint8_t shift2, uint32_t mask2, uint32_t *field_value2,
224                 uint8_t shift3, uint32_t mask3, uint32_t *field_value3,
225                 uint8_t shift4, uint32_t mask4, uint32_t *field_value4,
226                 uint8_t shift5, uint32_t mask5, uint32_t *field_value5,
227                 uint8_t shift6, uint32_t mask6, uint32_t *field_value6,
228                 uint8_t shift7, uint32_t mask7, uint32_t *field_value7)
229 {
230         uint32_t reg_val = dm_read_reg(ctx, addr);
231         *field_value1 = get_reg_field_value_ex(reg_val, mask1, shift1);
232         *field_value2 = get_reg_field_value_ex(reg_val, mask2, shift2);
233         *field_value3 = get_reg_field_value_ex(reg_val, mask3, shift3);
234         *field_value4 = get_reg_field_value_ex(reg_val, mask4, shift4);
235         *field_value5 = get_reg_field_value_ex(reg_val, mask5, shift5);
236         *field_value6 = get_reg_field_value_ex(reg_val, mask6, shift6);
237         *field_value7 = get_reg_field_value_ex(reg_val, mask7, shift7);
238         return reg_val;
239 }
240
241 uint32_t generic_reg_get8(const struct dc_context *ctx, uint32_t addr,
242                 uint8_t shift1, uint32_t mask1, uint32_t *field_value1,
243                 uint8_t shift2, uint32_t mask2, uint32_t *field_value2,
244                 uint8_t shift3, uint32_t mask3, uint32_t *field_value3,
245                 uint8_t shift4, uint32_t mask4, uint32_t *field_value4,
246                 uint8_t shift5, uint32_t mask5, uint32_t *field_value5,
247                 uint8_t shift6, uint32_t mask6, uint32_t *field_value6,
248                 uint8_t shift7, uint32_t mask7, uint32_t *field_value7,
249                 uint8_t shift8, uint32_t mask8, uint32_t *field_value8)
250 {
251         uint32_t reg_val = dm_read_reg(ctx, addr);
252         *field_value1 = get_reg_field_value_ex(reg_val, mask1, shift1);
253         *field_value2 = get_reg_field_value_ex(reg_val, mask2, shift2);
254         *field_value3 = get_reg_field_value_ex(reg_val, mask3, shift3);
255         *field_value4 = get_reg_field_value_ex(reg_val, mask4, shift4);
256         *field_value5 = get_reg_field_value_ex(reg_val, mask5, shift5);
257         *field_value6 = get_reg_field_value_ex(reg_val, mask6, shift6);
258         *field_value7 = get_reg_field_value_ex(reg_val, mask7, shift7);
259         *field_value8 = get_reg_field_value_ex(reg_val, mask8, shift8);
260         return reg_val;
261 }
262 /* note:  va version of this is pretty bad idea, since there is a output parameter pass by pointer
263  * compiler won't be able to check for size match and is prone to stack corruption type of bugs
264
265 uint32_t generic_reg_get(const struct dc_context *ctx,
266                 uint32_t addr, int n, ...)
267 {
268         uint32_t shift, mask;
269         uint32_t *field_value;
270         uint32_t reg_val;
271         int i = 0;
272
273         reg_val = dm_read_reg(ctx, addr);
274
275         va_list ap;
276         va_start(ap, n);
277
278         while (i < n) {
279                 shift = va_arg(ap, uint32_t);
280                 mask = va_arg(ap, uint32_t);
281                 field_value = va_arg(ap, uint32_t *);
282
283                 *field_value = get_reg_field_value_ex(reg_val, mask, shift);
284                 i++;
285         }
286
287         va_end(ap);
288
289         return reg_val;
290 }
291 */
292
293 void generic_reg_wait(const struct dc_context *ctx,
294         uint32_t addr, uint32_t shift, uint32_t mask, uint32_t condition_value,
295         unsigned int delay_between_poll_us, unsigned int time_out_num_tries,
296         const char *func_name, int line)
297 {
298         uint32_t field_value;
299         uint32_t reg_val;
300         int i;
301
302         /* something is terribly wrong if time out is > 200ms. (5Hz) */
303         ASSERT(delay_between_poll_us * time_out_num_tries <= 200000);
304
305         for (i = 0; i <= time_out_num_tries; i++) {
306                 if (i) {
307                         if (delay_between_poll_us >= 1000)
308                                 msleep(delay_between_poll_us/1000);
309                         else if (delay_between_poll_us > 0)
310                                 udelay(delay_between_poll_us);
311                 }
312
313                 reg_val = dm_read_reg(ctx, addr);
314
315                 field_value = get_reg_field_value_ex(reg_val, mask, shift);
316
317                 if (field_value == condition_value) {
318                         if (i * delay_between_poll_us > 1000 &&
319                                         !IS_FPGA_MAXIMUS_DC(ctx->dce_environment))
320                                 DC_LOG_DC("REG_WAIT taking a while: %dms in %s line:%d\n",
321                                                 delay_between_poll_us * i / 1000,
322                                                 func_name, line);
323                         return;
324                 }
325         }
326
327         DC_LOG_WARNING("REG_WAIT timeout %dus * %d tries - %s line:%d\n",
328                         delay_between_poll_us, time_out_num_tries,
329                         func_name, line);
330
331         if (!IS_FPGA_MAXIMUS_DC(ctx->dce_environment))
332                 BREAK_TO_DEBUGGER();
333 }
334
335 void generic_write_indirect_reg(const struct dc_context *ctx,
336                 uint32_t addr_index, uint32_t addr_data,
337                 uint32_t index, uint32_t data)
338 {
339         dm_write_reg(ctx, addr_index, index);
340         dm_write_reg(ctx, addr_data, data);
341 }
342
343 uint32_t generic_read_indirect_reg(const struct dc_context *ctx,
344                 uint32_t addr_index, uint32_t addr_data,
345                 uint32_t index)
346 {
347         uint32_t value = 0;
348
349         dm_write_reg(ctx, addr_index, index);
350         value = dm_read_reg(ctx, addr_data);
351
352         return value;
353 }
354
355
356 uint32_t generic_indirect_reg_update_ex(const struct dc_context *ctx,
357                 uint32_t addr_index, uint32_t addr_data,
358                 uint32_t index, uint32_t reg_val, int n,
359                 uint8_t shift1, uint32_t mask1, uint32_t field_value1,
360                 ...)
361 {
362         uint32_t shift, mask, field_value;
363         int i = 1;
364
365         va_list ap;
366
367         va_start(ap, field_value1);
368
369         reg_val = set_reg_field_value_ex(reg_val, field_value1, mask1, shift1);
370
371         while (i < n) {
372                 shift = va_arg(ap, uint32_t);
373                 mask = va_arg(ap, uint32_t);
374                 field_value = va_arg(ap, uint32_t);
375
376                 reg_val = set_reg_field_value_ex(reg_val, field_value, mask, shift);
377                 i++;
378         }
379
380         generic_write_indirect_reg(ctx, addr_index, addr_data, index, reg_val);
381         va_end(ap);
382
383         return reg_val;
384 }