Linux-libre 5.4.47-gnu
[librecmc/linux-libre.git] / drivers / gpu / drm / amd / display / include / fixed31_32.h
1 /*
2  * Copyright 2012-15 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
26 #ifndef __DAL_FIXED31_32_H__
27 #define __DAL_FIXED31_32_H__
28
29 #ifndef LLONG_MAX
30 #define LLONG_MAX 9223372036854775807ll
31 #endif
32 #ifndef LLONG_MIN
33 #define LLONG_MIN (-LLONG_MAX - 1ll)
34 #endif
35
36 #define FIXED31_32_BITS_PER_FRACTIONAL_PART 32
37 #ifndef LLONG_MIN
38 #define LLONG_MIN (1LL<<63)
39 #endif
40 #ifndef LLONG_MAX
41 #define LLONG_MAX (-1LL>>1)
42 #endif
43
44 /*
45  * @brief
46  * Arithmetic operations on real numbers
47  * represented as fixed-point numbers.
48  * There are: 1 bit for sign,
49  * 31 bit for integer part,
50  * 32 bits for fractional part.
51  *
52  * @note
53  * Currently, overflows and underflows are asserted;
54  * no special result returned.
55  */
56
57 struct fixed31_32 {
58         long long value;
59 };
60
61
62 /*
63  * @brief
64  * Useful constants
65  */
66
67 static const struct fixed31_32 dc_fixpt_zero = { 0 };
68 static const struct fixed31_32 dc_fixpt_epsilon = { 1LL };
69 static const struct fixed31_32 dc_fixpt_half = { 0x80000000LL };
70 static const struct fixed31_32 dc_fixpt_one = { 0x100000000LL };
71
72 static const struct fixed31_32 dc_fixpt_pi = { 13493037705LL };
73 static const struct fixed31_32 dc_fixpt_two_pi = { 26986075409LL };
74 static const struct fixed31_32 dc_fixpt_e = { 11674931555LL };
75 static const struct fixed31_32 dc_fixpt_ln2 = { 2977044471LL };
76 static const struct fixed31_32 dc_fixpt_ln2_div_2 = { 1488522236LL };
77
78 /*
79  * @brief
80  * Initialization routines
81  */
82
83 /*
84  * @brief
85  * result = numerator / denominator
86  */
87 struct fixed31_32 dc_fixpt_from_fraction(long long numerator, long long denominator);
88
89 /*
90  * @brief
91  * result = arg
92  */
93 static inline struct fixed31_32 dc_fixpt_from_int(int arg)
94 {
95         struct fixed31_32 res;
96
97         res.value = (long long) arg << FIXED31_32_BITS_PER_FRACTIONAL_PART;
98
99         return res;
100 }
101
102 /*
103  * @brief
104  * Unary operators
105  */
106
107 /*
108  * @brief
109  * result = -arg
110  */
111 static inline struct fixed31_32 dc_fixpt_neg(struct fixed31_32 arg)
112 {
113         struct fixed31_32 res;
114
115         res.value = -arg.value;
116
117         return res;
118 }
119
120 /*
121  * @brief
122  * result = abs(arg) := (arg >= 0) ? arg : -arg
123  */
124 static inline struct fixed31_32 dc_fixpt_abs(struct fixed31_32 arg)
125 {
126         if (arg.value < 0)
127                 return dc_fixpt_neg(arg);
128         else
129                 return arg;
130 }
131
132 /*
133  * @brief
134  * Binary relational operators
135  */
136
137 /*
138  * @brief
139  * result = arg1 < arg2
140  */
141 static inline bool dc_fixpt_lt(struct fixed31_32 arg1, struct fixed31_32 arg2)
142 {
143         return arg1.value < arg2.value;
144 }
145
146 /*
147  * @brief
148  * result = arg1 <= arg2
149  */
150 static inline bool dc_fixpt_le(struct fixed31_32 arg1, struct fixed31_32 arg2)
151 {
152         return arg1.value <= arg2.value;
153 }
154
155 /*
156  * @brief
157  * result = arg1 == arg2
158  */
159 static inline bool dc_fixpt_eq(struct fixed31_32 arg1, struct fixed31_32 arg2)
160 {
161         return arg1.value == arg2.value;
162 }
163
164 /*
165  * @brief
166  * result = min(arg1, arg2) := (arg1 <= arg2) ? arg1 : arg2
167  */
168 static inline struct fixed31_32 dc_fixpt_min(struct fixed31_32 arg1, struct fixed31_32 arg2)
169 {
170         if (arg1.value <= arg2.value)
171                 return arg1;
172         else
173                 return arg2;
174 }
175
176 /*
177  * @brief
178  * result = max(arg1, arg2) := (arg1 <= arg2) ? arg2 : arg1
179  */
180 static inline struct fixed31_32 dc_fixpt_max(struct fixed31_32 arg1, struct fixed31_32 arg2)
181 {
182         if (arg1.value <= arg2.value)
183                 return arg2;
184         else
185                 return arg1;
186 }
187
188 /*
189  * @brief
190  *          | min_value, when arg <= min_value
191  * result = | arg, when min_value < arg < max_value
192  *          | max_value, when arg >= max_value
193  */
194 static inline struct fixed31_32 dc_fixpt_clamp(
195         struct fixed31_32 arg,
196         struct fixed31_32 min_value,
197         struct fixed31_32 max_value)
198 {
199         if (dc_fixpt_le(arg, min_value))
200                 return min_value;
201         else if (dc_fixpt_le(max_value, arg))
202                 return max_value;
203         else
204                 return arg;
205 }
206
207 /*
208  * @brief
209  * Binary shift operators
210  */
211
212 /*
213  * @brief
214  * result = arg << shift
215  */
216 static inline struct fixed31_32 dc_fixpt_shl(struct fixed31_32 arg, unsigned char shift)
217 {
218         ASSERT(((arg.value >= 0) && (arg.value <= LLONG_MAX >> shift)) ||
219                 ((arg.value < 0) && (arg.value >= ~(LLONG_MAX >> shift))));
220
221         arg.value = arg.value << shift;
222
223         return arg;
224 }
225
226 /*
227  * @brief
228  * result = arg >> shift
229  */
230 static inline struct fixed31_32 dc_fixpt_shr(struct fixed31_32 arg, unsigned char shift)
231 {
232         bool negative = arg.value < 0;
233
234         if (negative)
235                 arg.value = -arg.value;
236         arg.value = arg.value >> shift;
237         if (negative)
238                 arg.value = -arg.value;
239         return arg;
240 }
241
242 /*
243  * @brief
244  * Binary additive operators
245  */
246
247 /*
248  * @brief
249  * result = arg1 + arg2
250  */
251 static inline struct fixed31_32 dc_fixpt_add(struct fixed31_32 arg1, struct fixed31_32 arg2)
252 {
253         struct fixed31_32 res;
254
255         ASSERT(((arg1.value >= 0) && (LLONG_MAX - arg1.value >= arg2.value)) ||
256                 ((arg1.value < 0) && (LLONG_MIN - arg1.value <= arg2.value)));
257
258         res.value = arg1.value + arg2.value;
259
260         return res;
261 }
262
263 /*
264  * @brief
265  * result = arg1 + arg2
266  */
267 static inline struct fixed31_32 dc_fixpt_add_int(struct fixed31_32 arg1, int arg2)
268 {
269         return dc_fixpt_add(arg1, dc_fixpt_from_int(arg2));
270 }
271
272 /*
273  * @brief
274  * result = arg1 - arg2
275  */
276 static inline struct fixed31_32 dc_fixpt_sub(struct fixed31_32 arg1, struct fixed31_32 arg2)
277 {
278         struct fixed31_32 res;
279
280         ASSERT(((arg2.value >= 0) && (LLONG_MIN + arg2.value <= arg1.value)) ||
281                 ((arg2.value < 0) && (LLONG_MAX + arg2.value >= arg1.value)));
282
283         res.value = arg1.value - arg2.value;
284
285         return res;
286 }
287
288 /*
289  * @brief
290  * result = arg1 - arg2
291  */
292 static inline struct fixed31_32 dc_fixpt_sub_int(struct fixed31_32 arg1, int arg2)
293 {
294         return dc_fixpt_sub(arg1, dc_fixpt_from_int(arg2));
295 }
296
297
298 /*
299  * @brief
300  * Binary multiplicative operators
301  */
302
303 /*
304  * @brief
305  * result = arg1 * arg2
306  */
307 struct fixed31_32 dc_fixpt_mul(struct fixed31_32 arg1, struct fixed31_32 arg2);
308
309
310 /*
311  * @brief
312  * result = arg1 * arg2
313  */
314 static inline struct fixed31_32 dc_fixpt_mul_int(struct fixed31_32 arg1, int arg2)
315 {
316         return dc_fixpt_mul(arg1, dc_fixpt_from_int(arg2));
317 }
318
319 /*
320  * @brief
321  * result = square(arg) := arg * arg
322  */
323 struct fixed31_32 dc_fixpt_sqr(struct fixed31_32 arg);
324
325 /*
326  * @brief
327  * result = arg1 / arg2
328  */
329 static inline struct fixed31_32 dc_fixpt_div_int(struct fixed31_32 arg1, long long arg2)
330 {
331         return dc_fixpt_from_fraction(arg1.value, dc_fixpt_from_int(arg2).value);
332 }
333
334 /*
335  * @brief
336  * result = arg1 / arg2
337  */
338 static inline struct fixed31_32 dc_fixpt_div(struct fixed31_32 arg1, struct fixed31_32 arg2)
339 {
340         return dc_fixpt_from_fraction(arg1.value, arg2.value);
341 }
342
343 /*
344  * @brief
345  * Reciprocal function
346  */
347
348 /*
349  * @brief
350  * result = reciprocal(arg) := 1 / arg
351  *
352  * @note
353  * No special actions taken in case argument is zero.
354  */
355 struct fixed31_32 dc_fixpt_recip(struct fixed31_32 arg);
356
357 /*
358  * @brief
359  * Trigonometric functions
360  */
361
362 /*
363  * @brief
364  * result = sinc(arg) := sin(arg) / arg
365  *
366  * @note
367  * Argument specified in radians,
368  * internally it's normalized to [-2pi...2pi] range.
369  */
370 struct fixed31_32 dc_fixpt_sinc(struct fixed31_32 arg);
371
372 /*
373  * @brief
374  * result = sin(arg)
375  *
376  * @note
377  * Argument specified in radians,
378  * internally it's normalized to [-2pi...2pi] range.
379  */
380 struct fixed31_32 dc_fixpt_sin(struct fixed31_32 arg);
381
382 /*
383  * @brief
384  * result = cos(arg)
385  *
386  * @note
387  * Argument specified in radians
388  * and should be in [-2pi...2pi] range -
389  * passing arguments outside that range
390  * will cause incorrect result!
391  */
392 struct fixed31_32 dc_fixpt_cos(struct fixed31_32 arg);
393
394 /*
395  * @brief
396  * Transcendent functions
397  */
398
399 /*
400  * @brief
401  * result = exp(arg)
402  *
403  * @note
404  * Currently, function is verified for abs(arg) <= 1.
405  */
406 struct fixed31_32 dc_fixpt_exp(struct fixed31_32 arg);
407
408 /*
409  * @brief
410  * result = log(arg)
411  *
412  * @note
413  * Currently, abs(arg) should be less than 1.
414  * No normalization is done.
415  * Currently, no special actions taken
416  * in case of invalid argument(s). Take care!
417  */
418 struct fixed31_32 dc_fixpt_log(struct fixed31_32 arg);
419
420 /*
421  * @brief
422  * Power function
423  */
424
425 /*
426  * @brief
427  * result = pow(arg1, arg2)
428  *
429  * @note
430  * Currently, abs(arg1) should be less than 1. Take care!
431  */
432 static inline struct fixed31_32 dc_fixpt_pow(struct fixed31_32 arg1, struct fixed31_32 arg2)
433 {
434         return dc_fixpt_exp(
435                 dc_fixpt_mul(
436                         dc_fixpt_log(arg1),
437                         arg2));
438 }
439
440 /*
441  * @brief
442  * Rounding functions
443  */
444
445 /*
446  * @brief
447  * result = floor(arg) := greatest integer lower than or equal to arg
448  */
449 static inline int dc_fixpt_floor(struct fixed31_32 arg)
450 {
451         unsigned long long arg_value = arg.value > 0 ? arg.value : -arg.value;
452
453         if (arg.value >= 0)
454                 return (int)(arg_value >> FIXED31_32_BITS_PER_FRACTIONAL_PART);
455         else
456                 return -(int)(arg_value >> FIXED31_32_BITS_PER_FRACTIONAL_PART);
457 }
458
459 /*
460  * @brief
461  * result = round(arg) := integer nearest to arg
462  */
463 static inline int dc_fixpt_round(struct fixed31_32 arg)
464 {
465         unsigned long long arg_value = arg.value > 0 ? arg.value : -arg.value;
466
467         const long long summand = dc_fixpt_half.value;
468
469         ASSERT(LLONG_MAX - (long long)arg_value >= summand);
470
471         arg_value += summand;
472
473         if (arg.value >= 0)
474                 return (int)(arg_value >> FIXED31_32_BITS_PER_FRACTIONAL_PART);
475         else
476                 return -(int)(arg_value >> FIXED31_32_BITS_PER_FRACTIONAL_PART);
477 }
478
479 /*
480  * @brief
481  * result = ceil(arg) := lowest integer greater than or equal to arg
482  */
483 static inline int dc_fixpt_ceil(struct fixed31_32 arg)
484 {
485         unsigned long long arg_value = arg.value > 0 ? arg.value : -arg.value;
486
487         const long long summand = dc_fixpt_one.value -
488                 dc_fixpt_epsilon.value;
489
490         ASSERT(LLONG_MAX - (long long)arg_value >= summand);
491
492         arg_value += summand;
493
494         if (arg.value >= 0)
495                 return (int)(arg_value >> FIXED31_32_BITS_PER_FRACTIONAL_PART);
496         else
497                 return -(int)(arg_value >> FIXED31_32_BITS_PER_FRACTIONAL_PART);
498 }
499
500 /* the following two function are used in scaler hw programming to convert fixed
501  * point value to format 2 bits from integer part and 19 bits from fractional
502  * part. The same applies for u0d19, 0 bits from integer part and 19 bits from
503  * fractional
504  */
505
506 unsigned int dc_fixpt_u4d19(struct fixed31_32 arg);
507
508 unsigned int dc_fixpt_u3d19(struct fixed31_32 arg);
509
510 unsigned int dc_fixpt_u2d19(struct fixed31_32 arg);
511
512 unsigned int dc_fixpt_u0d19(struct fixed31_32 arg);
513
514 unsigned int dc_fixpt_clamp_u0d14(struct fixed31_32 arg);
515
516 unsigned int dc_fixpt_clamp_u0d10(struct fixed31_32 arg);
517
518 int dc_fixpt_s4d19(struct fixed31_32 arg);
519
520 static inline struct fixed31_32 dc_fixpt_truncate(struct fixed31_32 arg, unsigned int frac_bits)
521 {
522         bool negative = arg.value < 0;
523
524         if (frac_bits >= FIXED31_32_BITS_PER_FRACTIONAL_PART) {
525                 ASSERT(frac_bits == FIXED31_32_BITS_PER_FRACTIONAL_PART);
526                 return arg;
527         }
528
529         if (negative)
530                 arg.value = -arg.value;
531         arg.value &= (~0LL) << (FIXED31_32_BITS_PER_FRACTIONAL_PART - frac_bits);
532         if (negative)
533                 arg.value = -arg.value;
534         return arg;
535 }
536
537 #endif