diff options
author | Alex Deucher <alexander.deucher@amd.com> | 2013-03-22 10:35:50 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2013-06-27 19:16:37 -0400 |
commit | 210a0b9e212370ed8c2784c2115e7ff4bb1259bd (patch) | |
tree | 35efeaaa2b97e7f4e0a9fe3475967bd859cf55d6 | |
parent | 9ed36f750534e2c6533fcbf32df89cf20cf87e91 (diff) |
drm: add some additional fixed point helpers (v3)
Required for certain driver calculations. Code
was written by Christian König and ported to the
drm by me.
v2: fix 64 bit divides
v3: fix 64 bit for real (math64.h)
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r-- | include/drm/drm_fixed.h | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/include/drm/drm_fixed.h b/include/drm/drm_fixed.h index 0ead502e17d2..f5e1168c7647 100644 --- a/include/drm/drm_fixed.h +++ b/include/drm/drm_fixed.h | |||
@@ -20,10 +20,13 @@ | |||
20 | * OTHER DEALINGS IN THE SOFTWARE. | 20 | * OTHER DEALINGS IN THE SOFTWARE. |
21 | * | 21 | * |
22 | * Authors: Dave Airlie | 22 | * Authors: Dave Airlie |
23 | * Christian König | ||
23 | */ | 24 | */ |
24 | #ifndef DRM_FIXED_H | 25 | #ifndef DRM_FIXED_H |
25 | #define DRM_FIXED_H | 26 | #define DRM_FIXED_H |
26 | 27 | ||
28 | #include <linux/math64.h> | ||
29 | |||
27 | typedef union dfixed { | 30 | typedef union dfixed { |
28 | u32 full; | 31 | u32 full; |
29 | } fixed20_12; | 32 | } fixed20_12; |
@@ -65,4 +68,95 @@ static inline u32 dfixed_div(fixed20_12 A, fixed20_12 B) | |||
65 | tmp /= 2; | 68 | tmp /= 2; |
66 | return lower_32_bits(tmp); | 69 | return lower_32_bits(tmp); |
67 | } | 70 | } |
71 | |||
72 | #define DRM_FIXED_POINT 32 | ||
73 | #define DRM_FIXED_ONE (1ULL << DRM_FIXED_POINT) | ||
74 | #define DRM_FIXED_DECIMAL_MASK (DRM_FIXED_ONE - 1) | ||
75 | #define DRM_FIXED_DIGITS_MASK (~DRM_FIXED_DECIMAL_MASK) | ||
76 | |||
77 | static inline s64 drm_int2fixp(int a) | ||
78 | { | ||
79 | return ((s64)a) << DRM_FIXED_POINT; | ||
80 | } | ||
81 | |||
82 | static inline int drm_fixp2int(int64_t a) | ||
83 | { | ||
84 | return ((s64)a) >> DRM_FIXED_POINT; | ||
85 | } | ||
86 | |||
87 | static inline s64 drm_fixp_msbset(int64_t a) | ||
88 | { | ||
89 | unsigned shift, sign = (a >> 63) & 1; | ||
90 | |||
91 | for (shift = 62; shift > 0; --shift) | ||
92 | if ((a >> shift) != sign) | ||
93 | return shift; | ||
94 | |||
95 | return 0; | ||
96 | } | ||
97 | |||
98 | static inline s64 drm_fixp_mul(s64 a, s64 b) | ||
99 | { | ||
100 | unsigned shift = drm_fixp_msbset(a) + drm_fixp_msbset(b); | ||
101 | s64 result; | ||
102 | |||
103 | if (shift > 63) { | ||
104 | shift = shift - 63; | ||
105 | a >>= shift >> 1; | ||
106 | b >>= shift >> 1; | ||
107 | } else | ||
108 | shift = 0; | ||
109 | |||
110 | result = a * b; | ||
111 | |||
112 | if (shift > DRM_FIXED_POINT) | ||
113 | return result << (shift - DRM_FIXED_POINT); | ||
114 | |||
115 | if (shift < DRM_FIXED_POINT) | ||
116 | return result >> (DRM_FIXED_POINT - shift); | ||
117 | |||
118 | return result; | ||
119 | } | ||
120 | |||
121 | static inline s64 drm_fixp_div(s64 a, s64 b) | ||
122 | { | ||
123 | unsigned shift = 63 - drm_fixp_msbset(a); | ||
124 | s64 result; | ||
125 | |||
126 | a <<= shift; | ||
127 | |||
128 | if (shift < DRM_FIXED_POINT) | ||
129 | b >>= (DRM_FIXED_POINT - shift); | ||
130 | |||
131 | result = div64_s64(a, b); | ||
132 | |||
133 | if (shift > DRM_FIXED_POINT) | ||
134 | return result >> (shift - DRM_FIXED_POINT); | ||
135 | |||
136 | return result; | ||
137 | } | ||
138 | |||
139 | static inline s64 drm_fixp_exp(s64 x) | ||
140 | { | ||
141 | s64 tolerance = div64_s64(DRM_FIXED_ONE, 1000000); | ||
142 | s64 sum = DRM_FIXED_ONE, term, y = x; | ||
143 | u64 count = 1; | ||
144 | |||
145 | if (x < 0) | ||
146 | y = -1 * x; | ||
147 | |||
148 | term = y; | ||
149 | |||
150 | while (term >= tolerance) { | ||
151 | sum = sum + term; | ||
152 | count = count + 1; | ||
153 | term = drm_fixp_mul(term, div64_s64(y, count)); | ||
154 | } | ||
155 | |||
156 | if (x < 0) | ||
157 | sum = drm_fixp_div(1, sum); | ||
158 | |||
159 | return sum; | ||
160 | } | ||
161 | |||
68 | #endif | 162 | #endif |