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 struct fb_ops bochsfb_ops
= {
14 .fb_check_var
= drm_fb_helper_check_var
,
15 .fb_set_par
= drm_fb_helper_set_par
,
16 .fb_fillrect
= sys_fillrect
,
17 .fb_copyarea
= sys_copyarea
,
18 .fb_imageblit
= sys_imageblit
,
19 .fb_pan_display
= drm_fb_helper_pan_display
,
20 .fb_blank
= drm_fb_helper_blank
,
21 .fb_setcmap
= drm_fb_helper_setcmap
,
24 static int bochsfb_create_object(struct bochs_device
*bochs
,
25 struct drm_mode_fb_cmd2
*mode_cmd
,
26 struct drm_gem_object
**gobj_p
)
28 struct drm_device
*dev
= bochs
->dev
;
29 struct drm_gem_object
*gobj
;
33 size
= mode_cmd
->pitches
[0] * mode_cmd
->height
;
34 ret
= bochs_gem_create(dev
, size
, true, &gobj
);
42 static int bochsfb_create(struct drm_fb_helper
*helper
,
43 struct drm_fb_helper_surface_size
*sizes
)
45 struct bochs_device
*bochs
=
46 container_of(helper
, struct bochs_device
, fb
.helper
);
47 struct drm_device
*dev
= bochs
->dev
;
49 struct drm_framebuffer
*fb
;
50 struct drm_mode_fb_cmd2 mode_cmd
;
51 struct device
*device
= &dev
->pdev
->dev
;
52 struct drm_gem_object
*gobj
= NULL
;
53 struct bochs_bo
*bo
= NULL
;
56 if (sizes
->surface_bpp
!= 32)
59 mode_cmd
.width
= sizes
->surface_width
;
60 mode_cmd
.height
= sizes
->surface_height
;
61 mode_cmd
.pitches
[0] = mode_cmd
.width
* ((sizes
->surface_bpp
+ 7) / 8);
62 mode_cmd
.pixel_format
= drm_mode_legacy_fb_format(sizes
->surface_bpp
,
63 sizes
->surface_depth
);
64 size
= mode_cmd
.pitches
[0] * mode_cmd
.height
;
66 /* alloc, pin & map bo */
67 ret
= bochsfb_create_object(bochs
, &mode_cmd
, &gobj
);
69 DRM_ERROR("failed to create fbcon backing object %d\n", ret
);
73 bo
= gem_to_bochs_bo(gobj
);
75 ret
= ttm_bo_reserve(&bo
->bo
, true, false, false, 0);
79 ret
= bochs_bo_pin(bo
, TTM_PL_FLAG_VRAM
, NULL
);
81 DRM_ERROR("failed to pin fbcon\n");
82 ttm_bo_unreserve(&bo
->bo
);
86 ret
= ttm_bo_kmap(&bo
->bo
, 0, bo
->bo
.num_pages
,
89 DRM_ERROR("failed to kmap fbcon\n");
90 ttm_bo_unreserve(&bo
->bo
);
94 ttm_bo_unreserve(&bo
->bo
);
97 info
= framebuffer_alloc(0, device
);
101 info
->par
= &bochs
->fb
.helper
;
103 ret
= bochs_framebuffer_init(bochs
->dev
, &bochs
->fb
.gfb
, &mode_cmd
, gobj
);
107 bochs
->fb
.size
= size
;
110 fb
= &bochs
->fb
.gfb
.base
;
111 bochs
->fb
.helper
.fb
= fb
;
112 bochs
->fb
.helper
.fbdev
= info
;
114 strcpy(info
->fix
.id
, "bochsdrmfb");
116 info
->flags
= FBINFO_DEFAULT
;
117 info
->fbops
= &bochsfb_ops
;
119 drm_fb_helper_fill_fix(info
, fb
->pitches
[0], fb
->depth
);
120 drm_fb_helper_fill_var(info
, &bochs
->fb
.helper
, sizes
->fb_width
,
123 info
->screen_base
= bo
->kmap
.virtual;
124 info
->screen_size
= size
;
127 /* FIXME: get this right for mmap(/dev/fb0) */
128 info
->fix
.smem_start
= bochs_bo_mmap_offset(bo
);
129 info
->fix
.smem_len
= size
;
132 ret
= fb_alloc_cmap(&info
->cmap
, 256, 0);
134 DRM_ERROR("%s: can't allocate color map\n", info
->fix
.id
);
141 static int bochs_fbdev_destroy(struct bochs_device
*bochs
)
143 struct bochs_framebuffer
*gfb
= &bochs
->fb
.gfb
;
144 struct fb_info
*info
;
146 DRM_DEBUG_DRIVER("\n");
148 if (bochs
->fb
.helper
.fbdev
) {
149 info
= bochs
->fb
.helper
.fbdev
;
151 unregister_framebuffer(info
);
153 fb_dealloc_cmap(&info
->cmap
);
154 framebuffer_release(info
);
158 drm_gem_object_unreference_unlocked(gfb
->obj
);
162 drm_fb_helper_fini(&bochs
->fb
.helper
);
163 drm_framebuffer_unregister_private(&gfb
->base
);
164 drm_framebuffer_cleanup(&gfb
->base
);
169 void bochs_fb_gamma_set(struct drm_crtc
*crtc
, u16 red
, u16 green
,
174 void bochs_fb_gamma_get(struct drm_crtc
*crtc
, u16
*red
, u16
*green
,
175 u16
*blue
, int regno
)
182 static struct drm_fb_helper_funcs bochs_fb_helper_funcs
= {
183 .gamma_set
= bochs_fb_gamma_set
,
184 .gamma_get
= bochs_fb_gamma_get
,
185 .fb_probe
= bochsfb_create
,
188 int bochs_fbdev_init(struct bochs_device
*bochs
)
192 bochs
->fb
.helper
.funcs
= &bochs_fb_helper_funcs
;
193 spin_lock_init(&bochs
->fb
.dirty_lock
);
195 ret
= drm_fb_helper_init(bochs
->dev
, &bochs
->fb
.helper
,
200 drm_fb_helper_single_add_all_connectors(&bochs
->fb
.helper
);
201 drm_helper_disable_unused_functions(bochs
->dev
);
202 drm_fb_helper_initial_config(&bochs
->fb
.helper
, 32);
204 bochs
->fb
.initialized
= true;
208 void bochs_fbdev_fini(struct bochs_device
*bochs
)
210 if (!bochs
->fb
.initialized
)
213 bochs_fbdev_destroy(bochs
);
214 bochs
->fb
.initialized
= false;