Bug Summary

File:dev/pci/drm/radeon/radeon_fb.c
Warning:line 276, column 2
Value stored to 'tmp' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name radeon_fb.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -D CONFIG_DRM_AMD_DC_DCN3_0 -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /usr/obj/sys/arch/amd64/compile/GENERIC.MP/scan-build/2022-01-12-131800-47421-1 -x c /usr/src/sys/dev/pci/drm/radeon/radeon_fb.c
1/*
2 * Copyright © 2007 David Airlie
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 *
23 * Authors:
24 * David Airlie
25 */
26
27#include <linux/module.h>
28#include <linux/pci.h>
29#include <linux/pm_runtime.h>
30#include <linux/slab.h>
31#include <linux/vga_switcheroo.h>
32
33#include <drm/drm_crtc.h>
34#include <drm/drm_crtc_helper.h>
35#include <drm/drm_fb_helper.h>
36#include <drm/drm_fourcc.h>
37#include <drm/radeon_drm.h>
38
39#include "radeon.h"
40
41/* object hierarchy -
42 * this contains a helper + a radeon fb
43 * the helper contains a pointer to radeon framebuffer baseclass.
44 */
45struct radeon_fbdev {
46 struct drm_fb_helper helper; /* must be first */
47 struct drm_framebuffer fb;
48 struct radeon_device *rdev;
49};
50
51#ifdef __linux__
52static int
53radeonfb_open(struct fb_info *info, int user)
54{
55 struct radeon_fbdev *rfbdev = info->par;
56 struct radeon_device *rdev = rfbdev->rdev;
57 int ret = pm_runtime_get_sync(rdev->ddev->dev);
58 if (ret < 0 && ret != -EACCES13) {
59 pm_runtime_mark_last_busy(rdev->ddev->dev);
60 pm_runtime_put_autosuspend(rdev->ddev->dev);
61 return ret;
62 }
63 return 0;
64}
65
66static int
67radeonfb_release(struct fb_info *info, int user)
68{
69 struct radeon_fbdev *rfbdev = info->par;
70 struct radeon_device *rdev = rfbdev->rdev;
71
72 pm_runtime_mark_last_busy(rdev->ddev->dev);
73 pm_runtime_put_autosuspend(rdev->ddev->dev);
74 return 0;
75}
76#endif
77
78static const struct fb_ops radeonfb_ops = {
79#ifdef notyet
80 .owner = THIS_MODULE((void *)0),
81 DRM_FB_HELPER_DEFAULT_OPS.fb_set_par = drm_fb_helper_set_par,
82 .fb_open = radeonfb_open,
83 .fb_release = radeonfb_release,
84 .fb_fillrect = drm_fb_helper_cfb_fillrect,
85 .fb_copyarea = drm_fb_helper_cfb_copyarea,
86 .fb_imageblit = drm_fb_helper_cfb_imageblit,
87#else
88 DRM_FB_HELPER_DEFAULT_OPS.fb_set_par = drm_fb_helper_set_par,
89#endif
90};
91
92void radeondrm_burner_cb(void *);
93
94int radeon_align_pitch(struct radeon_device *rdev, int width, int cpp, bool_Bool tiled)
95{
96 int aligned = width;
97 int align_large = (ASIC_IS_AVIVO(rdev)((rdev->family >= CHIP_RS600))) || tiled;
98 int pitch_mask = 0;
99
100 switch (cpp) {
101 case 1:
102 pitch_mask = align_large ? 255 : 127;
103 break;
104 case 2:
105 pitch_mask = align_large ? 127 : 31;
106 break;
107 case 3:
108 case 4:
109 pitch_mask = align_large ? 63 : 15;
110 break;
111 }
112
113 aligned += pitch_mask;
114 aligned &= ~pitch_mask;
115 return aligned * cpp;
116}
117
118static void radeonfb_destroy_pinned_object(struct drm_gem_object *gobj)
119{
120 struct radeon_bo *rbo = gem_to_radeon_bo(gobj)({ const __typeof( ((struct radeon_bo *)0)->tbo.base ) *__mptr
= ((gobj)); (struct radeon_bo *)( (char *)__mptr - __builtin_offsetof
(struct radeon_bo, tbo.base) );})
;
121 int ret;
122
123 ret = radeon_bo_reserve(rbo, false0);
124 if (likely(ret == 0)__builtin_expect(!!(ret == 0), 1)) {
125 radeon_bo_kunmap(rbo);
126 radeon_bo_unpin(rbo);
127 radeon_bo_unreserve(rbo);
128 }
129 drm_gem_object_put(gobj);
130}
131
132static int radeonfb_create_pinned_object(struct radeon_fbdev *rfbdev,
133 struct drm_mode_fb_cmd2 *mode_cmd,
134 struct drm_gem_object **gobj_p)
135{
136 const struct drm_format_info *info;
137 struct radeon_device *rdev = rfbdev->rdev;
138 struct drm_gem_object *gobj = NULL((void *)0);
139 struct radeon_bo *rbo = NULL((void *)0);
140 bool_Bool fb_tiled = false0; /* useful for testing */
141 u32 tiling_flags = 0;
142 int ret;
143 int aligned_size, size;
144 int height = mode_cmd->height;
145 u32 cpp;
146
147 info = drm_get_format_info(rdev->ddev, mode_cmd);
148 cpp = info->cpp[0];
149
150 /* need to align pitch with crtc limits */
151 mode_cmd->pitches[0] = radeon_align_pitch(rdev, mode_cmd->width, cpp,
152 fb_tiled);
153
154 if (rdev->family >= CHIP_R600)
155 height = roundup2(mode_cmd->height, 8)(((mode_cmd->height) + ((8) - 1)) & (~((__typeof(mode_cmd
->height))(8) - 1)))
;
156 size = mode_cmd->pitches[0] * height;
157 aligned_size = roundup2(size, PAGE_SIZE)(((size) + (((1 << 12)) - 1)) & (~((__typeof(size))
((1 << 12)) - 1)))
;
158 ret = radeon_gem_object_create(rdev, aligned_size, 0,
159 RADEON_GEM_DOMAIN_VRAM0x4,
160 0, true1, &gobj);
161 if (ret) {
162 pr_err("failed to allocate framebuffer (%d)\n", aligned_size)printk("\0013" "failed to allocate framebuffer (%d)\n", aligned_size
)
;
163 return -ENOMEM12;
164 }
165 rbo = gem_to_radeon_bo(gobj)({ const __typeof( ((struct radeon_bo *)0)->tbo.base ) *__mptr
= ((gobj)); (struct radeon_bo *)( (char *)__mptr - __builtin_offsetof
(struct radeon_bo, tbo.base) );})
;
166
167 if (fb_tiled)
168 tiling_flags = RADEON_TILING_MACRO0x1;
169
170#ifdef __BIG_ENDIAN
171 switch (cpp) {
172 case 4:
173 tiling_flags |= RADEON_TILING_SWAP_32BIT0x8;
174 break;
175 case 2:
176 tiling_flags |= RADEON_TILING_SWAP_16BIT0x4;
177 default:
178 break;
179 }
180#endif
181
182 if (tiling_flags) {
183 ret = radeon_bo_set_tiling_flags(rbo,
184 tiling_flags | RADEON_TILING_SURFACE0x10,
185 mode_cmd->pitches[0]);
186 if (ret)
187 dev_err(rdev->dev, "FB failed to set tiling flags\n")printf("drm:pid%d:%s *ERROR* " "FB failed to set tiling flags\n"
, ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc->p_p->ps_pid, __func__)
;
188 }
189
190
191 ret = radeon_bo_reserve(rbo, false0);
192 if (unlikely(ret != 0)__builtin_expect(!!(ret != 0), 0))
193 goto out_unref;
194 /* Only 27 bit offset for legacy CRTC */
195 ret = radeon_bo_pin_restricted(rbo, RADEON_GEM_DOMAIN_VRAM0x4,
196 ASIC_IS_AVIVO(rdev)((rdev->family >= CHIP_RS600)) ? 0 : 1 << 27,
197 NULL((void *)0));
198 if (ret) {
199 radeon_bo_unreserve(rbo);
200 goto out_unref;
201 }
202 if (fb_tiled)
203 radeon_bo_check_tiling(rbo, 0, 0);
204 ret = radeon_bo_kmap(rbo, NULL((void *)0));
205 radeon_bo_unreserve(rbo);
206 if (ret) {
207 goto out_unref;
208 }
209
210 *gobj_p = gobj;
211 return 0;
212out_unref:
213 radeonfb_destroy_pinned_object(gobj);
214 *gobj_p = NULL((void *)0);
215 return ret;
216}
217
218static int radeonfb_create(struct drm_fb_helper *helper,
219 struct drm_fb_helper_surface_size *sizes)
220{
221 struct radeon_fbdev *rfbdev =
222 container_of(helper, struct radeon_fbdev, helper)({ const __typeof( ((struct radeon_fbdev *)0)->helper ) *__mptr
= (helper); (struct radeon_fbdev *)( (char *)__mptr - __builtin_offsetof
(struct radeon_fbdev, helper) );})
;
223 struct radeon_device *rdev = rfbdev->rdev;
224 struct fb_info *info;
225 struct rasops_info *ri = &rdev->ro;
226 struct drm_framebuffer *fb = NULL((void *)0);
227 struct drm_mode_fb_cmd2 mode_cmd;
228 struct drm_gem_object *gobj = NULL((void *)0);
229 struct radeon_bo *rbo = NULL((void *)0);
230 int ret;
231 unsigned long tmp;
232
233 mode_cmd.width = sizes->surface_width;
234 mode_cmd.height = sizes->surface_height;
235
236 /* avivo can't scanout real 24bpp */
237 if ((sizes->surface_bpp == 24) && ASIC_IS_AVIVO(rdev)((rdev->family >= CHIP_RS600)))
238 sizes->surface_bpp = 32;
239
240 mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
241 sizes->surface_depth);
242
243 ret = radeonfb_create_pinned_object(rfbdev, &mode_cmd, &gobj);
244 if (ret) {
245 DRM_ERROR("failed to create fbcon object %d\n", ret)__drm_err("failed to create fbcon object %d\n", ret);
246 return ret;
247 }
248
249 rbo = gem_to_radeon_bo(gobj)({ const __typeof( ((struct radeon_bo *)0)->tbo.base ) *__mptr
= ((gobj)); (struct radeon_bo *)( (char *)__mptr - __builtin_offsetof
(struct radeon_bo, tbo.base) );})
;
250
251 /* okay we have an object now allocate the framebuffer */
252 info = drm_fb_helper_alloc_fbi(helper);
253 if (IS_ERR(info)) {
254 ret = PTR_ERR(info);
255 goto out;
256 }
257
258 /* radeon resume is fragile and needs a vt switch to help it along */
259 info->skip_vt_switch = false0;
260
261 ret = radeon_framebuffer_init(rdev->ddev, &rfbdev->fb, &mode_cmd, gobj);
262 if (ret) {
263 DRM_ERROR("failed to initialize framebuffer %d\n", ret)__drm_err("failed to initialize framebuffer %d\n", ret);
264 goto out;
265 }
266
267 fb = &rfbdev->fb;
268
269 /* setup helper */
270 rfbdev->helper.fb = fb;
271
272 memset_io(rbo->kptr, 0x0, radeon_bo_size(rbo))__builtin_memset((rbo->kptr), (0x0), (radeon_bo_size(rbo))
)
;
273
274 info->fbops = &radeonfb_ops;
275
276 tmp = radeon_bo_gpu_offset(rbo) - rdev->mc.vram_start;
Value stored to 'tmp' is never read
277#ifdef __linux__
278 info->fix.smem_start = rdev->mc.aper_base + tmp;
279 info->fix.smem_len = radeon_bo_size(rbo);
280 info->screen_base = rbo->kptr;
281 info->screen_size = radeon_bo_size(rbo);
282#endif
283
284 drm_fb_helper_fill_info(info, &rfbdev->helper, sizes);
285
286#ifdef __linux__
287 /* setup aperture base/size for vesafb takeover */
288 info->apertures->ranges[0].base = rdev->ddev->mode_config.fb_base;
289 info->apertures->ranges[0].size = rdev->mc.aper_size;
290#endif
291
292 /* Use default scratch pixmap (info->pixmap.flags = FB_PIXMAP_SYSTEM) */
293
294#ifdef __linux__
295 if (info->screen_base == NULL((void *)0)) {
296 ret = -ENOSPC28;
297 goto out;
298 }
299
300 DRM_INFO("fb mappable at 0x%lX\n", info->fix.smem_start)printk("\0016" "[" "drm" "] " "fb mappable at 0x%lX\n", info->
fix.smem_start)
;
301#endif
302 DRM_INFO("vram apper at 0x%lX\n", (unsigned long)rdev->mc.aper_base)printk("\0016" "[" "drm" "] " "vram apper at 0x%lX\n", (unsigned
long)rdev->mc.aper_base)
;
303 DRM_INFO("size %lu\n", (unsigned long)radeon_bo_size(rbo))printk("\0016" "[" "drm" "] " "size %lu\n", (unsigned long)radeon_bo_size
(rbo))
;
304 DRM_INFO("fb depth is %d\n", fb->format->depth)printk("\0016" "[" "drm" "] " "fb depth is %d\n", fb->format
->depth)
;
305 DRM_INFO(" pitch is %d\n", fb->pitches[0])printk("\0016" "[" "drm" "] " " pitch is %d\n", fb->pitches
[0])
;
306
307 ri->ri_bits = rbo->kptr;
308 ri->ri_depth = fb->format->cpp[0] * 8;
309 ri->ri_stride = fb->pitches[0];
310 ri->ri_width = sizes->fb_width;
311 ri->ri_height = sizes->fb_height;
312
313 switch (fb->format->format) {
314 case DRM_FORMAT_XRGB8888((__u32)('X') | ((__u32)('R') << 8) | ((__u32)('2') <<
16) | ((__u32)('4') << 24))
:
315 ri->ri_rnum = 8;
316 ri->ri_rpos = 16;
317 ri->ri_gnum = 8;
318 ri->ri_gpos = 8;
319 ri->ri_bnum = 8;
320 ri->ri_bpos = 0;
321 break;
322 case DRM_FORMAT_RGB565((__u32)('R') | ((__u32)('G') << 8) | ((__u32)('1') <<
16) | ((__u32)('6') << 24))
:
323 ri->ri_rnum = 5;
324 ri->ri_rpos = 11;
325 ri->ri_gnum = 6;
326 ri->ri_gpos = 5;
327 ri->ri_bnum = 5;
328 ri->ri_bpos = 0;
329 break;
330 }
331
332 vga_switcheroo_client_fb_set(rdev->ddev->pdev, info);
333 return 0;
334
335out:
336 if (rbo) {
337
338 }
339 if (fb && ret) {
340 drm_gem_object_put(gobj);
341 drm_framebuffer_unregister_private(fb);
342 drm_framebuffer_cleanup(fb);
343 kfree(fb);
344 }
345 return ret;
346}
347
348#ifdef notyet
349static int radeon_fbdev_destroy(struct drm_device *dev, struct radeon_fbdev *rfbdev)
350{
351 struct drm_framebuffer *fb = &rfbdev->fb;
352
353 drm_fb_helper_unregister_fbi(&rfbdev->helper);
354
355 if (fb->obj[0]) {
356 radeonfb_destroy_pinned_object(fb->obj[0]);
357 fb->obj[0] = NULL((void *)0);
358 drm_framebuffer_unregister_private(fb);
359 drm_framebuffer_cleanup(fb);
360 }
361 drm_fb_helper_fini(&rfbdev->helper);
362
363 return 0;
364}
365#endif
366
367static const struct drm_fb_helper_funcs radeon_fb_helper_funcs = {
368 .fb_probe = radeonfb_create,
369};
370
371int radeon_fbdev_init(struct radeon_device *rdev)
372{
373 struct radeon_fbdev *rfbdev;
374 int bpp_sel = 32;
375 int ret;
376
377 /* don't enable fbdev if no connectors */
378 if (list_empty(&rdev->ddev->mode_config.connector_list))
379 return 0;
380
381 /* select 8 bpp console on 8MB cards, or 16 bpp on RN50 or 32MB */
382 if (rdev->mc.real_vram_size <= (8*1024*1024))
383 bpp_sel = 8;
384 else if (ASIC_IS_RN50(rdev)((rdev->pdev->device == 0x515e) || (rdev->pdev->device
== 0x5969))
||
385 rdev->mc.real_vram_size <= (32*1024*1024))
386 bpp_sel = 16;
387
388 rfbdev = kzalloc(sizeof(struct radeon_fbdev), GFP_KERNEL(0x0001 | 0x0004));
389 if (!rfbdev)
390 return -ENOMEM12;
391
392 rfbdev->rdev = rdev;
393 rdev->mode_info.rfbdev = rfbdev;
394
395 drm_fb_helper_prepare(rdev->ddev, &rfbdev->helper,
396 &radeon_fb_helper_funcs);
397
398 ret = drm_fb_helper_init(rdev->ddev, &rfbdev->helper);
399 if (ret)
400 goto free;
401
402 task_set(&rdev->burner_task, radeondrm_burner_cb, rdev);
403
404#ifdef __sparc64__
405{
406 struct drm_fb_helper *fb_helper = &rfbdev->helper;
407 struct drm_connector_list_iter conn_iter;
408 struct drm_connector *connector;
409 struct drm_cmdline_mode *mode;
410
411 drm_connector_list_iter_begin(fb_helper->dev, &conn_iter);
412 drm_client_for_each_connector_iter(connector, &conn_iter)while ((connector = drm_connector_list_iter_next(&conn_iter
))) if (connector->connector_type != 18)
{
413 mode = &connector->cmdline_mode;
414
415 mode->specified = true1;
416 mode->xres = rdev->sf.sf_width;
417 mode->yres = rdev->sf.sf_height;
418 mode->bpp_specified = true1;
419 mode->bpp = rdev->sf.sf_depth;
420 }
421 drm_connector_list_iter_end(&conn_iter);
422}
423#endif
424
425 /* disable all the possible outputs/crtcs before entering KMS mode */
426 drm_helper_disable_unused_functions(rdev->ddev);
427
428 ret = drm_fb_helper_initial_config(&rfbdev->helper, bpp_sel);
429 if (ret)
430 goto fini;
431
432 return 0;
433
434fini:
435 drm_fb_helper_fini(&rfbdev->helper);
436free:
437 kfree(rfbdev);
438 return ret;
439}
440
441void radeon_fbdev_fini(struct radeon_device *rdev)
442{
443 if (!rdev->mode_info.rfbdev)
444 return;
445
446 task_del(systq, &rdev->burner_task);
447
448#ifdef notyet
449 radeon_fbdev_destroy(rdev->ddev, rdev->mode_info.rfbdev);
450#endif
451 kfree(rdev->mode_info.rfbdev);
452 rdev->mode_info.rfbdev = NULL((void *)0);
453}
454
455void radeon_fbdev_set_suspend(struct radeon_device *rdev, int state)
456{
457 if (rdev->mode_info.rfbdev)
458 drm_fb_helper_set_suspend(&rdev->mode_info.rfbdev->helper, state);
459}
460
461bool_Bool radeon_fbdev_robj_is_fb(struct radeon_device *rdev, struct radeon_bo *robj)
462{
463 if (!rdev->mode_info.rfbdev)
464 return false0;
465
466 if (robj == gem_to_radeon_bo(rdev->mode_info.rfbdev->fb.obj[0])({ const __typeof( ((struct radeon_bo *)0)->tbo.base ) *__mptr
= ((rdev->mode_info.rfbdev->fb.obj[0])); (struct radeon_bo
*)( (char *)__mptr - __builtin_offsetof(struct radeon_bo, tbo
.base) );})
)
467 return true1;
468 return false0;
469}
470
471void
472radeondrm_burner(void *v, u_int on, u_int flags)
473{
474 struct rasops_info *ri = v;
475 struct radeon_device *rdev = ri->ri_hw;
476
477 task_del(systq, &rdev->burner_task);
478
479 if (on)
480 rdev->burner_fblank = FB_BLANK_UNBLANK0;
481 else {
482 if (flags & WSDISPLAY_BURN_VBLANK0x0001)
483 rdev->burner_fblank = FB_BLANK_VSYNC_SUSPEND3;
484 else
485 rdev->burner_fblank = FB_BLANK_NORMAL1;
486 }
487
488 /*
489 * Setting the DPMS mode may sleep while waiting for vblank so
490 * hand things off to a taskq.
491 */
492 task_add(systq, &rdev->burner_task);
493}
494
495void
496radeondrm_burner_cb(void *arg1)
497{
498 struct radeon_device *rdev = arg1;
499 struct drm_fb_helper *helper = &rdev->mode_info.rfbdev->helper;
500
501 drm_fb_helper_blank(rdev->burner_fblank, helper->fbdev);
502}