root/drivers/gpu/drm/amd/display/dc/calcs/bw_fixed.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. abs_i64
  2. bw_int_to_fixed_nonconst
  3. bw_frc_to_fixed
  4. bw_floor2
  5. bw_ceil2
  6. bw_mul

   1 /*
   2  * Copyright 2015 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 #include "dm_services.h"
  26 #include "bw_fixed.h"
  27 
  28 
  29 #define MIN_I64 \
  30         (int64_t)(-(1LL << 63))
  31 
  32 #define MAX_I64 \
  33         (int64_t)((1ULL << 63) - 1)
  34 
  35 #define FRACTIONAL_PART_MASK \
  36         ((1ULL << BW_FIXED_BITS_PER_FRACTIONAL_PART) - 1)
  37 
  38 #define GET_FRACTIONAL_PART(x) \
  39         (FRACTIONAL_PART_MASK & (x))
  40 
  41 static uint64_t abs_i64(int64_t arg)
  42 {
  43         if (arg >= 0)
  44                 return (uint64_t)(arg);
  45         else
  46                 return (uint64_t)(-arg);
  47 }
  48 
  49 struct bw_fixed bw_int_to_fixed_nonconst(int64_t value)
  50 {
  51         struct bw_fixed res;
  52         ASSERT(value < BW_FIXED_MAX_I32 && value > BW_FIXED_MIN_I32);
  53         res.value = value << BW_FIXED_BITS_PER_FRACTIONAL_PART;
  54         return res;
  55 }
  56 
  57 struct bw_fixed bw_frc_to_fixed(int64_t numerator, int64_t denominator)
  58 {
  59         struct bw_fixed res;
  60         bool arg1_negative = numerator < 0;
  61         bool arg2_negative = denominator < 0;
  62         uint64_t arg1_value;
  63         uint64_t arg2_value;
  64         uint64_t remainder;
  65 
  66         /* determine integer part */
  67         uint64_t res_value;
  68 
  69         ASSERT(denominator != 0);
  70 
  71         arg1_value = abs_i64(numerator);
  72         arg2_value = abs_i64(denominator);
  73         res_value = div64_u64_rem(arg1_value, arg2_value, &remainder);
  74 
  75         ASSERT(res_value <= BW_FIXED_MAX_I32);
  76 
  77         /* determine fractional part */
  78         {
  79                 uint32_t i = BW_FIXED_BITS_PER_FRACTIONAL_PART;
  80 
  81                 do
  82                 {
  83                         remainder <<= 1;
  84 
  85                         res_value <<= 1;
  86 
  87                         if (remainder >= arg2_value)
  88                         {
  89                                 res_value |= 1;
  90                                 remainder -= arg2_value;
  91                         }
  92                 } while (--i != 0);
  93         }
  94 
  95         /* round up LSB */
  96         {
  97                 uint64_t summand = (remainder << 1) >= arg2_value;
  98 
  99                 ASSERT(res_value <= MAX_I64 - summand);
 100 
 101                 res_value += summand;
 102         }
 103 
 104         res.value = (int64_t)(res_value);
 105 
 106         if (arg1_negative ^ arg2_negative)
 107                 res.value = -res.value;
 108         return res;
 109 }
 110 
 111 struct bw_fixed bw_floor2(
 112         const struct bw_fixed arg,
 113         const struct bw_fixed significance)
 114 {
 115         struct bw_fixed result;
 116         int64_t multiplicand;
 117 
 118         multiplicand = div64_s64(arg.value, abs_i64(significance.value));
 119         result.value = abs_i64(significance.value) * multiplicand;
 120         ASSERT(abs_i64(result.value) <= abs_i64(arg.value));
 121         return result;
 122 }
 123 
 124 struct bw_fixed bw_ceil2(
 125         const struct bw_fixed arg,
 126         const struct bw_fixed significance)
 127 {
 128         struct bw_fixed result;
 129         int64_t multiplicand;
 130 
 131         multiplicand = div64_s64(arg.value, abs_i64(significance.value));
 132         result.value = abs_i64(significance.value) * multiplicand;
 133         if (abs_i64(result.value) < abs_i64(arg.value)) {
 134                 if (arg.value < 0)
 135                         result.value -= abs_i64(significance.value);
 136                 else
 137                         result.value += abs_i64(significance.value);
 138         }
 139         return result;
 140 }
 141 
 142 struct bw_fixed bw_mul(const struct bw_fixed arg1, const struct bw_fixed arg2)
 143 {
 144         struct bw_fixed res;
 145 
 146         bool arg1_negative = arg1.value < 0;
 147         bool arg2_negative = arg2.value < 0;
 148 
 149         uint64_t arg1_value = abs_i64(arg1.value);
 150         uint64_t arg2_value = abs_i64(arg2.value);
 151 
 152         uint64_t arg1_int = BW_FIXED_GET_INTEGER_PART(arg1_value);
 153         uint64_t arg2_int = BW_FIXED_GET_INTEGER_PART(arg2_value);
 154 
 155         uint64_t arg1_fra = GET_FRACTIONAL_PART(arg1_value);
 156         uint64_t arg2_fra = GET_FRACTIONAL_PART(arg2_value);
 157 
 158         uint64_t tmp;
 159 
 160         res.value = arg1_int * arg2_int;
 161 
 162         ASSERT(res.value <= BW_FIXED_MAX_I32);
 163 
 164         res.value <<= BW_FIXED_BITS_PER_FRACTIONAL_PART;
 165 
 166         tmp = arg1_int * arg2_fra;
 167 
 168         ASSERT(tmp <= (uint64_t)(MAX_I64 - res.value));
 169 
 170         res.value += tmp;
 171 
 172         tmp = arg2_int * arg1_fra;
 173 
 174         ASSERT(tmp <= (uint64_t)(MAX_I64 - res.value));
 175 
 176         res.value += tmp;
 177 
 178         tmp = arg1_fra * arg2_fra;
 179 
 180         tmp = (tmp >> BW_FIXED_BITS_PER_FRACTIONAL_PART) +
 181                 (tmp >= (uint64_t)(bw_frc_to_fixed(1, 2).value));
 182 
 183         ASSERT(tmp <= (uint64_t)(MAX_I64 - res.value));
 184 
 185         res.value += tmp;
 186 
 187         if (arg1_negative ^ arg2_negative)
 188                 res.value = -res.value;
 189         return res;
 190 }
 191 

/* [<][>][^][v][top][bottom][index][help] */