1 | /* SPDX-License-Identifier: MIT */ |
2 | /* |
3 | * Copyright © 2018 Intel Corporation |
4 | */ |
5 | |
6 | #ifndef _I915_FIXED_H_ |
7 | #define _I915_FIXED_H_ |
8 | |
9 | #include <linux/bug.h> |
10 | #include <linux/kernel.h> |
11 | #include <linux/math64.h> |
12 | #include <linux/types.h> |
13 | |
14 | typedef struct { |
15 | u32 val; |
16 | } uint_fixed_16_16_t; |
17 | |
18 | #define FP_16_16_MAX ((uint_fixed_16_16_t){ .val = UINT_MAX }) |
19 | |
20 | static inline bool is_fixed16_zero(uint_fixed_16_16_t val) |
21 | { |
22 | return val.val == 0; |
23 | } |
24 | |
25 | static inline uint_fixed_16_16_t u32_to_fixed16(u32 val) |
26 | { |
27 | uint_fixed_16_16_t fp = { .val = val << 16 }; |
28 | |
29 | WARN_ON(val > U16_MAX); |
30 | |
31 | return fp; |
32 | } |
33 | |
34 | static inline u32 fixed16_to_u32_round_up(uint_fixed_16_16_t fp) |
35 | { |
36 | return DIV_ROUND_UP(fp.val, 1 << 16); |
37 | } |
38 | |
39 | static inline u32 fixed16_to_u32(uint_fixed_16_16_t fp) |
40 | { |
41 | return fp.val >> 16; |
42 | } |
43 | |
44 | static inline uint_fixed_16_16_t min_fixed16(uint_fixed_16_16_t min1, |
45 | uint_fixed_16_16_t min2) |
46 | { |
47 | uint_fixed_16_16_t min = { .val = min(min1.val, min2.val) }; |
48 | |
49 | return min; |
50 | } |
51 | |
52 | static inline uint_fixed_16_16_t max_fixed16(uint_fixed_16_16_t max1, |
53 | uint_fixed_16_16_t max2) |
54 | { |
55 | uint_fixed_16_16_t max = { .val = max(max1.val, max2.val) }; |
56 | |
57 | return max; |
58 | } |
59 | |
60 | static inline uint_fixed_16_16_t clamp_u64_to_fixed16(u64 val) |
61 | { |
62 | uint_fixed_16_16_t fp = { .val = (u32)val }; |
63 | |
64 | WARN_ON(val > U32_MAX); |
65 | |
66 | return fp; |
67 | } |
68 | |
69 | static inline u32 div_round_up_fixed16(uint_fixed_16_16_t val, |
70 | uint_fixed_16_16_t d) |
71 | { |
72 | return DIV_ROUND_UP(val.val, d.val); |
73 | } |
74 | |
75 | static inline u32 mul_round_up_u32_fixed16(u32 val, uint_fixed_16_16_t mul) |
76 | { |
77 | u64 tmp; |
78 | |
79 | tmp = mul_u32_u32(a: val, b: mul.val); |
80 | tmp = DIV_ROUND_UP_ULL(tmp, 1 << 16); |
81 | WARN_ON(tmp > U32_MAX); |
82 | |
83 | return (u32)tmp; |
84 | } |
85 | |
86 | static inline uint_fixed_16_16_t mul_fixed16(uint_fixed_16_16_t val, |
87 | uint_fixed_16_16_t mul) |
88 | { |
89 | u64 tmp; |
90 | |
91 | tmp = mul_u32_u32(a: val.val, b: mul.val); |
92 | tmp = tmp >> 16; |
93 | |
94 | return clamp_u64_to_fixed16(val: tmp); |
95 | } |
96 | |
97 | static inline uint_fixed_16_16_t div_fixed16(u32 val, u32 d) |
98 | { |
99 | u64 tmp; |
100 | |
101 | tmp = (u64)val << 16; |
102 | tmp = DIV_ROUND_UP_ULL(tmp, d); |
103 | |
104 | return clamp_u64_to_fixed16(val: tmp); |
105 | } |
106 | |
107 | static inline u32 div_round_up_u32_fixed16(u32 val, uint_fixed_16_16_t d) |
108 | { |
109 | u64 tmp; |
110 | |
111 | tmp = (u64)val << 16; |
112 | tmp = DIV_ROUND_UP_ULL(tmp, d.val); |
113 | WARN_ON(tmp > U32_MAX); |
114 | |
115 | return (u32)tmp; |
116 | } |
117 | |
118 | static inline uint_fixed_16_16_t mul_u32_fixed16(u32 val, uint_fixed_16_16_t mul) |
119 | { |
120 | u64 tmp; |
121 | |
122 | tmp = mul_u32_u32(a: val, b: mul.val); |
123 | |
124 | return clamp_u64_to_fixed16(val: tmp); |
125 | } |
126 | |
127 | static inline uint_fixed_16_16_t add_fixed16(uint_fixed_16_16_t add1, |
128 | uint_fixed_16_16_t add2) |
129 | { |
130 | u64 tmp; |
131 | |
132 | tmp = (u64)add1.val + add2.val; |
133 | |
134 | return clamp_u64_to_fixed16(val: tmp); |
135 | } |
136 | |
137 | static inline uint_fixed_16_16_t add_fixed16_u32(uint_fixed_16_16_t add1, |
138 | u32 add2) |
139 | { |
140 | uint_fixed_16_16_t tmp_add2 = u32_to_fixed16(val: add2); |
141 | u64 tmp; |
142 | |
143 | tmp = (u64)add1.val + tmp_add2.val; |
144 | |
145 | return clamp_u64_to_fixed16(val: tmp); |
146 | } |
147 | |
148 | #endif /* _I915_FIXED_H_ */ |
149 | |