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