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