Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.2.
  1/*
  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.
  6 */
  7
  8#include "bochs.h"
  9
 10/* ---------------------------------------------------------------------- */
 11
 12static int bochsfb_mmap(struct fb_info *info,
 13			struct vm_area_struct *vma)
 14{
 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);
 19
 20	return ttm_fbdev_mmap(vma, &bo->bo);
 21}
 22
 23static struct fb_ops bochsfb_ops = {
 24	.owner = THIS_MODULE,
 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,
 34};
 35
 36static int bochsfb_create_object(struct bochs_device *bochs,
 37				 const struct drm_mode_fb_cmd2 *mode_cmd,
 38				 struct drm_gem_object **gobj_p)
 39{
 40	struct drm_device *dev = bochs->dev;
 41	struct drm_gem_object *gobj;
 42	u32 size;
 43	int ret = 0;
 44
 45	size = mode_cmd->pitches[0] * mode_cmd->height;
 46	ret = bochs_gem_create(dev, size, true, &gobj);
 47	if (ret)
 48		return ret;
 49
 50	*gobj_p = gobj;
 51	return ret;
 52}
 53
 54static int bochsfb_create(struct drm_fb_helper *helper,
 55			  struct drm_fb_helper_surface_size *sizes)
 56{
 57	struct bochs_device *bochs =
 58		container_of(helper, struct bochs_device, fb.helper);
 59	struct fb_info *info;
 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;
 64	int size, ret;
 65
 66	if (sizes->surface_bpp != 32)
 67		return -EINVAL;
 68
 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;
 75
 76	/* alloc, pin & map bo */
 77	ret = bochsfb_create_object(bochs, &mode_cmd, &gobj);
 78	if (ret) {
 79		DRM_ERROR("failed to create fbcon backing object %d\n", ret);
 80		return ret;
 81	}
 82
 83	bo = gem_to_bochs_bo(gobj);
 84
 85	ret = ttm_bo_reserve(&bo->bo, true, false, false, NULL);
 86	if (ret)
 87		return ret;
 88
 89	ret = bochs_bo_pin(bo, TTM_PL_FLAG_VRAM, NULL);
 90	if (ret) {
 91		DRM_ERROR("failed to pin fbcon\n");
 92		ttm_bo_unreserve(&bo->bo);
 93		return ret;
 94	}
 95
 96	ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages,
 97			  &bo->kmap);
 98	if (ret) {
 99		DRM_ERROR("failed to kmap fbcon\n");
100		ttm_bo_unreserve(&bo->bo);
101		return ret;
102	}
103
104	ttm_bo_unreserve(&bo->bo);
105
106	/* init fb device */
107	info = drm_fb_helper_alloc_fbi(helper);
108	if (IS_ERR(info))
109		return PTR_ERR(info);
110
111	info->par = &bochs->fb.helper;
112
113	ret = bochs_framebuffer_init(bochs->dev, &bochs->fb.gfb, &mode_cmd, gobj);
114	if (ret) {
115		drm_fb_helper_release_fbi(helper);
116		return ret;
117	}
118
119	bochs->fb.size = size;
120
121	/* setup helper */
122	fb = &bochs->fb.gfb.base;
123	bochs->fb.helper.fb = fb;
124
125	strcpy(info->fix.id, "bochsdrmfb");
126
127	info->flags = FBINFO_DEFAULT;
128	info->fbops = &bochsfb_ops;
129
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,
132			       sizes->fb_height);
133
134	info->screen_base = bo->kmap.virtual;
135	info->screen_size = size;
136
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;
140
141	return 0;
142}
143
144static int bochs_fbdev_destroy(struct bochs_device *bochs)
145{
146	struct bochs_framebuffer *gfb = &bochs->fb.gfb;
147
148	DRM_DEBUG_DRIVER("\n");
149
150	drm_fb_helper_unregister_fbi(&bochs->fb.helper);
151	drm_fb_helper_release_fbi(&bochs->fb.helper);
152
153	if (gfb->obj) {
154		drm_gem_object_unreference_unlocked(gfb->obj);
155		gfb->obj = NULL;
156	}
157
158	drm_fb_helper_fini(&bochs->fb.helper);
159	drm_framebuffer_unregister_private(&gfb->base);
160	drm_framebuffer_cleanup(&gfb->base);
161
162	return 0;
163}
164
165void bochs_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
166			u16 blue, int regno)
167{
168}
169
170void bochs_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
171			u16 *blue, int regno)
172{
173	*red   = regno;
174	*green = regno;
175	*blue  = regno;
176}
177
178static const struct drm_fb_helper_funcs bochs_fb_helper_funcs = {
179	.gamma_set = bochs_fb_gamma_set,
180	.gamma_get = bochs_fb_gamma_get,
181	.fb_probe = bochsfb_create,
182};
183
184int bochs_fbdev_init(struct bochs_device *bochs)
185{
186	int ret;
187
188	drm_fb_helper_prepare(bochs->dev, &bochs->fb.helper,
189			      &bochs_fb_helper_funcs);
190
191	ret = drm_fb_helper_init(bochs->dev, &bochs->fb.helper,
192				 1, 1);
193	if (ret)
194		return ret;
195
196	ret = drm_fb_helper_single_add_all_connectors(&bochs->fb.helper);
197	if (ret)
198		goto fini;
199
200	drm_helper_disable_unused_functions(bochs->dev);
201
202	ret = drm_fb_helper_initial_config(&bochs->fb.helper, 32);
203	if (ret)
204		goto fini;
205
206	bochs->fb.initialized = true;
207	return 0;
208
209fini:
210	drm_fb_helper_fini(&bochs->fb.helper);
211	return ret;
212}
213
214void bochs_fbdev_fini(struct bochs_device *bochs)
215{
216	if (!bochs->fb.initialized)
217		return;
218
219	bochs_fbdev_destroy(bochs);
220	bochs->fb.initialized = false;
221}