]> Git Repo - linux.git/blob - drivers/gpu/drm/amd/display/dc/spl/spl_custom_float.c
Linux 6.14-rc3
[linux.git] / drivers / gpu / drm / amd / display / dc / spl / spl_custom_float.c
1 // SPDX-License-Identifier: MIT
2 //
3 // Copyright 2024 Advanced Micro Devices, Inc.
4
5 #include "spl_debug.h"
6 #include "spl_custom_float.h"
7
8 static bool spl_build_custom_float(struct spl_fixed31_32 value,
9                                const struct spl_custom_float_format *format,
10                                bool *negative,
11                                uint32_t *mantissa,
12                                uint32_t *exponenta)
13 {
14         uint32_t exp_offset = (1 << (format->exponenta_bits - 1)) - 1;
15
16         const struct spl_fixed31_32 mantissa_constant_plus_max_fraction =
17                 spl_fixpt_from_fraction((1LL << (format->mantissa_bits + 1)) - 1,
18                                        1LL << format->mantissa_bits);
19
20         struct spl_fixed31_32 mantiss;
21
22         if (spl_fixpt_eq(value, spl_fixpt_zero)) {
23                 *negative = false;
24                 *mantissa = 0;
25                 *exponenta = 0;
26                 return true;
27         }
28
29         if (spl_fixpt_lt(value, spl_fixpt_zero)) {
30                 *negative = format->sign;
31                 value = spl_fixpt_neg(value);
32         } else {
33                 *negative = false;
34         }
35
36         if (spl_fixpt_lt(value, spl_fixpt_one)) {
37                 uint32_t i = 1;
38
39                 do {
40                         value = spl_fixpt_shl(value, 1);
41                         ++i;
42                 } while (spl_fixpt_lt(value, spl_fixpt_one));
43
44                 --i;
45
46                 if (exp_offset <= i) {
47                         *mantissa = 0;
48                         *exponenta = 0;
49                         return true;
50                 }
51
52                 *exponenta = exp_offset - i;
53         } else if (spl_fixpt_le(mantissa_constant_plus_max_fraction, value)) {
54                 uint32_t i = 1;
55
56                 do {
57                         value = spl_fixpt_shr(value, 1);
58                         ++i;
59                 } while (spl_fixpt_lt(mantissa_constant_plus_max_fraction, value));
60
61                 *exponenta = exp_offset + i - 1;
62         } else {
63                 *exponenta = exp_offset;
64         }
65
66         mantiss = spl_fixpt_sub(value, spl_fixpt_one);
67
68         if (spl_fixpt_lt(mantiss, spl_fixpt_zero) ||
69             spl_fixpt_lt(spl_fixpt_one, mantiss))
70                 mantiss = spl_fixpt_zero;
71         else
72                 mantiss = spl_fixpt_shl(mantiss, format->mantissa_bits);
73
74         *mantissa = spl_fixpt_floor(mantiss);
75
76         return true;
77 }
78
79 static bool spl_setup_custom_float(const struct spl_custom_float_format *format,
80                                bool negative,
81                                uint32_t mantissa,
82                                uint32_t exponenta,
83                                uint32_t *result)
84 {
85         uint32_t i = 0;
86         uint32_t j = 0;
87         uint32_t value = 0;
88
89         /* verification code:
90          * once calculation is ok we can remove it
91          */
92
93         const uint32_t mantissa_mask =
94                 (1 << (format->mantissa_bits + 1)) - 1;
95
96         const uint32_t exponenta_mask =
97                 (1 << (format->exponenta_bits + 1)) - 1;
98
99         if (mantissa & ~mantissa_mask) {
100                 SPL_BREAK_TO_DEBUGGER();
101                 mantissa = mantissa_mask;
102         }
103
104         if (exponenta & ~exponenta_mask) {
105                 SPL_BREAK_TO_DEBUGGER();
106                 exponenta = exponenta_mask;
107         }
108
109         /* end of verification code */
110
111         while (i < format->mantissa_bits) {
112                 uint32_t mask = 1 << i;
113
114                 if (mantissa & mask)
115                         value |= mask;
116
117                 ++i;
118         }
119
120         while (j < format->exponenta_bits) {
121                 uint32_t mask = 1 << j;
122
123                 if (exponenta & mask)
124                         value |= mask << i;
125
126                 ++j;
127         }
128
129         if (negative && format->sign)
130                 value |= 1 << (i + j);
131
132         *result = value;
133
134         return true;
135 }
136
137 bool spl_convert_to_custom_float_format(struct spl_fixed31_32 value,
138                                     const struct spl_custom_float_format *format,
139                                     uint32_t *result)
140 {
141         uint32_t mantissa;
142         uint32_t exponenta;
143         bool negative;
144
145         return spl_build_custom_float(value, format, &negative, &mantissa, &exponenta) &&
146                                   spl_setup_custom_float(format,
147                                                      negative,
148                                                      mantissa,
149                                                      exponenta,
150                                                      result);
151 }
This page took 0.041077 seconds and 4 git commands to generate.