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.
9 #include <drm/drm_gem_framebuffer_helper.h>
11 /* ---------------------------------------------------------------------- */
13 static int bochsfb_mmap(struct fb_info
*info
,
14 struct vm_area_struct
*vma
)
16 struct drm_fb_helper
*fb_helper
= info
->par
;
17 struct bochs_bo
*bo
= gem_to_bochs_bo(fb_helper
->fb
->obj
[0]);
19 return ttm_fbdev_mmap(vma
, &bo
->bo
);
22 static struct fb_ops bochsfb_ops
= {
24 DRM_FB_HELPER_DEFAULT_OPS
,
25 .fb_fillrect
= drm_fb_helper_cfb_fillrect
,
26 .fb_copyarea
= drm_fb_helper_cfb_copyarea
,
27 .fb_imageblit
= drm_fb_helper_cfb_imageblit
,
28 .fb_mmap
= bochsfb_mmap
,
31 static int bochsfb_create_object(struct bochs_device
*bochs
,
32 const struct drm_mode_fb_cmd2
*mode_cmd
,
33 struct drm_gem_object
**gobj_p
)
35 struct drm_device
*dev
= bochs
->dev
;
36 struct drm_gem_object
*gobj
;
40 size
= mode_cmd
->pitches
[0] * mode_cmd
->height
;
41 ret
= bochs_gem_create(dev
, size
, true, &gobj
);
49 static int bochsfb_create(struct drm_fb_helper
*helper
,
50 struct drm_fb_helper_surface_size
*sizes
)
52 struct bochs_device
*bochs
=
53 container_of(helper
, struct bochs_device
, fb
.helper
);
55 struct drm_framebuffer
*fb
;
56 struct drm_mode_fb_cmd2 mode_cmd
;
57 struct drm_gem_object
*gobj
= NULL
;
58 struct bochs_bo
*bo
= NULL
;
61 if (sizes
->surface_bpp
!= 32)
64 mode_cmd
.width
= sizes
->surface_width
;
65 mode_cmd
.height
= sizes
->surface_height
;
66 mode_cmd
.pitches
[0] = sizes
->surface_width
* 4;
67 mode_cmd
.pixel_format
= DRM_FORMAT_HOST_XRGB8888
;
68 size
= mode_cmd
.pitches
[0] * mode_cmd
.height
;
70 /* alloc, pin & map bo */
71 ret
= bochsfb_create_object(bochs
, &mode_cmd
, &gobj
);
73 DRM_ERROR("failed to create fbcon backing object %d\n", ret
);
77 bo
= gem_to_bochs_bo(gobj
);
79 ret
= ttm_bo_reserve(&bo
->bo
, true, false, NULL
);
83 ret
= bochs_bo_pin(bo
, TTM_PL_FLAG_VRAM
, NULL
);
85 DRM_ERROR("failed to pin fbcon\n");
86 ttm_bo_unreserve(&bo
->bo
);
90 ret
= ttm_bo_kmap(&bo
->bo
, 0, bo
->bo
.num_pages
,
93 DRM_ERROR("failed to kmap fbcon\n");
94 ttm_bo_unreserve(&bo
->bo
);
98 ttm_bo_unreserve(&bo
->bo
);
101 info
= drm_fb_helper_alloc_fbi(helper
);
103 DRM_ERROR("Failed to allocate fbi: %ld\n", PTR_ERR(info
));
104 return PTR_ERR(info
);
107 info
->par
= &bochs
->fb
.helper
;
109 fb
= drm_gem_fbdev_fb_create(bochs
->dev
, sizes
, 0, gobj
, NULL
);
111 DRM_ERROR("Failed to create framebuffer: %ld\n", PTR_ERR(fb
));
116 bochs
->fb
.helper
.fb
= fb
;
118 strcpy(info
->fix
.id
, "bochsdrmfb");
120 info
->fbops
= &bochsfb_ops
;
122 drm_fb_helper_fill_fix(info
, fb
->pitches
[0], fb
->format
->depth
);
123 drm_fb_helper_fill_var(info
, &bochs
->fb
.helper
, sizes
->fb_width
,
126 info
->screen_base
= bo
->kmap
.virtual;
127 info
->screen_size
= size
;
129 drm_vma_offset_remove(&bo
->bo
.bdev
->vma_manager
, &bo
->bo
.vma_node
);
130 info
->fix
.smem_start
= 0;
131 info
->fix
.smem_len
= size
;
135 static const struct drm_fb_helper_funcs bochs_fb_helper_funcs
= {
136 .fb_probe
= bochsfb_create
,
139 static struct drm_framebuffer
*
140 bochs_gem_fb_create(struct drm_device
*dev
, struct drm_file
*file
,
141 const struct drm_mode_fb_cmd2
*mode_cmd
)
143 if (mode_cmd
->pixel_format
!= DRM_FORMAT_XRGB8888
&&
144 mode_cmd
->pixel_format
!= DRM_FORMAT_BGRX8888
)
145 return ERR_PTR(-EINVAL
);
147 return drm_gem_fb_create(dev
, file
, mode_cmd
);
150 const struct drm_mode_config_funcs bochs_mode_funcs
= {
151 .fb_create
= bochs_gem_fb_create
,
154 int bochs_fbdev_init(struct bochs_device
*bochs
)
156 return drm_fb_helper_fbdev_setup(bochs
->dev
, &bochs
->fb
.helper
,
157 &bochs_fb_helper_funcs
, 32, 1);
160 void bochs_fbdev_fini(struct bochs_device
*bochs
)
162 drm_fb_helper_fbdev_teardown(bochs
->dev
);