xref: /dragonfly/sys/dev/drm/amd/display/dc/calcs/custom_float.c (revision b843c749addef9340ee7d4e250b09fdd492602a1)
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 
build_custom_float(struct fixed31_32 value,const struct custom_float_format * format,bool * negative,uint32_t * mantissa,uint32_t * exponenta)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 
setup_custom_float(const struct custom_float_format * format,bool negative,uint32_t mantissa,uint32_t exponenta,uint32_t * result)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 
convert_to_custom_float_format(struct fixed31_32 value,const struct custom_float_format * format,uint32_t * result)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 
198