linux/drivers/gpu/drm/amd/display/include/fixed31_32.h
<<
>>
Prefs
   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
  57struct fixed31_32 {
  58        long long value;
  59};
  60
  61
  62/*
  63 * @brief
  64 * Useful constants
  65 */
  66
  67static const struct fixed31_32 dc_fixpt_zero = { 0 };
  68static const struct fixed31_32 dc_fixpt_epsilon = { 1LL };
  69static const struct fixed31_32 dc_fixpt_half = { 0x80000000LL };
  70static const struct fixed31_32 dc_fixpt_one = { 0x100000000LL };
  71
  72static const struct fixed31_32 dc_fixpt_pi = { 13493037705LL };
  73static const struct fixed31_32 dc_fixpt_two_pi = { 26986075409LL };
  74static const struct fixed31_32 dc_fixpt_e = { 11674931555LL };
  75static const struct fixed31_32 dc_fixpt_ln2 = { 2977044471LL };
  76static 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 */
  87struct fixed31_32 dc_fixpt_from_fraction(long long numerator, long long denominator);
  88
  89/*
  90 * @brief
  91 * result = arg
  92 */
  93static 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 */
 111static 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 */
 124static 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 */
 141static 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 */
 150static 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 */
 159static 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 */
 168static 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 */
 180static 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 */
 194static 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 */
 216static 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 */
 230static 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 */
 251static 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 */
 267static 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 */
 276static 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 */
 292static 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 */
 307struct fixed31_32 dc_fixpt_mul(struct fixed31_32 arg1, struct fixed31_32 arg2);
 308
 309
 310/*
 311 * @brief
 312 * result = arg1 * arg2
 313 */
 314static 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 */
 323struct fixed31_32 dc_fixpt_sqr(struct fixed31_32 arg);
 324
 325/*
 326 * @brief
 327 * result = arg1 / arg2
 328 */
 329static 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 */
 338static 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 */
 355struct 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 */
 370struct 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 */
 380struct 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 */
 392struct 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 */
 406struct 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 */
 418struct 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 */
 432static 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 */
 449static 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 */
 463static 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 */
 483static 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
 506unsigned int dc_fixpt_u4d19(struct fixed31_32 arg);
 507
 508unsigned int dc_fixpt_u3d19(struct fixed31_32 arg);
 509
 510unsigned int dc_fixpt_u2d19(struct fixed31_32 arg);
 511
 512unsigned int dc_fixpt_u0d19(struct fixed31_32 arg);
 513
 514unsigned int dc_fixpt_clamp_u0d14(struct fixed31_32 arg);
 515
 516unsigned int dc_fixpt_clamp_u0d10(struct fixed31_32 arg);
 517
 518int dc_fixpt_s4d19(struct fixed31_32 arg);
 519
 520static 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
 538