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

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

DEFINITIONS

This source file includes following definitions.
  1. build_custom_float
  2. setup_custom_float
  3. convert_to_custom_float_format

   1 /*
   2  * Copyright 2017 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 "custom_float.h"
  27 
  28 
  29 static bool build_custom_float(
  30         struct fixed31_32 value,
  31         const struct custom_float_format *format,
  32         bool *negative,
  33         uint32_t *mantissa,
  34         uint32_t *exponenta)
  35 {
  36         uint32_t exp_offset = (1 << (format->exponenta_bits - 1)) - 1;
  37 
  38         const struct fixed31_32 mantissa_constant_plus_max_fraction =
  39                 dc_fixpt_from_fraction(
  40                         (1LL << (format->mantissa_bits + 1)) - 1,
  41                         1LL << format->mantissa_bits);
  42 
  43         struct fixed31_32 mantiss;
  44 
  45         if (dc_fixpt_eq(
  46                 value,
  47                 dc_fixpt_zero)) {
  48                 *negative = false;
  49                 *mantissa = 0;
  50                 *exponenta = 0;
  51                 return true;
  52         }
  53 
  54         if (dc_fixpt_lt(
  55                 value,
  56                 dc_fixpt_zero)) {
  57                 *negative = format->sign;
  58                 value = dc_fixpt_neg(value);
  59         } else {
  60                 *negative = false;
  61         }
  62 
  63         if (dc_fixpt_lt(
  64                 value,
  65                 dc_fixpt_one)) {
  66                 uint32_t i = 1;
  67 
  68                 do {
  69                         value = dc_fixpt_shl(value, 1);
  70                         ++i;
  71                 } while (dc_fixpt_lt(
  72                         value,
  73                         dc_fixpt_one));
  74 
  75                 --i;
  76 
  77                 if (exp_offset <= i) {
  78                         *mantissa = 0;
  79                         *exponenta = 0;
  80                         return true;
  81                 }
  82 
  83                 *exponenta = exp_offset - i;
  84         } else if (dc_fixpt_le(
  85                 mantissa_constant_plus_max_fraction,
  86                 value)) {
  87                 uint32_t i = 1;
  88 
  89                 do {
  90                         value = dc_fixpt_shr(value, 1);
  91                         ++i;
  92                 } while (dc_fixpt_lt(
  93                         mantissa_constant_plus_max_fraction,
  94                         value));
  95 
  96                 *exponenta = exp_offset + i - 1;
  97         } else {
  98                 *exponenta = exp_offset;
  99         }
 100 
 101         mantiss = dc_fixpt_sub(
 102                 value,
 103                 dc_fixpt_one);
 104 
 105         if (dc_fixpt_lt(
 106                         mantiss,
 107                         dc_fixpt_zero) ||
 108                 dc_fixpt_lt(
 109                         dc_fixpt_one,
 110                         mantiss))
 111                 mantiss = dc_fixpt_zero;
 112         else
 113                 mantiss = dc_fixpt_shl(
 114                         mantiss,
 115                         format->mantissa_bits);
 116 
 117         *mantissa = dc_fixpt_floor(mantiss);
 118 
 119         return true;
 120 }
 121 
 122 static bool setup_custom_float(
 123         const struct custom_float_format *format,
 124         bool negative,
 125         uint32_t mantissa,
 126         uint32_t exponenta,
 127         uint32_t *result)
 128 {
 129         uint32_t i = 0;
 130         uint32_t j = 0;
 131 
 132         uint32_t value = 0;
 133 
 134         /* verification code:
 135          * once calculation is ok we can remove it
 136          */
 137 
 138         const uint32_t mantissa_mask =
 139                 (1 << (format->mantissa_bits + 1)) - 1;
 140 
 141         const uint32_t exponenta_mask =
 142                 (1 << (format->exponenta_bits + 1)) - 1;
 143 
 144         if (mantissa & ~mantissa_mask) {
 145                 BREAK_TO_DEBUGGER();
 146                 mantissa = mantissa_mask;
 147         }
 148 
 149         if (exponenta & ~exponenta_mask) {
 150                 BREAK_TO_DEBUGGER();
 151                 exponenta = exponenta_mask;
 152         }
 153 
 154         /* end of verification code */
 155 
 156         while (i < format->mantissa_bits) {
 157                 uint32_t mask = 1 << i;
 158 
 159                 if (mantissa & mask)
 160                         value |= mask;
 161 
 162                 ++i;
 163         }
 164 
 165         while (j < format->exponenta_bits) {
 166                 uint32_t mask = 1 << j;
 167 
 168                 if (exponenta & mask)
 169                         value |= mask << i;
 170 
 171                 ++j;
 172         }
 173 
 174         if (negative && format->sign)
 175                 value |= 1 << (i + j);
 176 
 177         *result = value;
 178 
 179         return true;
 180 }
 181 
 182 bool convert_to_custom_float_format(
 183         struct fixed31_32 value,
 184         const struct custom_float_format *format,
 185         uint32_t *result)
 186 {
 187         uint32_t mantissa;
 188         uint32_t exponenta;
 189         bool negative;
 190 
 191         return build_custom_float(
 192                 value, format, &negative, &mantissa, &exponenta) &&
 193         setup_custom_float(
 194                 format, negative, mantissa, exponenta, result);
 195 }
 196 
 197 

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