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