]> git.karo-electronics.de Git - karo-tx-linux.git/blob - drivers/gpu/drm/cirrus/cirrus_main.c
raid1: Add some macros to make code clearly.
[karo-tx-linux.git] / drivers / gpu / drm / cirrus / cirrus_main.c
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
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
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 *
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 */
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 */
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
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
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
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
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
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
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
258 int cirrus_gem_init_object(struct drm_gem_object *obj)
259 {
260         BUG();
261         return 0;
262 }
263
264 void cirrus_bo_unref(struct cirrus_bo **bo)
265 {
266         struct ttm_buffer_object *tbo;
267
268         if ((*bo) == NULL)
269                 return;
270
271         tbo = &((*bo)->bo);
272         ttm_bo_unref(&tbo);
273         if (tbo == NULL)
274                 *bo = NULL;
275
276 }
277
278 void cirrus_gem_free_object(struct drm_gem_object *obj)
279 {
280         struct cirrus_bo *cirrus_bo = gem_to_cirrus_bo(obj);
281
282         if (!cirrus_bo)
283                 return;
284         cirrus_bo_unref(&cirrus_bo);
285 }
286
287
288 static inline u64 cirrus_bo_mmap_offset(struct cirrus_bo *bo)
289 {
290         return drm_vma_node_offset_addr(&bo->bo.vma_node);
291 }
292
293 int
294 cirrus_dumb_mmap_offset(struct drm_file *file,
295                      struct drm_device *dev,
296                      uint32_t handle,
297                      uint64_t *offset)
298 {
299         struct drm_gem_object *obj;
300         int ret;
301         struct cirrus_bo *bo;
302
303         mutex_lock(&dev->struct_mutex);
304         obj = drm_gem_object_lookup(dev, file, handle);
305         if (obj == NULL) {
306                 ret = -ENOENT;
307                 goto out_unlock;
308         }
309
310         bo = gem_to_cirrus_bo(obj);
311         *offset = cirrus_bo_mmap_offset(bo);
312
313         drm_gem_object_unreference(obj);
314         ret = 0;
315 out_unlock:
316         mutex_unlock(&dev->struct_mutex);
317         return ret;
318
319 }