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
= sys_fillrect
,
28 .fb_copyarea
= sys_copyarea
,
29 .fb_imageblit
= 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 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
);
59 struct drm_device
*dev
= bochs
->dev
;
61 struct drm_framebuffer
*fb
;
62 struct drm_mode_fb_cmd2 mode_cmd
;
63 struct device
*device
= &dev
->pdev
->dev
;
64 struct drm_gem_object
*gobj
= NULL
;
65 struct bochs_bo
*bo
= NULL
;
68 if (sizes
->surface_bpp
!= 32)
71 mode_cmd
.width
= sizes
->surface_width
;
72 mode_cmd
.height
= sizes
->surface_height
;
73 mode_cmd
.pitches
[0] = mode_cmd
.width
* ((sizes
->surface_bpp
+ 7) / 8);
74 mode_cmd
.pixel_format
= drm_mode_legacy_fb_format(sizes
->surface_bpp
,
75 sizes
->surface_depth
);
76 size
= mode_cmd
.pitches
[0] * mode_cmd
.height
;
78 /* alloc, pin & map bo */
79 ret
= bochsfb_create_object(bochs
, &mode_cmd
, &gobj
);
81 DRM_ERROR("failed to create fbcon backing object %d\n", ret
);
85 bo
= gem_to_bochs_bo(gobj
);
87 ret
= ttm_bo_reserve(&bo
->bo
, true, false, false, NULL
);
91 ret
= bochs_bo_pin(bo
, TTM_PL_FLAG_VRAM
, NULL
);
93 DRM_ERROR("failed to pin fbcon\n");
94 ttm_bo_unreserve(&bo
->bo
);
98 ret
= ttm_bo_kmap(&bo
->bo
, 0, bo
->bo
.num_pages
,
101 DRM_ERROR("failed to kmap fbcon\n");
102 ttm_bo_unreserve(&bo
->bo
);
106 ttm_bo_unreserve(&bo
->bo
);
109 info
= framebuffer_alloc(0, device
);
113 info
->par
= &bochs
->fb
.helper
;
115 ret
= bochs_framebuffer_init(bochs
->dev
, &bochs
->fb
.gfb
, &mode_cmd
, gobj
);
119 bochs
->fb
.size
= size
;
122 fb
= &bochs
->fb
.gfb
.base
;
123 bochs
->fb
.helper
.fb
= fb
;
124 bochs
->fb
.helper
.fbdev
= info
;
126 strcpy(info
->fix
.id
, "bochsdrmfb");
128 info
->flags
= FBINFO_DEFAULT
;
129 info
->fbops
= &bochsfb_ops
;
131 drm_fb_helper_fill_fix(info
, fb
->pitches
[0], fb
->depth
);
132 drm_fb_helper_fill_var(info
, &bochs
->fb
.helper
, sizes
->fb_width
,
135 info
->screen_base
= bo
->kmap
.virtual;
136 info
->screen_size
= size
;
138 drm_vma_offset_remove(&bo
->bo
.bdev
->vma_manager
, &bo
->bo
.vma_node
);
139 info
->fix
.smem_start
= 0;
140 info
->fix
.smem_len
= size
;
142 ret
= fb_alloc_cmap(&info
->cmap
, 256, 0);
144 DRM_ERROR("%s: can't allocate color map\n", info
->fix
.id
);
151 static int bochs_fbdev_destroy(struct bochs_device
*bochs
)
153 struct bochs_framebuffer
*gfb
= &bochs
->fb
.gfb
;
154 struct fb_info
*info
;
156 DRM_DEBUG_DRIVER("\n");
158 if (bochs
->fb
.helper
.fbdev
) {
159 info
= bochs
->fb
.helper
.fbdev
;
161 unregister_framebuffer(info
);
163 fb_dealloc_cmap(&info
->cmap
);
164 framebuffer_release(info
);
168 drm_gem_object_unreference_unlocked(gfb
->obj
);
172 drm_fb_helper_fini(&bochs
->fb
.helper
);
173 drm_framebuffer_unregister_private(&gfb
->base
);
174 drm_framebuffer_cleanup(&gfb
->base
);
179 void bochs_fb_gamma_set(struct drm_crtc
*crtc
, u16 red
, u16 green
,
184 void bochs_fb_gamma_get(struct drm_crtc
*crtc
, u16
*red
, u16
*green
,
185 u16
*blue
, int regno
)
192 static const struct drm_fb_helper_funcs bochs_fb_helper_funcs
= {
193 .gamma_set
= bochs_fb_gamma_set
,
194 .gamma_get
= bochs_fb_gamma_get
,
195 .fb_probe
= bochsfb_create
,
198 int bochs_fbdev_init(struct bochs_device
*bochs
)
202 drm_fb_helper_prepare(bochs
->dev
, &bochs
->fb
.helper
,
203 &bochs_fb_helper_funcs
);
205 ret
= drm_fb_helper_init(bochs
->dev
, &bochs
->fb
.helper
,
210 ret
= drm_fb_helper_single_add_all_connectors(&bochs
->fb
.helper
);
214 drm_helper_disable_unused_functions(bochs
->dev
);
216 ret
= drm_fb_helper_initial_config(&bochs
->fb
.helper
, 32);
220 bochs
->fb
.initialized
= true;
224 drm_fb_helper_fini(&bochs
->fb
.helper
);
228 void bochs_fbdev_fini(struct bochs_device
*bochs
)
230 if (!bochs
->fb
.initialized
)
233 bochs_fbdev_destroy(bochs
);
234 bochs
->fb
.initialized
= false;