Path: blob/master/drivers/gpu/drm/amd/display/include/fixed31_32.h
26535 views
/*1* Copyright 2012-15 Advanced Micro Devices, Inc.2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice shall be included in11* all copies or substantial portions of the Software.12*13* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR14* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,15* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL16* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR17* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,18* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR19* OTHER DEALINGS IN THE SOFTWARE.20*21* Authors: AMD22*23*/2425#ifndef __DAL_FIXED31_32_H__26#define __DAL_FIXED31_32_H__2728#ifndef LLONG_MAX29#define LLONG_MAX 9223372036854775807ll30#endif31#ifndef LLONG_MIN32#define LLONG_MIN (-LLONG_MAX - 1ll)33#endif3435#define FIXED31_32_BITS_PER_FRACTIONAL_PART 3236#ifndef LLONG_MIN37#define LLONG_MIN (1LL<<63)38#endif39#ifndef LLONG_MAX40#define LLONG_MAX (-1LL>>1)41#endif4243/*44* @brief45* Arithmetic operations on real numbers46* represented as fixed-point numbers.47* There are: 1 bit for sign,48* 31 bit for integer part,49* 32 bits for fractional part.50*51* @note52* Currently, overflows and underflows are asserted;53* no special result returned.54*/5556struct fixed31_32 {57long long value;58};596061/*62* @brief63* Useful constants64*/6566static const struct fixed31_32 dc_fixpt_zero = { 0 };67static const struct fixed31_32 dc_fixpt_epsilon = { 1LL };68static const struct fixed31_32 dc_fixpt_half = { 0x80000000LL };69static const struct fixed31_32 dc_fixpt_one = { 0x100000000LL };7071/*72* @brief73* Initialization routines74*/7576/*77* @brief78* result = numerator / denominator79*/80struct fixed31_32 dc_fixpt_from_fraction(long long numerator, long long denominator);8182/*83* @brief84* result = arg85*/86static inline struct fixed31_32 dc_fixpt_from_int(int arg)87{88struct fixed31_32 res;8990res.value = (long long) arg << FIXED31_32_BITS_PER_FRACTIONAL_PART;9192return res;93}9495/*96* @brief97* Unary operators98*/99100/*101* @brief102* result = -arg103*/104static inline struct fixed31_32 dc_fixpt_neg(struct fixed31_32 arg)105{106struct fixed31_32 res;107108res.value = -arg.value;109110return res;111}112113/*114* @brief115* result = abs(arg) := (arg >= 0) ? arg : -arg116*/117static inline struct fixed31_32 dc_fixpt_abs(struct fixed31_32 arg)118{119if (arg.value < 0)120return dc_fixpt_neg(arg);121else122return arg;123}124125/*126* @brief127* Binary relational operators128*/129130/*131* @brief132* result = arg1 < arg2133*/134static inline bool dc_fixpt_lt(struct fixed31_32 arg1, struct fixed31_32 arg2)135{136return arg1.value < arg2.value;137}138139/*140* @brief141* result = arg1 <= arg2142*/143static inline bool dc_fixpt_le(struct fixed31_32 arg1, struct fixed31_32 arg2)144{145return arg1.value <= arg2.value;146}147148/*149* @brief150* result = arg1 == arg2151*/152static inline bool dc_fixpt_eq(struct fixed31_32 arg1, struct fixed31_32 arg2)153{154return arg1.value == arg2.value;155}156157/*158* @brief159* result = min(arg1, arg2) := (arg1 <= arg2) ? arg1 : arg2160*/161static inline struct fixed31_32 dc_fixpt_min(struct fixed31_32 arg1, struct fixed31_32 arg2)162{163if (arg1.value <= arg2.value)164return arg1;165else166return arg2;167}168169/*170* @brief171* result = max(arg1, arg2) := (arg1 <= arg2) ? arg2 : arg1172*/173static inline struct fixed31_32 dc_fixpt_max(struct fixed31_32 arg1, struct fixed31_32 arg2)174{175if (arg1.value <= arg2.value)176return arg2;177else178return arg1;179}180181/*182* @brief183* | min_value, when arg <= min_value184* result = | arg, when min_value < arg < max_value185* | max_value, when arg >= max_value186*/187static inline struct fixed31_32 dc_fixpt_clamp(188struct fixed31_32 arg,189struct fixed31_32 min_value,190struct fixed31_32 max_value)191{192if (dc_fixpt_le(arg, min_value))193return min_value;194else if (dc_fixpt_le(max_value, arg))195return max_value;196else197return arg;198}199200/*201* @brief202* Binary shift operators203*/204205/*206* @brief207* result = arg << shift208*/209static inline struct fixed31_32 dc_fixpt_shl(struct fixed31_32 arg, unsigned char shift)210{211ASSERT(((arg.value >= 0) && (arg.value <= LLONG_MAX >> shift)) ||212((arg.value < 0) && (arg.value >= ~(LLONG_MAX >> shift))));213214arg.value = arg.value << shift;215216return arg;217}218219/*220* @brief221* result = arg >> shift222*/223static inline struct fixed31_32 dc_fixpt_shr(struct fixed31_32 arg, unsigned char shift)224{225bool negative = arg.value < 0;226227if (negative)228arg.value = -arg.value;229arg.value = arg.value >> shift;230if (negative)231arg.value = -arg.value;232return arg;233}234235/*236* @brief237* Binary additive operators238*/239240/*241* @brief242* result = arg1 + arg2243*/244static inline struct fixed31_32 dc_fixpt_add(struct fixed31_32 arg1, struct fixed31_32 arg2)245{246struct fixed31_32 res;247248ASSERT(((arg1.value >= 0) && (LLONG_MAX - arg1.value >= arg2.value)) ||249((arg1.value < 0) && (LLONG_MIN - arg1.value <= arg2.value)));250251res.value = arg1.value + arg2.value;252253return res;254}255256/*257* @brief258* result = arg1 + arg2259*/260static inline struct fixed31_32 dc_fixpt_add_int(struct fixed31_32 arg1, int arg2)261{262return dc_fixpt_add(arg1, dc_fixpt_from_int(arg2));263}264265/*266* @brief267* result = arg1 - arg2268*/269static inline struct fixed31_32 dc_fixpt_sub(struct fixed31_32 arg1, struct fixed31_32 arg2)270{271struct fixed31_32 res;272273ASSERT(((arg2.value >= 0) && (LLONG_MIN + arg2.value <= arg1.value)) ||274((arg2.value < 0) && (LLONG_MAX + arg2.value >= arg1.value)));275276res.value = arg1.value - arg2.value;277278return res;279}280281/*282* @brief283* result = arg1 - arg2284*/285static inline struct fixed31_32 dc_fixpt_sub_int(struct fixed31_32 arg1, int arg2)286{287return dc_fixpt_sub(arg1, dc_fixpt_from_int(arg2));288}289290291/*292* @brief293* Binary multiplicative operators294*/295296/*297* @brief298* result = arg1 * arg2299*/300struct fixed31_32 dc_fixpt_mul(struct fixed31_32 arg1, struct fixed31_32 arg2);301302303/*304* @brief305* result = arg1 * arg2306*/307static inline struct fixed31_32 dc_fixpt_mul_int(struct fixed31_32 arg1, int arg2)308{309return dc_fixpt_mul(arg1, dc_fixpt_from_int(arg2));310}311312/*313* @brief314* result = square(arg) := arg * arg315*/316struct fixed31_32 dc_fixpt_sqr(struct fixed31_32 arg);317318/*319* @brief320* result = arg1 / arg2321*/322static inline struct fixed31_32 dc_fixpt_div_int(struct fixed31_32 arg1, long long arg2)323{324return dc_fixpt_from_fraction(arg1.value, dc_fixpt_from_int((int)arg2).value);325}326327/*328* @brief329* result = arg1 / arg2330*/331static inline struct fixed31_32 dc_fixpt_div(struct fixed31_32 arg1, struct fixed31_32 arg2)332{333return dc_fixpt_from_fraction(arg1.value, arg2.value);334}335336/*337* @brief338* Reciprocal function339*/340341/*342* @brief343* result = reciprocal(arg) := 1 / arg344*345* @note346* No special actions taken in case argument is zero.347*/348struct fixed31_32 dc_fixpt_recip(struct fixed31_32 arg);349350/*351* @brief352* Trigonometric functions353*/354355/*356* @brief357* result = sinc(arg) := sin(arg) / arg358*359* @note360* Argument specified in radians,361* internally it's normalized to [-2pi...2pi] range.362*/363struct fixed31_32 dc_fixpt_sinc(struct fixed31_32 arg);364365/*366* @brief367* result = sin(arg)368*369* @note370* Argument specified in radians,371* internally it's normalized to [-2pi...2pi] range.372*/373struct fixed31_32 dc_fixpt_sin(struct fixed31_32 arg);374375/*376* @brief377* result = cos(arg)378*379* @note380* Argument specified in radians381* and should be in [-2pi...2pi] range -382* passing arguments outside that range383* will cause incorrect result!384*/385struct fixed31_32 dc_fixpt_cos(struct fixed31_32 arg);386387/*388* @brief389* Transcendent functions390*/391392/*393* @brief394* result = exp(arg)395*396* @note397* Currently, function is verified for abs(arg) <= 1.398*/399struct fixed31_32 dc_fixpt_exp(struct fixed31_32 arg);400401/*402* @brief403* result = log(arg)404*405* @note406* Currently, abs(arg) should be less than 1.407* No normalization is done.408* Currently, no special actions taken409* in case of invalid argument(s). Take care!410*/411struct fixed31_32 dc_fixpt_log(struct fixed31_32 arg);412413/*414* @brief415* Power function416*/417418/*419* @brief420* result = pow(arg1, arg2)421*422* @note423* Currently, abs(arg1) should be less than 1. Take care!424*/425static inline struct fixed31_32 dc_fixpt_pow(struct fixed31_32 arg1, struct fixed31_32 arg2)426{427if (arg1.value == 0)428return arg2.value == 0 ? dc_fixpt_one : dc_fixpt_zero;429430return dc_fixpt_exp(431dc_fixpt_mul(432dc_fixpt_log(arg1),433arg2));434}435436/*437* @brief438* Rounding functions439*/440441/*442* @brief443* result = floor(arg) := greatest integer lower than or equal to arg444*/445static inline int dc_fixpt_floor(struct fixed31_32 arg)446{447unsigned long long arg_value = arg.value > 0 ? arg.value : -arg.value;448449if (arg.value >= 0)450return (int)(arg_value >> FIXED31_32_BITS_PER_FRACTIONAL_PART);451else452return -(int)(arg_value >> FIXED31_32_BITS_PER_FRACTIONAL_PART);453}454455/*456* @brief457* result = round(arg) := integer nearest to arg458*/459static inline int dc_fixpt_round(struct fixed31_32 arg)460{461unsigned long long arg_value = arg.value > 0 ? arg.value : -arg.value;462463const long long summand = dc_fixpt_half.value;464465ASSERT(LLONG_MAX - (long long)arg_value >= summand);466467arg_value += summand;468469if (arg.value >= 0)470return (int)(arg_value >> FIXED31_32_BITS_PER_FRACTIONAL_PART);471else472return -(int)(arg_value >> FIXED31_32_BITS_PER_FRACTIONAL_PART);473}474475/*476* @brief477* result = ceil(arg) := lowest integer greater than or equal to arg478*/479static inline int dc_fixpt_ceil(struct fixed31_32 arg)480{481unsigned long long arg_value = arg.value > 0 ? arg.value : -arg.value;482483const long long summand = dc_fixpt_one.value -484dc_fixpt_epsilon.value;485486ASSERT(LLONG_MAX - (long long)arg_value >= summand);487488arg_value += summand;489490if (arg.value >= 0)491return (int)(arg_value >> FIXED31_32_BITS_PER_FRACTIONAL_PART);492else493return -(int)(arg_value >> FIXED31_32_BITS_PER_FRACTIONAL_PART);494}495496/* the following two function are used in scaler hw programming to convert fixed497* point value to format 2 bits from integer part and 19 bits from fractional498* part. The same applies for u0d19, 0 bits from integer part and 19 bits from499* fractional500*/501502unsigned int dc_fixpt_u4d19(struct fixed31_32 arg);503504unsigned int dc_fixpt_u3d19(struct fixed31_32 arg);505506unsigned int dc_fixpt_u2d19(struct fixed31_32 arg);507508unsigned int dc_fixpt_u0d19(struct fixed31_32 arg);509510unsigned int dc_fixpt_clamp_u0d14(struct fixed31_32 arg);511512unsigned int dc_fixpt_clamp_u0d10(struct fixed31_32 arg);513514int dc_fixpt_s4d19(struct fixed31_32 arg);515516static inline struct fixed31_32 dc_fixpt_truncate(struct fixed31_32 arg, unsigned int frac_bits)517{518bool negative = arg.value < 0;519520if (frac_bits >= FIXED31_32_BITS_PER_FRACTIONAL_PART) {521ASSERT(frac_bits == FIXED31_32_BITS_PER_FRACTIONAL_PART);522return arg;523}524525if (negative)526arg.value = -arg.value;527arg.value &= (~0ULL) << (FIXED31_32_BITS_PER_FRACTIONAL_PART - frac_bits);528if (negative)529arg.value = -arg.value;530return arg;531}532533struct fixed31_32 dc_fixpt_from_ux_dy(unsigned int value, unsigned int integer_bits, unsigned int fractional_bits);534struct fixed31_32 dc_fixpt_from_int_dy(unsigned int int_value,535unsigned int frac_value,536unsigned int integer_bits,537unsigned int fractional_bits);538539#endif540541542