• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2012 Red Hat
3  *
4  * This file is subject to the terms and conditions of the GNU General
5  * Public License version 2. See the file COPYING in the main
6  * directory of this archive for more details.
7  *
8  * Authors: Matthew Garrett
9  *          Dave Airlie
10  */
11 #include <drm/drmP.h>
12 #include <drm/drm_crtc_helper.h>
13 
14 #include "cirrus_drv.h"
15 
16 
cirrus_user_framebuffer_destroy(struct drm_framebuffer * fb)17 static void cirrus_user_framebuffer_destroy(struct drm_framebuffer *fb)
18 {
19 	struct cirrus_framebuffer *cirrus_fb = to_cirrus_framebuffer(fb);
20 	if (cirrus_fb->obj)
21 		drm_gem_object_unreference_unlocked(cirrus_fb->obj);
22 	drm_framebuffer_cleanup(fb);
23 	kfree(fb);
24 }
25 
26 static const struct drm_framebuffer_funcs cirrus_fb_funcs = {
27 	.destroy = cirrus_user_framebuffer_destroy,
28 };
29 
cirrus_framebuffer_init(struct drm_device * dev,struct cirrus_framebuffer * gfb,struct drm_mode_fb_cmd2 * mode_cmd,struct drm_gem_object * obj)30 int cirrus_framebuffer_init(struct drm_device *dev,
31 			    struct cirrus_framebuffer *gfb,
32 			    struct drm_mode_fb_cmd2 *mode_cmd,
33 			    struct drm_gem_object *obj)
34 {
35 	int ret;
36 
37 	drm_helper_mode_fill_fb_struct(&gfb->base, mode_cmd);
38 	gfb->obj = obj;
39 	ret = drm_framebuffer_init(dev, &gfb->base, &cirrus_fb_funcs);
40 	if (ret) {
41 		DRM_ERROR("drm_framebuffer_init failed: %d\n", ret);
42 		return ret;
43 	}
44 	return 0;
45 }
46 
47 static struct drm_framebuffer *
cirrus_user_framebuffer_create(struct drm_device * dev,struct drm_file * filp,struct drm_mode_fb_cmd2 * mode_cmd)48 cirrus_user_framebuffer_create(struct drm_device *dev,
49 			       struct drm_file *filp,
50 			       struct drm_mode_fb_cmd2 *mode_cmd)
51 {
52 	struct drm_gem_object *obj;
53 	struct cirrus_framebuffer *cirrus_fb;
54 	int ret;
55 	u32 bpp, depth;
56 
57 	drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp);
58 	/* cirrus can't handle > 24bpp framebuffers at all */
59 	if (bpp > 24)
60 		return ERR_PTR(-EINVAL);
61 
62 	obj = drm_gem_object_lookup(dev, filp, mode_cmd->handles[0]);
63 	if (obj == NULL)
64 		return ERR_PTR(-ENOENT);
65 
66 	cirrus_fb = kzalloc(sizeof(*cirrus_fb), GFP_KERNEL);
67 	if (!cirrus_fb) {
68 		drm_gem_object_unreference_unlocked(obj);
69 		return ERR_PTR(-ENOMEM);
70 	}
71 
72 	ret = cirrus_framebuffer_init(dev, cirrus_fb, mode_cmd, obj);
73 	if (ret) {
74 		drm_gem_object_unreference_unlocked(obj);
75 		kfree(cirrus_fb);
76 		return ERR_PTR(ret);
77 	}
78 	return &cirrus_fb->base;
79 }
80 
81 static const struct drm_mode_config_funcs cirrus_mode_funcs = {
82 	.fb_create = cirrus_user_framebuffer_create,
83 };
84 
85 /* Unmap the framebuffer from the core and release the memory */
cirrus_vram_fini(struct cirrus_device * cdev)86 static void cirrus_vram_fini(struct cirrus_device *cdev)
87 {
88 	iounmap(cdev->rmmio);
89 	cdev->rmmio = NULL;
90 	if (cdev->mc.vram_base)
91 		release_mem_region(cdev->mc.vram_base, cdev->mc.vram_size);
92 }
93 
94 /* Map the framebuffer from the card and configure the core */
cirrus_vram_init(struct cirrus_device * cdev)95 static int cirrus_vram_init(struct cirrus_device *cdev)
96 {
97 	/* BAR 0 is VRAM */
98 	cdev->mc.vram_base = pci_resource_start(cdev->dev->pdev, 0);
99 	/* We have 4MB of VRAM */
100 	cdev->mc.vram_size = 4 * 1024 * 1024;
101 
102 	if (!request_mem_region(cdev->mc.vram_base, cdev->mc.vram_size,
103 				"cirrusdrmfb_vram")) {
104 		DRM_ERROR("can't reserve VRAM\n");
105 		return -ENXIO;
106 	}
107 
108 	return 0;
109 }
110 
111 /*
112  * Our emulated hardware has two sets of memory. One is video RAM and can
113  * simply be used as a linear framebuffer - the other provides mmio access
114  * to the display registers. The latter can also be accessed via IO port
115  * access, but we map the range and use mmio to program them instead
116  */
117 
cirrus_device_init(struct cirrus_device * cdev,struct drm_device * ddev,struct pci_dev * pdev,uint32_t flags)118 int cirrus_device_init(struct cirrus_device *cdev,
119 		       struct drm_device *ddev,
120 		       struct pci_dev *pdev, uint32_t flags)
121 {
122 	int ret;
123 
124 	cdev->dev = ddev;
125 	cdev->flags = flags;
126 
127 	/* Hardcode the number of CRTCs to 1 */
128 	cdev->num_crtc = 1;
129 
130 	/* BAR 0 is the framebuffer, BAR 1 contains registers */
131 	cdev->rmmio_base = pci_resource_start(cdev->dev->pdev, 1);
132 	cdev->rmmio_size = pci_resource_len(cdev->dev->pdev, 1);
133 
134 	if (!request_mem_region(cdev->rmmio_base, cdev->rmmio_size,
135 				"cirrusdrmfb_mmio")) {
136 		DRM_ERROR("can't reserve mmio registers\n");
137 		return -ENOMEM;
138 	}
139 
140 	cdev->rmmio = ioremap(cdev->rmmio_base, cdev->rmmio_size);
141 
142 	if (cdev->rmmio == NULL)
143 		return -ENOMEM;
144 
145 	ret = cirrus_vram_init(cdev);
146 	if (ret) {
147 		release_mem_region(cdev->rmmio_base, cdev->rmmio_size);
148 		return ret;
149 	}
150 
151 	return 0;
152 }
153 
cirrus_device_fini(struct cirrus_device * cdev)154 void cirrus_device_fini(struct cirrus_device *cdev)
155 {
156 	release_mem_region(cdev->rmmio_base, cdev->rmmio_size);
157 	cirrus_vram_fini(cdev);
158 }
159 
160 /*
161  * Functions here will be called by the core once it's bound the driver to
162  * a PCI device
163  */
164 
cirrus_driver_load(struct drm_device * dev,unsigned long flags)165 int cirrus_driver_load(struct drm_device *dev, unsigned long flags)
166 {
167 	struct cirrus_device *cdev;
168 	int r;
169 
170 	cdev = kzalloc(sizeof(struct cirrus_device), GFP_KERNEL);
171 	if (cdev == NULL)
172 		return -ENOMEM;
173 	dev->dev_private = (void *)cdev;
174 
175 	r = cirrus_device_init(cdev, dev, dev->pdev, flags);
176 	if (r) {
177 		dev_err(&dev->pdev->dev, "Fatal error during GPU init: %d\n", r);
178 		goto out;
179 	}
180 
181 	r = cirrus_mm_init(cdev);
182 	if (r)
183 		dev_err(&dev->pdev->dev, "fatal err on mm init\n");
184 
185 	r = cirrus_modeset_init(cdev);
186 	if (r)
187 		dev_err(&dev->pdev->dev, "Fatal error during modeset init: %d\n", r);
188 
189 	dev->mode_config.funcs = (void *)&cirrus_mode_funcs;
190 out:
191 	if (r)
192 		cirrus_driver_unload(dev);
193 	return r;
194 }
195 
cirrus_driver_unload(struct drm_device * dev)196 int cirrus_driver_unload(struct drm_device *dev)
197 {
198 	struct cirrus_device *cdev = dev->dev_private;
199 
200 	if (cdev == NULL)
201 		return 0;
202 	cirrus_modeset_fini(cdev);
203 	cirrus_mm_fini(cdev);
204 	cirrus_device_fini(cdev);
205 	kfree(cdev);
206 	dev->dev_private = NULL;
207 	return 0;
208 }
209 
cirrus_gem_create(struct drm_device * dev,u32 size,bool iskernel,struct drm_gem_object ** obj)210 int cirrus_gem_create(struct drm_device *dev,
211 		   u32 size, bool iskernel,
212 		   struct drm_gem_object **obj)
213 {
214 	struct cirrus_bo *cirrusbo;
215 	int ret;
216 
217 	*obj = NULL;
218 
219 	size = roundup(size, PAGE_SIZE);
220 	if (size == 0)
221 		return -EINVAL;
222 
223 	ret = cirrus_bo_create(dev, size, 0, 0, &cirrusbo);
224 	if (ret) {
225 		if (ret != -ERESTARTSYS)
226 			DRM_ERROR("failed to allocate GEM object\n");
227 		return ret;
228 	}
229 	*obj = &cirrusbo->gem;
230 	return 0;
231 }
232 
cirrus_dumb_create(struct drm_file * file,struct drm_device * dev,struct drm_mode_create_dumb * args)233 int cirrus_dumb_create(struct drm_file *file,
234 		    struct drm_device *dev,
235 		    struct drm_mode_create_dumb *args)
236 {
237 	int ret;
238 	struct drm_gem_object *gobj;
239 	u32 handle;
240 
241 	args->pitch = args->width * ((args->bpp + 7) / 8);
242 	args->size = args->pitch * args->height;
243 
244 	ret = cirrus_gem_create(dev, args->size, false,
245 			     &gobj);
246 	if (ret)
247 		return ret;
248 
249 	ret = drm_gem_handle_create(file, gobj, &handle);
250 	drm_gem_object_unreference_unlocked(gobj);
251 	if (ret)
252 		return ret;
253 
254 	args->handle = handle;
255 	return 0;
256 }
257 
cirrus_bo_unref(struct cirrus_bo ** bo)258 static void cirrus_bo_unref(struct cirrus_bo **bo)
259 {
260 	struct ttm_buffer_object *tbo;
261 
262 	if ((*bo) == NULL)
263 		return;
264 
265 	tbo = &((*bo)->bo);
266 	ttm_bo_unref(&tbo);
267 	*bo = NULL;
268 }
269 
cirrus_gem_free_object(struct drm_gem_object * obj)270 void cirrus_gem_free_object(struct drm_gem_object *obj)
271 {
272 	struct cirrus_bo *cirrus_bo = gem_to_cirrus_bo(obj);
273 
274 	cirrus_bo_unref(&cirrus_bo);
275 }
276 
277 
cirrus_bo_mmap_offset(struct cirrus_bo * bo)278 static inline u64 cirrus_bo_mmap_offset(struct cirrus_bo *bo)
279 {
280 	return drm_vma_node_offset_addr(&bo->bo.vma_node);
281 }
282 
283 int
cirrus_dumb_mmap_offset(struct drm_file * file,struct drm_device * dev,uint32_t handle,uint64_t * offset)284 cirrus_dumb_mmap_offset(struct drm_file *file,
285 		     struct drm_device *dev,
286 		     uint32_t handle,
287 		     uint64_t *offset)
288 {
289 	struct drm_gem_object *obj;
290 	int ret;
291 	struct cirrus_bo *bo;
292 
293 	mutex_lock(&dev->struct_mutex);
294 	obj = drm_gem_object_lookup(dev, file, handle);
295 	if (obj == NULL) {
296 		ret = -ENOENT;
297 		goto out_unlock;
298 	}
299 
300 	bo = gem_to_cirrus_bo(obj);
301 	*offset = cirrus_bo_mmap_offset(bo);
302 
303 	drm_gem_object_unreference(obj);
304 	ret = 0;
305 out_unlock:
306 	mutex_unlock(&dev->struct_mutex);
307 	return ret;
308 
309 }
310