Rev 5271 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 5271 | Rev 5354 | ||
---|---|---|---|
1 | #include |
1 | #include |
2 | #include |
2 | #include |
3 | #include "radeon.h" |
3 | #include "radeon.h" |
4 | #include "radeon_object.h" |
4 | #include "radeon_object.h" |
5 | #include "bitmap.h" |
5 | #include "bitmap.h" |
6 | #include "display.h" |
6 | #include |
7 | 7 | ||
8 | #include "r100d.h" |
8 | #include "r100d.h" |
9 | 9 | ||
10 | 10 | ||
11 | display_t *os_display; |
11 | display_t *os_display; |
12 | 12 | ||
13 | static cursor_t* __stdcall select_cursor(cursor_t *cursor); |
13 | static cursor_t* __stdcall select_cursor(cursor_t *cursor); |
14 | static void __stdcall move_cursor(cursor_t *cursor, int x, int y); |
14 | static void __stdcall move_cursor(cursor_t *cursor, int x, int y); |
15 | 15 | ||
16 | extern void __attribute__((regparm(1))) destroy_cursor(cursor_t *cursor); |
16 | extern void __attribute__((regparm(1))) destroy_cursor(cursor_t *cursor); |
17 | 17 | ||
18 | void disable_mouse(void) |
18 | void disable_mouse(void) |
19 | {}; |
19 | {}; |
20 | 20 | ||
21 | int init_cursor(cursor_t *cursor) |
21 | int init_cursor(cursor_t *cursor) |
22 | { |
22 | { |
23 | struct radeon_device *rdev; |
23 | struct radeon_device *rdev; |
24 | 24 | ||
25 | uint32_t *bits; |
25 | uint32_t *bits; |
26 | uint32_t *src; |
26 | uint32_t *src; |
27 | 27 | ||
28 | int i,j; |
28 | int i,j; |
29 | int r; |
29 | int r; |
30 | 30 | ||
31 | rdev = (struct radeon_device *)os_display->ddev->dev_private; |
31 | rdev = (struct radeon_device *)os_display->ddev->dev_private; |
32 | 32 | ||
33 | r = radeon_bo_create(rdev, CURSOR_WIDTH*CURSOR_HEIGHT*4, |
33 | r = radeon_bo_create(rdev, CURSOR_WIDTH*CURSOR_HEIGHT*4, |
34 | 4096, false, RADEON_GEM_DOMAIN_VRAM, 0, NULL, NULL, &cursor->robj); |
34 | 4096, false, RADEON_GEM_DOMAIN_VRAM, 0, NULL, NULL, (struct radeon_bo**)&cursor->cobj); |
35 | 35 | ||
36 | if (unlikely(r != 0)) |
36 | if (unlikely(r != 0)) |
37 | return r; |
37 | return r; |
38 | 38 | ||
39 | r = radeon_bo_reserve(cursor->robj, false); |
39 | r = radeon_bo_reserve(cursor->cobj, false); |
40 | if (unlikely(r != 0)) |
40 | if (unlikely(r != 0)) |
41 | return r; |
41 | return r; |
42 | 42 | ||
43 | r = radeon_bo_pin(cursor->robj, RADEON_GEM_DOMAIN_VRAM, NULL); |
43 | r = radeon_bo_pin(cursor->cobj, RADEON_GEM_DOMAIN_VRAM, NULL); |
44 | if (unlikely(r != 0)) |
44 | if (unlikely(r != 0)) |
45 | return r; |
45 | return r; |
46 | 46 | ||
47 | r = radeon_bo_kmap(cursor->robj, (void**)&bits); |
47 | r = radeon_bo_kmap(cursor->cobj, (void**)&bits); |
48 | if (r) { |
48 | if (r) { |
49 | DRM_ERROR("radeon: failed to map cursor (%d).\n", r); |
49 | DRM_ERROR("radeon: failed to map cursor (%d).\n", r); |
50 | return r; |
50 | return r; |
51 | }; |
51 | }; |
52 | 52 | ||
53 | src = cursor->data; |
53 | src = cursor->data; |
54 | 54 | ||
55 | for(i = 0; i < 32; i++) |
55 | for(i = 0; i < 32; i++) |
56 | { |
56 | { |
57 | for(j = 0; j < 32; j++) |
57 | for(j = 0; j < 32; j++) |
58 | *bits++ = *src++; |
58 | *bits++ = *src++; |
59 | for(j = 32; j < CURSOR_WIDTH; j++) |
59 | for(j = 32; j < CURSOR_WIDTH; j++) |
60 | *bits++ = 0; |
60 | *bits++ = 0; |
61 | } |
61 | } |
62 | for(i = 0; i < CURSOR_WIDTH*(CURSOR_HEIGHT-32); i++) |
62 | for(i = 0; i < CURSOR_WIDTH*(CURSOR_HEIGHT-32); i++) |
63 | *bits++ = 0; |
63 | *bits++ = 0; |
64 | 64 | ||
65 | radeon_bo_kunmap(cursor->robj); |
65 | radeon_bo_kunmap(cursor->cobj); |
66 | 66 | ||
67 | // cursor->header.destroy = destroy_cursor; |
67 | // cursor->header.destroy = destroy_cursor; |
68 | 68 | ||
69 | return 0; |
69 | return 0; |
70 | }; |
70 | }; |
71 | 71 | ||
72 | void __attribute__((regparm(1))) destroy_cursor(cursor_t *cursor) |
72 | void __attribute__((regparm(1))) destroy_cursor(cursor_t *cursor) |
73 | { |
73 | { |
74 | list_del(&cursor->list); |
74 | list_del(&cursor->list); |
75 | radeon_bo_unpin(cursor->robj); |
75 | radeon_bo_unpin(cursor->cobj); |
76 | KernelFree(cursor->data); |
76 | KernelFree(cursor->data); |
77 | __DestroyObject(cursor); |
77 | __DestroyObject(cursor); |
78 | }; |
78 | }; |
79 | 79 | ||
80 | static void radeon_show_cursor() |
80 | static void radeon_show_cursor() |
81 | { |
81 | { |
82 | struct radeon_device *rdev = (struct radeon_device *)os_display->ddev->dev_private; |
82 | struct radeon_device *rdev = (struct radeon_device *)os_display->ddev->dev_private; |
83 | 83 | ||
84 | 84 | ||
85 | if (ASIC_IS_DCE4(rdev)) { |
85 | if (ASIC_IS_DCE4(rdev)) { |
86 | WREG32(RADEON_MM_INDEX, EVERGREEN_CUR_CONTROL); |
86 | WREG32(RADEON_MM_INDEX, EVERGREEN_CUR_CONTROL); |
87 | WREG32(RADEON_MM_DATA, EVERGREEN_CURSOR_EN | |
87 | WREG32(RADEON_MM_DATA, EVERGREEN_CURSOR_EN | |
88 | EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT)); |
88 | EVERGREEN_CURSOR_MODE(EVERGREEN_CURSOR_24_8_PRE_MULT)); |
89 | } else if (ASIC_IS_AVIVO(rdev)) { |
89 | } else if (ASIC_IS_AVIVO(rdev)) { |
90 | WREG32(RADEON_MM_INDEX, AVIVO_D1CUR_CONTROL); |
90 | WREG32(RADEON_MM_INDEX, AVIVO_D1CUR_CONTROL); |
91 | WREG32(RADEON_MM_DATA, AVIVO_D1CURSOR_EN | |
91 | WREG32(RADEON_MM_DATA, AVIVO_D1CURSOR_EN | |
92 | (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT)); |
92 | (AVIVO_D1CURSOR_MODE_24BPP << AVIVO_D1CURSOR_MODE_SHIFT)); |
93 | } else { |
93 | } else { |
94 | WREG32(RADEON_MM_INDEX, RADEON_CRTC_GEN_CNTL); |
94 | WREG32(RADEON_MM_INDEX, RADEON_CRTC_GEN_CNTL); |
95 | WREG32_P(RADEON_MM_DATA, (RADEON_CRTC_CUR_EN | |
95 | WREG32_P(RADEON_MM_DATA, (RADEON_CRTC_CUR_EN | |
96 | (RADEON_CRTC_CUR_MODE_24BPP << RADEON_CRTC_CUR_MODE_SHIFT)), |
96 | (RADEON_CRTC_CUR_MODE_24BPP << RADEON_CRTC_CUR_MODE_SHIFT)), |
97 | ~(RADEON_CRTC_CUR_EN | RADEON_CRTC_CUR_MODE_MASK)); |
97 | ~(RADEON_CRTC_CUR_EN | RADEON_CRTC_CUR_MODE_MASK)); |
98 | } |
98 | } |
99 | } |
99 | } |
100 | 100 | ||
101 | cursor_t* __stdcall select_cursor(cursor_t *cursor) |
101 | cursor_t* __stdcall select_cursor(cursor_t *cursor) |
102 | { |
102 | { |
103 | struct radeon_device *rdev; |
103 | struct radeon_device *rdev; |
104 | cursor_t *old; |
104 | cursor_t *old; |
105 | uint32_t gpu_addr; |
105 | uint32_t gpu_addr; |
106 | 106 | ||
107 | rdev = (struct radeon_device *)os_display->ddev->dev_private; |
107 | rdev = (struct radeon_device *)os_display->ddev->dev_private; |
108 | 108 | ||
109 | old = os_display->cursor; |
109 | old = os_display->cursor; |
110 | 110 | ||
111 | os_display->cursor = cursor; |
111 | os_display->cursor = cursor; |
112 | gpu_addr = radeon_bo_gpu_offset(cursor->robj); |
112 | gpu_addr = radeon_bo_gpu_offset(cursor->cobj); |
113 | 113 | ||
114 | if (ASIC_IS_DCE4(rdev)) |
114 | if (ASIC_IS_DCE4(rdev)) |
115 | { |
115 | { |
116 | WREG32(EVERGREEN_CUR_SURFACE_ADDRESS_HIGH, 0); |
116 | WREG32(EVERGREEN_CUR_SURFACE_ADDRESS_HIGH, 0); |
117 | WREG32(EVERGREEN_CUR_SURFACE_ADDRESS, gpu_addr); |
117 | WREG32(EVERGREEN_CUR_SURFACE_ADDRESS, gpu_addr); |
118 | } |
118 | } |
119 | else if (ASIC_IS_AVIVO(rdev)) |
119 | else if (ASIC_IS_AVIVO(rdev)) |
120 | { |
120 | { |
121 | if (rdev->family >= CHIP_RV770) |
121 | if (rdev->family >= CHIP_RV770) |
122 | WREG32(R700_D1CUR_SURFACE_ADDRESS_HIGH, 0); |
122 | WREG32(R700_D1CUR_SURFACE_ADDRESS_HIGH, 0); |
123 | WREG32(AVIVO_D1CUR_SURFACE_ADDRESS, gpu_addr); |
123 | WREG32(AVIVO_D1CUR_SURFACE_ADDRESS, gpu_addr); |
124 | } |
124 | } |
125 | else { |
125 | else { |
126 | WREG32(RADEON_CUR_OFFSET, gpu_addr - rdev->mc.vram_start); |
126 | WREG32(RADEON_CUR_OFFSET, gpu_addr - rdev->mc.vram_start); |
127 | } |
127 | } |
128 | 128 | ||
129 | return old; |
129 | return old; |
130 | }; |
130 | }; |
131 | 131 | ||
132 | static void radeon_lock_cursor(bool lock) |
132 | static void radeon_lock_cursor(bool lock) |
133 | { |
133 | { |
134 | struct radeon_device *rdev; |
134 | struct radeon_device *rdev; |
135 | 135 | ||
136 | rdev = (struct radeon_device *)os_display->ddev->dev_private; |
136 | rdev = (struct radeon_device *)os_display->ddev->dev_private; |
137 | 137 | ||
138 | uint32_t cur_lock; |
138 | uint32_t cur_lock; |
139 | 139 | ||
140 | if (ASIC_IS_DCE4(rdev)) { |
140 | if (ASIC_IS_DCE4(rdev)) { |
141 | cur_lock = RREG32(EVERGREEN_CUR_UPDATE); |
141 | cur_lock = RREG32(EVERGREEN_CUR_UPDATE); |
142 | if (lock) |
142 | if (lock) |
143 | cur_lock |= EVERGREEN_CURSOR_UPDATE_LOCK; |
143 | cur_lock |= EVERGREEN_CURSOR_UPDATE_LOCK; |
144 | else |
144 | else |
145 | cur_lock &= ~EVERGREEN_CURSOR_UPDATE_LOCK; |
145 | cur_lock &= ~EVERGREEN_CURSOR_UPDATE_LOCK; |
146 | WREG32(EVERGREEN_CUR_UPDATE, cur_lock); |
146 | WREG32(EVERGREEN_CUR_UPDATE, cur_lock); |
147 | } else if (ASIC_IS_AVIVO(rdev)) { |
147 | } else if (ASIC_IS_AVIVO(rdev)) { |
148 | cur_lock = RREG32(AVIVO_D1CUR_UPDATE); |
148 | cur_lock = RREG32(AVIVO_D1CUR_UPDATE); |
149 | if (lock) |
149 | if (lock) |
150 | cur_lock |= AVIVO_D1CURSOR_UPDATE_LOCK; |
150 | cur_lock |= AVIVO_D1CURSOR_UPDATE_LOCK; |
151 | else |
151 | else |
152 | cur_lock &= ~AVIVO_D1CURSOR_UPDATE_LOCK; |
152 | cur_lock &= ~AVIVO_D1CURSOR_UPDATE_LOCK; |
153 | WREG32(AVIVO_D1CUR_UPDATE, cur_lock); |
153 | WREG32(AVIVO_D1CUR_UPDATE, cur_lock); |
154 | } else { |
154 | } else { |
155 | cur_lock = RREG32(RADEON_CUR_OFFSET); |
155 | cur_lock = RREG32(RADEON_CUR_OFFSET); |
156 | if (lock) |
156 | if (lock) |
157 | cur_lock |= RADEON_CUR_LOCK; |
157 | cur_lock |= RADEON_CUR_LOCK; |
158 | else |
158 | else |
159 | cur_lock &= ~RADEON_CUR_LOCK; |
159 | cur_lock &= ~RADEON_CUR_LOCK; |
160 | WREG32(RADEON_CUR_OFFSET, cur_lock); |
160 | WREG32(RADEON_CUR_OFFSET, cur_lock); |
161 | } |
161 | } |
162 | } |
162 | } |
163 | 163 | ||
164 | 164 | ||
165 | void __stdcall move_cursor(cursor_t *cursor, int x, int y) |
165 | void __stdcall move_cursor(cursor_t *cursor, int x, int y) |
166 | { |
166 | { |
167 | struct radeon_device *rdev; |
167 | struct radeon_device *rdev; |
168 | rdev = (struct radeon_device *)os_display->ddev->dev_private; |
168 | rdev = (struct radeon_device *)os_display->ddev->dev_private; |
169 | 169 | ||
170 | int hot_x = cursor->hot_x; |
170 | int hot_x = cursor->hot_x; |
171 | int hot_y = cursor->hot_y; |
171 | int hot_y = cursor->hot_y; |
172 | int w = 32; |
172 | int w = 32; |
173 | 173 | ||
174 | radeon_lock_cursor(true); |
174 | radeon_lock_cursor(true); |
175 | 175 | ||
176 | if (ASIC_IS_DCE4(rdev)) { |
176 | if (ASIC_IS_DCE4(rdev)) { |
177 | WREG32(EVERGREEN_CUR_POSITION,(x << 16) | y); |
177 | WREG32(EVERGREEN_CUR_POSITION,(x << 16) | y); |
178 | WREG32(EVERGREEN_CUR_HOT_SPOT, (hot_x << 16) | hot_y); |
178 | WREG32(EVERGREEN_CUR_HOT_SPOT, (hot_x << 16) | hot_y); |
179 | WREG32(EVERGREEN_CUR_SIZE, ((w - 1) << 16) | 31); |
179 | WREG32(EVERGREEN_CUR_SIZE, ((w - 1) << 16) | 31); |
180 | } else if (ASIC_IS_AVIVO(rdev)) { |
180 | } else if (ASIC_IS_AVIVO(rdev)) { |
181 | WREG32(AVIVO_D1CUR_POSITION, (x << 16) | y); |
181 | WREG32(AVIVO_D1CUR_POSITION, (x << 16) | y); |
182 | WREG32(AVIVO_D1CUR_HOT_SPOT, (hot_x << 16) | hot_y); |
182 | WREG32(AVIVO_D1CUR_HOT_SPOT, (hot_x << 16) | hot_y); |
183 | WREG32(AVIVO_D1CUR_SIZE, ((w - 1) << 16) | 31); |
183 | WREG32(AVIVO_D1CUR_SIZE, ((w - 1) << 16) | 31); |
184 | } else { |
184 | } else { |
185 | 185 | ||
186 | uint32_t gpu_addr; |
186 | uint32_t gpu_addr; |
187 | int xorg =0, yorg=0; |
187 | int xorg =0, yorg=0; |
188 | 188 | ||
189 | x = x - hot_x; |
189 | x = x - hot_x; |
190 | y = y - hot_y; |
190 | y = y - hot_y; |
191 | 191 | ||
192 | if( x < 0 ) |
192 | if( x < 0 ) |
193 | { |
193 | { |
194 | xorg = -x + 1; |
194 | xorg = -x + 1; |
195 | x = 0; |
195 | x = 0; |
196 | } |
196 | } |
197 | 197 | ||
198 | if( y < 0 ) |
198 | if( y < 0 ) |
199 | { |
199 | { |
200 | yorg = -hot_y + 1; |
200 | yorg = -hot_y + 1; |
201 | y = 0; |
201 | y = 0; |
202 | }; |
202 | }; |
203 | 203 | ||
204 | WREG32(RADEON_CUR_HORZ_VERT_OFF, |
204 | WREG32(RADEON_CUR_HORZ_VERT_OFF, |
205 | (RADEON_CUR_LOCK | (xorg << 16) | yorg )); |
205 | (RADEON_CUR_LOCK | (xorg << 16) | yorg )); |
206 | WREG32(RADEON_CUR_HORZ_VERT_POSN, |
206 | WREG32(RADEON_CUR_HORZ_VERT_POSN, |
207 | (RADEON_CUR_LOCK | (x << 16) | y)); |
207 | (RADEON_CUR_LOCK | (x << 16) | y)); |
208 | 208 | ||
209 | gpu_addr = radeon_bo_gpu_offset(cursor->robj); |
209 | gpu_addr = radeon_bo_gpu_offset(cursor->cobj); |
210 | 210 | ||
211 | /* offset is from DISP(2)_BASE_ADDRESS */ |
211 | /* offset is from DISP(2)_BASE_ADDRESS */ |
212 | WREG32(RADEON_CUR_OFFSET, |
212 | WREG32(RADEON_CUR_OFFSET, |
213 | (gpu_addr - rdev->mc.vram_start + (yorg * 256))); |
213 | (gpu_addr - rdev->mc.vram_start + (yorg * 256))); |
214 | } |
214 | } |
215 | radeon_lock_cursor(false); |
215 | radeon_lock_cursor(false); |
216 | } |
216 | } |
217 | 217 | ||
218 | void __stdcall restore_cursor(int x, int y) |
218 | void __stdcall restore_cursor(int x, int y) |
219 | { |
219 | { |
220 | }; |
220 | }; |
221 | 221 | ||
222 | 222 | ||
223 | bool init_display(struct radeon_device *rdev, videomode_t *usermode) |
223 | bool init_display(struct radeon_device *rdev, videomode_t *usermode) |
224 | { |
224 | { |
225 | struct drm_device *dev; |
225 | struct drm_device *dev; |
226 | 226 | ||
227 | cursor_t *cursor; |
227 | cursor_t *cursor; |
228 | bool retval = true; |
228 | bool retval = true; |
229 | u32 ifl; |
229 | u32 ifl; |
230 | 230 | ||
231 | ENTER(); |
231 | ENTER(); |
232 | 232 | ||
233 | os_display = GetDisplay(); |
233 | os_display = GetDisplay(); |
234 | 234 | ||
235 | dev = os_display->ddev = rdev->ddev; |
235 | dev = os_display->ddev = rdev->ddev; |
236 | 236 | ||
237 | ifl = safe_cli(); |
237 | ifl = safe_cli(); |
238 | { |
238 | { |
239 | list_for_each_entry(cursor, &os_display->cursors, list) |
239 | list_for_each_entry(cursor, &os_display->cursors, list) |
240 | { |
240 | { |
241 | init_cursor(cursor); |
241 | init_cursor(cursor); |
242 | }; |
242 | }; |
243 | 243 | ||
244 | os_display->restore_cursor(0,0); |
244 | os_display->restore_cursor(0,0); |
245 | os_display->init_cursor = init_cursor; |
245 | os_display->init_cursor = init_cursor; |
246 | os_display->select_cursor = select_cursor; |
246 | os_display->select_cursor = select_cursor; |
247 | os_display->show_cursor = NULL; |
247 | os_display->show_cursor = NULL; |
248 | os_display->move_cursor = move_cursor; |
248 | os_display->move_cursor = move_cursor; |
249 | os_display->restore_cursor = restore_cursor; |
249 | os_display->restore_cursor = restore_cursor; |
250 | os_display->disable_mouse = disable_mouse; |
250 | os_display->disable_mouse = disable_mouse; |
251 | 251 | ||
252 | select_cursor(os_display->cursor); |
252 | select_cursor(os_display->cursor); |
253 | radeon_show_cursor(); |
253 | radeon_show_cursor(); |
254 | }; |
254 | }; |
255 | safe_sti(ifl); |
255 | safe_sti(ifl); |
256 | 256 | ||
257 | // init_bitmaps(); |
257 | // init_bitmaps(); |
258 | 258 | ||
259 | LEAVE(); |
259 | LEAVE(); |
260 | 260 | ||
261 | return retval; |
261 | return retval; |
262 | }; |
262 | }; |
263 | 263 | ||
264 | 264 | ||
265 | struct fb_info *framebuffer_alloc(size_t size, struct device *dev) |
265 | struct fb_info *framebuffer_alloc(size_t size, struct device *dev) |
266 | { |
266 | { |
267 | #define BYTES_PER_LONG (BITS_PER_LONG/8) |
267 | #define BYTES_PER_LONG (BITS_PER_LONG/8) |
268 | #define PADDING (BYTES_PER_LONG - (sizeof(struct fb_info) % BYTES_PER_LONG)) |
268 | #define PADDING (BYTES_PER_LONG - (sizeof(struct fb_info) % BYTES_PER_LONG)) |
269 | int fb_info_size = sizeof(struct fb_info); |
269 | int fb_info_size = sizeof(struct fb_info); |
270 | struct fb_info *info; |
270 | struct fb_info *info; |
271 | char *p; |
271 | char *p; |
272 | 272 | ||
273 | if (size) |
273 | if (size) |
274 | fb_info_size += PADDING; |
274 | fb_info_size += PADDING; |
275 | 275 | ||
276 | p = kzalloc(fb_info_size + size, GFP_KERNEL); |
276 | p = kzalloc(fb_info_size + size, GFP_KERNEL); |
277 | 277 | ||
278 | if (!p) |
278 | if (!p) |
279 | return NULL; |
279 | return NULL; |
280 | 280 | ||
281 | info = (struct fb_info *) p; |
281 | info = (struct fb_info *) p; |
282 | 282 | ||
283 | if (size) |
283 | if (size) |
284 | info->par = p + fb_info_size; |
284 | info->par = p + fb_info_size; |
285 | 285 | ||
286 | return info; |
286 | return info; |
287 | #undef PADDING |
287 | #undef PADDING |
288 | #undef BYTES_PER_LONG |
288 | #undef BYTES_PER_LONG |
289 | } |
289 | } |
290 | 290 | ||
291 | void framebuffer_release(struct fb_info *info) |
291 | void framebuffer_release(struct fb_info *info) |
292 | { |
292 | { |
293 | kfree(info); |
293 | kfree(info); |
294 | } |
294 | } |
295 | 295 | ||
296 | 296 | ||
297 | /* 23 bits of float fractional data */ |
297 | /* 23 bits of float fractional data */ |
298 | #define I2F_FRAC_BITS 23 |
298 | #define I2F_FRAC_BITS 23 |
299 | #define I2F_MASK ((1 << I2F_FRAC_BITS) - 1) |
299 | #define I2F_MASK ((1 << I2F_FRAC_BITS) - 1) |
300 | 300 | ||
301 | /* |
301 | /* |
302 | * Converts unsigned integer into 32-bit IEEE floating point representation. |
302 | * Converts unsigned integer into 32-bit IEEE floating point representation. |
303 | * Will be exact from 0 to 2^24. Above that, we round towards zero |
303 | * Will be exact from 0 to 2^24. Above that, we round towards zero |
304 | * as the fractional bits will not fit in a float. (It would be better to |
304 | * as the fractional bits will not fit in a float. (It would be better to |
305 | * round towards even as the fpu does, but that is slower.) |
305 | * round towards even as the fpu does, but that is slower.) |
306 | */ |
306 | */ |
307 | __pure uint32_t int2float(uint32_t x) |
307 | __pure uint32_t int2float(uint32_t x) |
308 | { |
308 | { |
309 | uint32_t msb, exponent, fraction; |
309 | uint32_t msb, exponent, fraction; |
310 | 310 | ||
311 | /* Zero is special */ |
311 | /* Zero is special */ |
312 | if (!x) return 0; |
312 | if (!x) return 0; |
313 | 313 | ||
314 | /* Get location of the most significant bit */ |
314 | /* Get location of the most significant bit */ |
315 | msb = __fls(x); |
315 | msb = __fls(x); |
316 | 316 | ||
317 | /* |
317 | /* |
318 | * Use a rotate instead of a shift because that works both leftwards |
318 | * Use a rotate instead of a shift because that works both leftwards |
319 | * and rightwards due to the mod(32) behaviour. This means we don't |
319 | * and rightwards due to the mod(32) behaviour. This means we don't |
320 | * need to check to see if we are above 2^24 or not. |
320 | * need to check to see if we are above 2^24 or not. |
321 | */ |
321 | */ |
322 | fraction = ror32(x, (msb - I2F_FRAC_BITS) & 0x1f) & I2F_MASK; |
322 | fraction = ror32(x, (msb - I2F_FRAC_BITS) & 0x1f) & I2F_MASK; |
323 | exponent = (127 + msb) << I2F_FRAC_BITS; |
323 | exponent = (127 + msb) << I2F_FRAC_BITS; |
324 | 324 | ||
325 | return fraction + exponent; |
325 | return fraction + exponent; |
326 | }><>><>><>><>>>><>><>><>><>><>><>><>><>>>>> |
326 | }><>><>><>><>>>><>><>><>><>><>><>><>><>>>>> |