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 DRM_FB_HELPER_DEFAULT_OPS
,
26 .fb_fillrect
= drm_fb_helper_cfb_fillrect
,
27 .fb_copyarea
= drm_fb_helper_cfb_copyarea
,
28 .fb_imageblit
= drm_fb_helper_cfb_imageblit
,
29 .fb_mmap
= bochsfb_mmap
,
32 static int bochsfb_create_object(struct bochs_device
*bochs
,
33 const struct drm_mode_fb_cmd2
*mode_cmd
,
34 struct drm_gem_object
**gobj_p
)
36 struct drm_device
*dev
= bochs
->dev
;
37 struct drm_gem_object
*gobj
;
41 size
= mode_cmd
->pitches
[0] * mode_cmd
->height
;
42 ret
= bochs_gem_create(dev
, size
, true, &gobj
);
50 static int bochsfb_create(struct drm_fb_helper
*helper
,
51 struct drm_fb_helper_surface_size
*sizes
)
53 struct bochs_device
*bochs
=
54 container_of(helper
, struct bochs_device
, fb
.helper
);
56 struct drm_framebuffer
*fb
;
57 struct drm_mode_fb_cmd2 mode_cmd
;
58 struct drm_gem_object
*gobj
= NULL
;
59 struct bochs_bo
*bo
= NULL
;
62 if (sizes
->surface_bpp
!= 32)
65 mode_cmd
.width
= sizes
->surface_width
;
66 mode_cmd
.height
= sizes
->surface_height
;
67 mode_cmd
.pitches
[0] = mode_cmd
.width
* ((sizes
->surface_bpp
+ 7) / 8);
68 mode_cmd
.pixel_format
= drm_mode_legacy_fb_format(sizes
->surface_bpp
,
69 sizes
->surface_depth
);
70 size
= mode_cmd
.pitches
[0] * mode_cmd
.height
;
72 /* alloc, pin & map bo */
73 ret
= bochsfb_create_object(bochs
, &mode_cmd
, &gobj
);
75 DRM_ERROR("failed to create fbcon backing object %d\n", ret
);
79 bo
= gem_to_bochs_bo(gobj
);
81 ret
= ttm_bo_reserve(&bo
->bo
, true, false, NULL
);
85 ret
= bochs_bo_pin(bo
, TTM_PL_FLAG_VRAM
, NULL
);
87 DRM_ERROR("failed to pin fbcon\n");
88 ttm_bo_unreserve(&bo
->bo
);
92 ret
= ttm_bo_kmap(&bo
->bo
, 0, bo
->bo
.num_pages
,
95 DRM_ERROR("failed to kmap fbcon\n");
96 ttm_bo_unreserve(&bo
->bo
);
100 ttm_bo_unreserve(&bo
->bo
);
103 info
= drm_fb_helper_alloc_fbi(helper
);
105 return PTR_ERR(info
);
107 info
->par
= &bochs
->fb
.helper
;
109 ret
= bochs_framebuffer_init(bochs
->dev
, &bochs
->fb
.gfb
, &mode_cmd
, gobj
);
113 bochs
->fb
.size
= size
;
116 fb
= &bochs
->fb
.gfb
.base
;
117 bochs
->fb
.helper
.fb
= fb
;
119 strcpy(info
->fix
.id
, "bochsdrmfb");
121 info
->fbops
= &bochsfb_ops
;
123 drm_fb_helper_fill_fix(info
, fb
->pitches
[0], fb
->format
->depth
);
124 drm_fb_helper_fill_var(info
, &bochs
->fb
.helper
, sizes
->fb_width
,
127 info
->screen_base
= bo
->kmap
.virtual;
128 info
->screen_size
= size
;
130 drm_vma_offset_remove(&bo
->bo
.bdev
->vma_manager
, &bo
->bo
.vma_node
);
131 info
->fix
.smem_start
= 0;
132 info
->fix
.smem_len
= size
;
134 bochs
->fb
.initialized
= true;
138 static int bochs_fbdev_destroy(struct bochs_device
*bochs
)
140 struct bochs_framebuffer
*gfb
= &bochs
->fb
.gfb
;
142 DRM_DEBUG_DRIVER("\n");
144 drm_fb_helper_unregister_fbi(&bochs
->fb
.helper
);
147 drm_gem_object_unreference_unlocked(gfb
->obj
);
151 drm_framebuffer_unregister_private(&gfb
->base
);
152 drm_framebuffer_cleanup(&gfb
->base
);
157 static const struct drm_fb_helper_funcs bochs_fb_helper_funcs
= {
158 .fb_probe
= bochsfb_create
,
161 int bochs_fbdev_init(struct bochs_device
*bochs
)
165 drm_fb_helper_prepare(bochs
->dev
, &bochs
->fb
.helper
,
166 &bochs_fb_helper_funcs
);
168 ret
= drm_fb_helper_init(bochs
->dev
, &bochs
->fb
.helper
, 1);
172 ret
= drm_fb_helper_single_add_all_connectors(&bochs
->fb
.helper
);
176 drm_helper_disable_unused_functions(bochs
->dev
);
178 ret
= drm_fb_helper_initial_config(&bochs
->fb
.helper
, 32);
185 drm_fb_helper_fini(&bochs
->fb
.helper
);
189 void bochs_fbdev_fini(struct bochs_device
*bochs
)
191 if (bochs
->fb
.initialized
)
192 bochs_fbdev_destroy(bochs
);
194 if (bochs
->fb
.helper
.fbdev
)
195 drm_fb_helper_fini(&bochs
->fb
.helper
);
197 bochs
->fb
.initialized
= false;