2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
10 /* ---------------------------------------------------------------------- */
12 static int bochsfb_mmap(struct fb_info
*info
,
13 struct vm_area_struct
*vma
)
15 struct drm_fb_helper
*fb_helper
= info
->par
;
16 struct bochs_device
*bochs
=
17 container_of(fb_helper
, struct bochs_device
, fb
.helper
);
18 struct bochs_bo
*bo
= gem_to_bochs_bo(bochs
->fb
.gfb
.obj
);
20 return ttm_fbdev_mmap(vma
, &bo
->bo
);
23 static struct fb_ops bochsfb_ops
= {
25 .fb_check_var
= drm_fb_helper_check_var
,
26 .fb_set_par
= drm_fb_helper_set_par
,
27 .fb_fillrect
= drm_fb_helper_sys_fillrect
,
28 .fb_copyarea
= drm_fb_helper_sys_copyarea
,
29 .fb_imageblit
= drm_fb_helper_sys_imageblit
,
30 .fb_pan_display
= drm_fb_helper_pan_display
,
31 .fb_blank
= drm_fb_helper_blank
,
32 .fb_setcmap
= drm_fb_helper_setcmap
,
33 .fb_mmap
= bochsfb_mmap
,
36 static int bochsfb_create_object(struct bochs_device
*bochs
,
37 const struct drm_mode_fb_cmd2
*mode_cmd
,
38 struct drm_gem_object
**gobj_p
)
40 struct drm_device
*dev
= bochs
->dev
;
41 struct drm_gem_object
*gobj
;
45 size
= mode_cmd
->pitches
[0] * mode_cmd
->height
;
46 ret
= bochs_gem_create(dev
, size
, true, &gobj
);
54 static int bochsfb_create(struct drm_fb_helper
*helper
,
55 struct drm_fb_helper_surface_size
*sizes
)
57 struct bochs_device
*bochs
=
58 container_of(helper
, struct bochs_device
, fb
.helper
);
60 struct drm_framebuffer
*fb
;
61 struct drm_mode_fb_cmd2 mode_cmd
;
62 struct drm_gem_object
*gobj
= NULL
;
63 struct bochs_bo
*bo
= NULL
;
66 if (sizes
->surface_bpp
!= 32)
69 mode_cmd
.width
= sizes
->surface_width
;
70 mode_cmd
.height
= sizes
->surface_height
;
71 mode_cmd
.pitches
[0] = mode_cmd
.width
* ((sizes
->surface_bpp
+ 7) / 8);
72 mode_cmd
.pixel_format
= drm_mode_legacy_fb_format(sizes
->surface_bpp
,
73 sizes
->surface_depth
);
74 size
= mode_cmd
.pitches
[0] * mode_cmd
.height
;
76 /* alloc, pin & map bo */
77 ret
= bochsfb_create_object(bochs
, &mode_cmd
, &gobj
);
79 DRM_ERROR("failed to create fbcon backing object %d\n", ret
);
83 bo
= gem_to_bochs_bo(gobj
);
85 ret
= ttm_bo_reserve(&bo
->bo
, true, false, NULL
);
89 ret
= bochs_bo_pin(bo
, TTM_PL_FLAG_VRAM
, NULL
);
91 DRM_ERROR("failed to pin fbcon\n");
92 ttm_bo_unreserve(&bo
->bo
);
96 ret
= ttm_bo_kmap(&bo
->bo
, 0, bo
->bo
.num_pages
,
99 DRM_ERROR("failed to kmap fbcon\n");
100 ttm_bo_unreserve(&bo
->bo
);
104 ttm_bo_unreserve(&bo
->bo
);
107 info
= drm_fb_helper_alloc_fbi(helper
);
109 return PTR_ERR(info
);
111 info
->par
= &bochs
->fb
.helper
;
113 ret
= bochs_framebuffer_init(bochs
->dev
, &bochs
->fb
.gfb
, &mode_cmd
, gobj
);
115 drm_fb_helper_release_fbi(helper
);
119 bochs
->fb
.size
= size
;
122 fb
= &bochs
->fb
.gfb
.base
;
123 bochs
->fb
.helper
.fb
= fb
;
125 strcpy(info
->fix
.id
, "bochsdrmfb");
127 info
->flags
= FBINFO_DEFAULT
;
128 info
->fbops
= &bochsfb_ops
;
130 drm_fb_helper_fill_fix(info
, fb
->pitches
[0], fb
->depth
);
131 drm_fb_helper_fill_var(info
, &bochs
->fb
.helper
, sizes
->fb_width
,
134 info
->screen_base
= bo
->kmap
.virtual;
135 info
->screen_size
= size
;
137 drm_vma_offset_remove(&bo
->bo
.bdev
->vma_manager
, &bo
->bo
.vma_node
);
138 info
->fix
.smem_start
= 0;
139 info
->fix
.smem_len
= size
;
141 bochs
->fb
.initialized
= true;
145 static int bochs_fbdev_destroy(struct bochs_device
*bochs
)
147 struct bochs_framebuffer
*gfb
= &bochs
->fb
.gfb
;
149 DRM_DEBUG_DRIVER("\n");
151 drm_fb_helper_unregister_fbi(&bochs
->fb
.helper
);
152 drm_fb_helper_release_fbi(&bochs
->fb
.helper
);
155 drm_gem_object_unreference_unlocked(gfb
->obj
);
159 drm_framebuffer_unregister_private(&gfb
->base
);
160 drm_framebuffer_cleanup(&gfb
->base
);
165 static const struct drm_fb_helper_funcs bochs_fb_helper_funcs
= {
166 .fb_probe
= bochsfb_create
,
169 int bochs_fbdev_init(struct bochs_device
*bochs
)
173 drm_fb_helper_prepare(bochs
->dev
, &bochs
->fb
.helper
,
174 &bochs_fb_helper_funcs
);
176 ret
= drm_fb_helper_init(bochs
->dev
, &bochs
->fb
.helper
,
181 ret
= drm_fb_helper_single_add_all_connectors(&bochs
->fb
.helper
);
185 drm_helper_disable_unused_functions(bochs
->dev
);
187 ret
= drm_fb_helper_initial_config(&bochs
->fb
.helper
, 32);
194 drm_fb_helper_fini(&bochs
->fb
.helper
);
198 void bochs_fbdev_fini(struct bochs_device
*bochs
)
200 if (bochs
->fb
.initialized
)
201 bochs_fbdev_destroy(bochs
);
203 drm_fb_helper_fini(&bochs
->fb
.helper
);
204 bochs
->fb
.initialized
= false;