FILE
spl_fixpt31_32.h
File preview with syntax highlighting.
linux-6.19.14/drivers/gpu/drm/amd/display/dc/sspl/spl_fixpt31_32.h
1/* SPDX-License-Identifier: MIT */ 2 3/* Copyright 2024 Advanced Micro Devices, Inc. */ 4 5#ifndef __SPL_FIXED31_32_H__ 6#define __SPL_FIXED31_32_H__ 7 8#include "spl_debug.h" 9#include "spl_os_types.h" // swap 10 11#ifndef LLONG_MAX 12#define LLONG_MAX 9223372036854775807ll 13#endif 14#ifndef LLONG_MIN 15#define LLONG_MIN (-LLONG_MAX - 1ll) 16#endif 17 18#define FIXED31_32_BITS_PER_FRACTIONAL_PART 32 19#ifndef LLONG_MIN 20#define LLONG_MIN (1LL<<63) 21#endif 22#ifndef LLONG_MAX 23#define LLONG_MAX (-1LL>>1) 24#endif 25 26/* 27 * @brief 28 * Arithmetic operations on real numbers 29 * represented as fixed-point numbers. 30 * There are: 1 bit for sign, 31 * 31 bit for integer part, 32 * 32 bits for fractional part. 33 * 34 * @note 35 * Currently, overflows and underflows are asserted; 36 * no special result returned. 37 */ 38 39struct spl_fixed31_32 { 40 long long value; 41}; 42 43 44/* 45 * @brief 46 * Useful constants 47 */ 48 49static const struct spl_fixed31_32 spl_fixpt_zero = { 0 }; 50static const struct spl_fixed31_32 spl_fixpt_epsilon = { 1LL }; 51static const struct spl_fixed31_32 spl_fixpt_half = { 0x80000000LL }; 52static const struct spl_fixed31_32 spl_fixpt_one = { 0x100000000LL }; 53 54/* 55 * @brief 56 * Initialization routines 57 */ 58 59/* 60 * @brief 61 * result = numerator / denominator 62 */ 63struct spl_fixed31_32 spl_fixpt_from_fraction(long long numerator, long long denominator); 64 65/* 66 * @brief 67 * result = arg 68 */ 69static inline struct spl_fixed31_32 spl_fixpt_from_int(int arg) 70{ 71 struct spl_fixed31_32 res; 72 73 res.value = (long long) arg << FIXED31_32_BITS_PER_FRACTIONAL_PART; 74 75 return res; 76} 77 78/* 79 * @brief 80 * Unary operators 81 */ 82 83/* 84 * @brief 85 * result = -arg 86 */ 87static inline struct spl_fixed31_32 spl_fixpt_neg(struct spl_fixed31_32 arg) 88{ 89 struct spl_fixed31_32 res; 90 91 res.value = -arg.value; 92 93 return res; 94} 95 96/* 97 * @brief 98 * result = abs(arg) := (arg >= 0) ? arg : -arg 99 */ 100static inline struct spl_fixed31_32 spl_fixpt_abs(struct spl_fixed31_32 arg) 101{ 102 if (arg.value < 0) 103 return spl_fixpt_neg(arg); 104 else 105 return arg; 106} 107 108/* 109 * @brief 110 * Binary relational operators 111 */ 112 113/* 114 * @brief 115 * result = arg1 < arg2 116 */ 117static inline bool spl_fixpt_lt(struct spl_fixed31_32 arg1, struct spl_fixed31_32 arg2) 118{ 119 return arg1.value < arg2.value; 120} 121 122/* 123 * @brief 124 * result = arg1 <= arg2 125 */ 126static inline bool spl_fixpt_le(struct spl_fixed31_32 arg1, struct spl_fixed31_32 arg2) 127{ 128 return arg1.value <= arg2.value; 129} 130 131/* 132 * @brief 133 * result = arg1 == arg2 134 */ 135static inline bool spl_fixpt_eq(struct spl_fixed31_32 arg1, struct spl_fixed31_32 arg2) 136{ 137 return arg1.value == arg2.value; 138} 139 140/* 141 * @brief 142 * result = min(arg1, arg2) := (arg1 <= arg2) ? arg1 : arg2 143 */ 144static inline struct spl_fixed31_32 spl_fixpt_min(struct spl_fixed31_32 arg1, struct spl_fixed31_32 arg2) 145{ 146 if (arg1.value <= arg2.value) 147 return arg1; 148 else 149 return arg2; 150} 151 152/* 153 * @brief 154 * result = max(arg1, arg2) := (arg1 <= arg2) ? arg2 : arg1 155 */ 156static inline struct spl_fixed31_32 spl_fixpt_max(struct spl_fixed31_32 arg1, struct spl_fixed31_32 arg2) 157{ 158 if (arg1.value <= arg2.value) 159 return arg2; 160 else 161 return arg1; 162} 163 164/* 165 * @brief 166 * | min_value, when arg <= min_value 167 * result = | arg, when min_value < arg < max_value 168 * | max_value, when arg >= max_value 169 */ 170static inline struct spl_fixed31_32 spl_fixpt_clamp( 171 struct spl_fixed31_32 arg, 172 struct spl_fixed31_32 min_value, 173 struct spl_fixed31_32 max_value) 174{ 175 if (spl_fixpt_le(arg, min_value)) 176 return min_value; 177 else if (spl_fixpt_le(max_value, arg)) 178 return max_value; 179 else 180 return arg; 181} 182 183/* 184 * @brief 185 * Binary shift operators 186 */ 187 188/* 189 * @brief 190 * result = arg << shift 191 */ 192static inline struct spl_fixed31_32 spl_fixpt_shl(struct spl_fixed31_32 arg, unsigned int shift) 193{ 194 SPL_ASSERT(((arg.value >= 0) && (arg.value <= LLONG_MAX >> shift)) || 195 ((arg.value < 0) && (arg.value >= ~(LLONG_MAX >> shift)))); 196 197 arg.value = arg.value << shift; 198 199 return arg; 200} 201 202/* 203 * @brief 204 * result = arg >> shift 205 */ 206static inline struct spl_fixed31_32 spl_fixpt_shr(struct spl_fixed31_32 arg, unsigned int shift) 207{ 208 bool negative = arg.value < 0; 209 210 if (negative) 211 arg.value = -arg.value; 212 arg.value = arg.value >> shift; 213 if (negative) 214 arg.value = -arg.value; 215 return arg; 216} 217 218/* 219 * @brief 220 * Binary additive operators 221 */ 222 223/* 224 * @brief 225 * result = arg1 + arg2 226 */ 227static inline struct spl_fixed31_32 spl_fixpt_add(struct spl_fixed31_32 arg1, struct spl_fixed31_32 arg2) 228{ 229 struct spl_fixed31_32 res; 230 231 SPL_ASSERT(((arg1.value >= 0) && (LLONG_MAX - arg1.value >= arg2.value)) || 232 ((arg1.value < 0) && (LLONG_MIN - arg1.value <= arg2.value))); 233 234 res.value = arg1.value + arg2.value; 235 236 return res; 237} 238 239/* 240 * @brief 241 * result = arg1 + arg2 242 */ 243static inline struct spl_fixed31_32 spl_fixpt_add_int(struct spl_fixed31_32 arg1, int arg2) 244{ 245 return spl_fixpt_add(arg1, spl_fixpt_from_int(arg2)); 246} 247 248/* 249 * @brief 250 * result = arg1 - arg2 251 */ 252static inline struct spl_fixed31_32 spl_fixpt_sub(struct spl_fixed31_32 arg1, struct spl_fixed31_32 arg2) 253{ 254 struct spl_fixed31_32 res; 255 256 SPL_ASSERT(((arg2.value >= 0) && (LLONG_MIN + arg2.value <= arg1.value)) || 257 ((arg2.value < 0) && (LLONG_MAX + arg2.value >= arg1.value))); 258 259 res.value = arg1.value - arg2.value; 260 261 return res; 262} 263 264/* 265 * @brief 266 * result = arg1 - arg2 267 */ 268static inline struct spl_fixed31_32 spl_fixpt_sub_int(struct spl_fixed31_32 arg1, int arg2) 269{ 270 return spl_fixpt_sub(arg1, spl_fixpt_from_int(arg2)); 271} 272 273 274/* 275 * @brief 276 * Binary multiplicative operators 277 */ 278 279/* 280 * @brief 281 * result = arg1 * arg2 282 */ 283struct spl_fixed31_32 spl_fixpt_mul(struct spl_fixed31_32 arg1, struct spl_fixed31_32 arg2); 284 285 286/* 287 * @brief 288 * result = arg1 * arg2 289 */ 290static inline struct spl_fixed31_32 spl_fixpt_mul_int(struct spl_fixed31_32 arg1, int arg2) 291{ 292 return spl_fixpt_mul(arg1, spl_fixpt_from_int(arg2)); 293} 294 295/* 296 * @brief 297 * result = square(arg) := arg * arg 298 */ 299struct spl_fixed31_32 spl_fixpt_sqr(struct spl_fixed31_32 arg); 300 301/* 302 * @brief 303 * result = arg1 / arg2 304 */ 305static inline struct spl_fixed31_32 spl_fixpt_div_int(struct spl_fixed31_32 arg1, long long arg2) 306{ 307 return spl_fixpt_from_fraction(arg1.value, spl_fixpt_from_int((int)arg2).value); 308} 309 310/* 311 * @brief 312 * result = arg1 / arg2 313 */ 314static inline struct spl_fixed31_32 spl_fixpt_div(struct spl_fixed31_32 arg1, struct spl_fixed31_32 arg2) 315{ 316 return spl_fixpt_from_fraction(arg1.value, arg2.value); 317} 318 319/* 320 * @brief 321 * Reciprocal function 322 */ 323 324/* 325 * @brief 326 * result = reciprocal(arg) := 1 / arg 327 * 328 * @note 329 * No special actions taken in case argument is zero. 330 */ 331struct spl_fixed31_32 spl_fixpt_recip(struct spl_fixed31_32 arg); 332 333/* 334 * @brief 335 * Trigonometric functions 336 */ 337 338/* 339 * @brief 340 * result = sinc(arg) := sin(arg) / arg 341 * 342 * @note 343 * Argument specified in radians, 344 * internally it's normalized to [-2pi...2pi] range. 345 */ 346struct spl_fixed31_32 spl_fixpt_sinc(struct spl_fixed31_32 arg); 347 348/* 349 * @brief 350 * result = sin(arg) 351 * 352 * @note 353 * Argument specified in radians, 354 * internally it's normalized to [-2pi...2pi] range. 355 */ 356struct spl_fixed31_32 spl_fixpt_sin(struct spl_fixed31_32 arg); 357 358/* 359 * @brief 360 * result = cos(arg) 361 * 362 * @note 363 * Argument specified in radians 364 * and should be in [-2pi...2pi] range - 365 * passing arguments outside that range 366 * will cause incorrect result! 367 */ 368struct spl_fixed31_32 spl_fixpt_cos(struct spl_fixed31_32 arg); 369 370/* 371 * @brief 372 * Transcendent functions 373 */ 374 375/* 376 * @brief 377 * result = exp(arg) 378 * 379 * @note 380 * Currently, function is verified for abs(arg) <= 1. 381 */ 382struct spl_fixed31_32 spl_fixpt_exp(struct spl_fixed31_32 arg); 383 384/* 385 * @brief 386 * result = log(arg) 387 * 388 * @note 389 * Currently, abs(arg) should be less than 1. 390 * No normalization is done. 391 * Currently, no special actions taken 392 * in case of invalid argument(s). Take care! 393 */ 394struct spl_fixed31_32 spl_fixpt_log(struct spl_fixed31_32 arg); 395 396/* 397 * @brief 398 * Power function 399 */ 400 401/* 402 * @brief 403 * result = pow(arg1, arg2) 404 * 405 * @note 406 * Currently, abs(arg1) should be less than 1. Take care! 407 */ 408static inline struct spl_fixed31_32 spl_fixpt_pow(struct spl_fixed31_32 arg1, struct spl_fixed31_32 arg2) 409{ 410 if (arg1.value == 0) 411 return arg2.value == 0 ? spl_fixpt_one : spl_fixpt_zero; 412 413 return spl_fixpt_exp( 414 spl_fixpt_mul( 415 spl_fixpt_log(arg1), 416 arg2)); 417} 418 419/* 420 * @brief 421 * Rounding functions 422 */ 423 424/* 425 * @brief 426 * result = floor(arg) := greatest integer lower than or equal to arg 427 */ 428static inline int spl_fixpt_floor(struct spl_fixed31_32 arg) 429{ 430 unsigned long long arg_value = arg.value > 0 ? arg.value : -arg.value; 431 432 if (arg.value >= 0) 433 return (int)(arg_value >> FIXED31_32_BITS_PER_FRACTIONAL_PART); 434 else 435 return -(int)(arg_value >> FIXED31_32_BITS_PER_FRACTIONAL_PART); 436} 437 438/* 439 * @brief 440 * result = round(arg) := integer nearest to arg 441 */ 442static inline int spl_fixpt_round(struct spl_fixed31_32 arg) 443{ 444 unsigned long long arg_value = arg.value > 0 ? arg.value : -arg.value; 445 446 const long long summand = spl_fixpt_half.value; 447 448 SPL_ASSERT(LLONG_MAX - (long long)arg_value >= summand); 449 450 arg_value += summand; 451 452 if (arg.value >= 0) 453 return (int)(arg_value >> FIXED31_32_BITS_PER_FRACTIONAL_PART); 454 else 455 return -(int)(arg_value >> FIXED31_32_BITS_PER_FRACTIONAL_PART); 456} 457 458/* 459 * @brief 460 * result = ceil(arg) := lowest integer greater than or equal to arg 461 */ 462static inline int spl_fixpt_ceil(struct spl_fixed31_32 arg) 463{ 464 unsigned long long arg_value = arg.value > 0 ? arg.value : -arg.value; 465 466 const long long summand = spl_fixpt_one.value - 467 spl_fixpt_epsilon.value; 468 469 SPL_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/* the following two function are used in scaler hw programming to convert fixed 480 * point value to format 2 bits from integer part and 19 bits from fractional 481 * part. The same applies for u0d19, 0 bits from integer part and 19 bits from 482 * fractional 483 */ 484 485unsigned int spl_fixpt_u4d19(struct spl_fixed31_32 arg); 486 487unsigned int spl_fixpt_u3d19(struct spl_fixed31_32 arg); 488 489unsigned int spl_fixpt_u2d19(struct spl_fixed31_32 arg); 490 491unsigned int spl_fixpt_u0d19(struct spl_fixed31_32 arg); 492 493unsigned int spl_fixpt_clamp_u0d14(struct spl_fixed31_32 arg); 494 495unsigned int spl_fixpt_clamp_u0d10(struct spl_fixed31_32 arg); 496 497int spl_fixpt_s4d19(struct spl_fixed31_32 arg); 498 499static inline struct spl_fixed31_32 spl_fixpt_truncate(struct spl_fixed31_32 arg, unsigned int frac_bits) 500{ 501 bool negative = arg.value < 0; 502 503 if (frac_bits >= FIXED31_32_BITS_PER_FRACTIONAL_PART) { 504 SPL_ASSERT(frac_bits == FIXED31_32_BITS_PER_FRACTIONAL_PART); 505 return arg; 506 } 507 508 if (negative) 509 arg.value = -arg.value; 510 arg.value &= (~0ULL) << (FIXED31_32_BITS_PER_FRACTIONAL_PART - frac_bits); 511 if (negative) 512 arg.value = -arg.value; 513 return arg; 514} 515 516struct spl_fixed31_32 spl_fixpt_from_ux_dy(unsigned int value, unsigned int integer_bits, unsigned int fractional_bits); 517struct spl_fixed31_32 spl_fixpt_from_int_dy(unsigned int int_value, 518 unsigned int frac_value, 519 unsigned int integer_bits, 520 unsigned int fractional_bits); 521 522#endif
~/
Read-only file preview.