aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/cirrus
diff options
context:
space:
mode:
authorDave Airlie <airlied@redhat.com>2012-04-17 09:12:29 -0400
committerDave Airlie <airlied@redhat.com>2012-05-17 06:02:24 -0400
commitf9aa76a85248565ff13dc0e10633c4343a059f71 (patch)
tree23cb9a78412f33af72bea500c2027bb3d6706f1f /drivers/gpu/drm/cirrus
parent414c453106255b11df77ed6b08eedb6d2369c338 (diff)
drm/kms: driver for virtual cirrus under qemu
This is the initial driver for emulated cirrus GPU found in qemu. This driver only supports the emulated GPU and doesn't attempt to bind to any real cirrus GPUs. This driver is intended to be used with xf86-video-modesetting in userspace. It requires at least version 0.3.0 This follow the same design as ast and mgag200, and is based on work done by Matthew Garrett previously. This GPU has no hw cursor, and it can't scanout 32-bpp, only packed 24-bpp. i.e. it sucks. Reviewed-by: Adam Jackson <ajax@redhat.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/cirrus')
-rw-r--r--drivers/gpu/drm/cirrus/Kconfig11
-rw-r--r--drivers/gpu/drm/cirrus/Makefile5
-rw-r--r--drivers/gpu/drm/cirrus/cirrus_drv.c106
-rw-r--r--drivers/gpu/drm/cirrus/cirrus_drv.h246
-rw-r--r--drivers/gpu/drm/cirrus/cirrus_fbdev.c307
-rw-r--r--drivers/gpu/drm/cirrus/cirrus_main.c335
-rw-r--r--drivers/gpu/drm/cirrus/cirrus_mode.c629
-rw-r--r--drivers/gpu/drm/cirrus/cirrus_ttm.c453
8 files changed, 2092 insertions, 0 deletions
diff --git a/drivers/gpu/drm/cirrus/Kconfig b/drivers/gpu/drm/cirrus/Kconfig
new file mode 100644
index 000000000000..0303257ca136
--- /dev/null
+++ b/drivers/gpu/drm/cirrus/Kconfig
@@ -0,0 +1,11 @@
1config DRM_CIRRUS_QEMU
2 tristate "Cirrus driver for QEMU emulated device"
3 depends on DRM && PCI && EXPERIMENTAL
4 select FB_CFB_FILLRECT
5 select FB_CFB_COPYAREA
6 select FB_CFB_IMAGEBLIT
7 select DRM_KMS_HELPER
8 help
9 This is a KMS driver for emulated cirrus device in qemu.
10 It is *NOT* intended for real cirrus devices. This requires
11 the modesetting userspace X.org driver.
diff --git a/drivers/gpu/drm/cirrus/Makefile b/drivers/gpu/drm/cirrus/Makefile
new file mode 100644
index 000000000000..69ffe7006d55
--- /dev/null
+++ b/drivers/gpu/drm/cirrus/Makefile
@@ -0,0 +1,5 @@
1ccflags-y := -Iinclude/drm
2cirrus-y := cirrus_main.o cirrus_mode.o \
3 cirrus_drv.o cirrus_fbdev.o cirrus_ttm.o
4
5obj-$(CONFIG_DRM_CIRRUS_QEMU) += cirrus.o
diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.c b/drivers/gpu/drm/cirrus/cirrus_drv.c
new file mode 100644
index 000000000000..2e1f925b5caf
--- /dev/null
+++ b/drivers/gpu/drm/cirrus/cirrus_drv.c
@@ -0,0 +1,106 @@
1/*
2 * Copyright 2012 Red Hat <mjg@redhat.com>
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 <linux/module.h>
12#include <linux/console.h>
13#include "drmP.h"
14#include "drm.h"
15
16#include "cirrus_drv.h"
17
18int cirrus_modeset = -1;
19
20MODULE_PARM_DESC(modeset, "Disable/Enable modesetting");
21module_param_named(modeset, cirrus_modeset, int, 0400);
22
23/*
24 * This is the generic driver code. This binds the driver to the drm core,
25 * which then performs further device association and calls our graphics init
26 * functions
27 */
28
29static struct drm_driver driver;
30
31/* only bind to the cirrus chip in qemu */
32static DEFINE_PCI_DEVICE_TABLE(pciidlist) = {
33 { PCI_VENDOR_ID_CIRRUS, PCI_DEVICE_ID_CIRRUS_5446, 0x1af4, 0x1100, 0,
34 0, 0 },
35 {0,}
36};
37
38static int __devinit
39cirrus_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
40{
41 return drm_get_pci_dev(pdev, ent, &driver);
42}
43
44static void cirrus_pci_remove(struct pci_dev *pdev)
45{
46 struct drm_device *dev = pci_get_drvdata(pdev);
47
48 drm_put_dev(dev);
49}
50
51static const struct file_operations cirrus_driver_fops = {
52 .owner = THIS_MODULE,
53 .open = drm_open,
54 .release = drm_release,
55 .unlocked_ioctl = drm_ioctl,
56 .mmap = cirrus_mmap,
57 .poll = drm_poll,
58 .fasync = drm_fasync,
59};
60static struct drm_driver driver = {
61 .driver_features = DRIVER_MODESET | DRIVER_GEM | DRIVER_USE_MTRR,
62 .load = cirrus_driver_load,
63 .unload = cirrus_driver_unload,
64 .fops = &cirrus_driver_fops,
65 .name = DRIVER_NAME,
66 .desc = DRIVER_DESC,
67 .date = DRIVER_DATE,
68 .major = DRIVER_MAJOR,
69 .minor = DRIVER_MINOR,
70 .patchlevel = DRIVER_PATCHLEVEL,
71 .gem_init_object = cirrus_gem_init_object,
72 .gem_free_object = cirrus_gem_free_object,
73 .dumb_create = cirrus_dumb_create,
74 .dumb_map_offset = cirrus_dumb_mmap_offset,
75 .dumb_destroy = cirrus_dumb_destroy,
76};
77
78static struct pci_driver cirrus_pci_driver = {
79 .name = DRIVER_NAME,
80 .id_table = pciidlist,
81 .probe = cirrus_pci_probe,
82 .remove = cirrus_pci_remove,
83};
84
85static int __init cirrus_init(void)
86{
87 if (vgacon_text_force() && cirrus_modeset == -1)
88 return -EINVAL;
89
90 if (cirrus_modeset == 0)
91 return -EINVAL;
92 return drm_pci_init(&driver, &cirrus_pci_driver);
93}
94
95static void __exit cirrus_exit(void)
96{
97 drm_pci_exit(&driver, &cirrus_pci_driver);
98}
99
100module_init(cirrus_init);
101module_exit(cirrus_exit);
102
103MODULE_DEVICE_TABLE(pci, pciidlist);
104MODULE_AUTHOR(DRIVER_AUTHOR);
105MODULE_DESCRIPTION(DRIVER_DESC);
106MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/cirrus/cirrus_drv.h b/drivers/gpu/drm/cirrus/cirrus_drv.h
new file mode 100644
index 000000000000..21bdfa8836f7
--- /dev/null
+++ b/drivers/gpu/drm/cirrus/cirrus_drv.h
@@ -0,0 +1,246 @@
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#ifndef __CIRRUS_DRV_H__
12#define __CIRRUS_DRV_H__
13
14#include <video/vga.h>
15
16#include <drm/drm_fb_helper.h>
17
18#include "ttm/ttm_bo_api.h"
19#include "ttm/ttm_bo_driver.h"
20#include "ttm/ttm_placement.h"
21#include "ttm/ttm_memory.h"
22#include "ttm/ttm_module.h"
23
24#define DRIVER_AUTHOR "Matthew Garrett"
25
26#define DRIVER_NAME "cirrus"
27#define DRIVER_DESC "qemu Cirrus emulation"
28#define DRIVER_DATE "20110418"
29
30#define DRIVER_MAJOR 1
31#define DRIVER_MINOR 0
32#define DRIVER_PATCHLEVEL 0
33
34#define CIRRUSFB_CONN_LIMIT 1
35
36#define RREG8(reg) ioread8(((void __iomem *)cdev->rmmio) + (reg))
37#define WREG8(reg, v) iowrite8(v, ((void __iomem *)cdev->rmmio) + (reg))
38#define RREG32(reg) ioread32(((void __iomem *)cdev->rmmio) + (reg))
39#define WREG32(reg, v) iowrite32(v, ((void __iomem *)cdev->rmmio) + (reg))
40
41#define SEQ_INDEX 4
42#define SEQ_DATA 5
43
44#define WREG_SEQ(reg, v) \
45 do { \
46 WREG8(SEQ_INDEX, reg); \
47 WREG8(SEQ_DATA, v); \
48 } while (0) \
49
50#define CRT_INDEX 0x14
51#define CRT_DATA 0x15
52
53#define WREG_CRT(reg, v) \
54 do { \
55 WREG8(CRT_INDEX, reg); \
56 WREG8(CRT_DATA, v); \
57 } while (0) \
58
59#define GFX_INDEX 0xe
60#define GFX_DATA 0xf
61
62#define WREG_GFX(reg, v) \
63 do { \
64 WREG8(GFX_INDEX, reg); \
65 WREG8(GFX_DATA, v); \
66 } while (0) \
67
68/*
69 * Cirrus has a "hidden" DAC register that can be accessed by writing to
70 * the pixel mask register to reset the state, then reading from the register
71 * four times. The next write will then pass to the DAC
72 */
73#define VGA_DAC_MASK 0x6
74
75#define WREG_HDR(v) \
76 do { \
77 RREG8(VGA_DAC_MASK); \
78 RREG8(VGA_DAC_MASK); \
79 RREG8(VGA_DAC_MASK); \
80 RREG8(VGA_DAC_MASK); \
81 WREG8(VGA_DAC_MASK, v); \
82 } while (0) \
83
84
85#define CIRRUS_MAX_FB_HEIGHT 4096
86#define CIRRUS_MAX_FB_WIDTH 4096
87
88#define CIRRUS_DPMS_CLEARED (-1)
89
90#define to_cirrus_crtc(x) container_of(x, struct cirrus_crtc, base)
91#define to_cirrus_encoder(x) container_of(x, struct cirrus_encoder, base)
92#define to_cirrus_framebuffer(x) container_of(x, struct cirrus_framebuffer, base)
93
94struct cirrus_crtc {
95 struct drm_crtc base;
96 u8 lut_r[256], lut_g[256], lut_b[256];
97 int last_dpms;
98 bool enabled;
99};
100
101struct cirrus_fbdev;
102struct cirrus_mode_info {
103 bool mode_config_initialized;
104 struct cirrus_crtc *crtc;
105 /* pointer to fbdev info structure */
106 struct cirrus_fbdev *gfbdev;
107};
108
109struct cirrus_encoder {
110 struct drm_encoder base;
111 int last_dpms;
112};
113
114struct cirrus_connector {
115 struct drm_connector base;
116};
117
118struct cirrus_framebuffer {
119 struct drm_framebuffer base;
120 struct drm_gem_object *obj;
121};
122
123struct cirrus_mc {
124 resource_size_t vram_size;
125 resource_size_t vram_base;
126};
127
128struct cirrus_device {
129 struct drm_device *dev;
130 unsigned long flags;
131
132 resource_size_t rmmio_base;
133 resource_size_t rmmio_size;
134 void __iomem *rmmio;
135
136 struct cirrus_mc mc;
137 struct cirrus_mode_info mode_info;
138
139 int num_crtc;
140 int fb_mtrr;
141
142 struct {
143 struct drm_global_reference mem_global_ref;
144 struct ttm_bo_global_ref bo_global_ref;
145 struct ttm_bo_device bdev;
146 atomic_t validate_sequence;
147 } ttm;
148
149};
150
151
152struct cirrus_fbdev {
153 struct drm_fb_helper helper;
154 struct cirrus_framebuffer gfb;
155 struct list_head fbdev_list;
156 void *sysram;
157 int size;
158};
159
160struct cirrus_bo {
161 struct ttm_buffer_object bo;
162 struct ttm_placement placement;
163 struct ttm_bo_kmap_obj kmap;
164 struct drm_gem_object gem;
165 u32 placements[3];
166 int pin_count;
167};
168#define gem_to_cirrus_bo(gobj) container_of((gobj), struct cirrus_bo, gem)
169
170static inline struct cirrus_bo *
171cirrus_bo(struct ttm_buffer_object *bo)
172{
173 return container_of(bo, struct cirrus_bo, bo);
174}
175
176
177#define to_cirrus_obj(x) container_of(x, struct cirrus_gem_object, base)
178#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
179
180 /* cirrus_mode.c */
181void cirrus_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
182 u16 blue, int regno);
183void cirrus_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
184 u16 *blue, int regno);
185
186
187 /* cirrus_main.c */
188int cirrus_device_init(struct cirrus_device *cdev,
189 struct drm_device *ddev,
190 struct pci_dev *pdev,
191 uint32_t flags);
192void cirrus_device_fini(struct cirrus_device *cdev);
193int cirrus_gem_init_object(struct drm_gem_object *obj);
194void cirrus_gem_free_object(struct drm_gem_object *obj);
195int cirrus_dumb_mmap_offset(struct drm_file *file,
196 struct drm_device *dev,
197 uint32_t handle,
198 uint64_t *offset);
199int cirrus_gem_create(struct drm_device *dev,
200 u32 size, bool iskernel,
201 struct drm_gem_object **obj);
202int cirrus_dumb_create(struct drm_file *file,
203 struct drm_device *dev,
204 struct drm_mode_create_dumb *args);
205int cirrus_dumb_destroy(struct drm_file *file,
206 struct drm_device *dev,
207 uint32_t handle);
208
209int cirrus_framebuffer_init(struct drm_device *dev,
210 struct cirrus_framebuffer *gfb,
211 struct drm_mode_fb_cmd2 *mode_cmd,
212 struct drm_gem_object *obj);
213
214 /* cirrus_display.c */
215int cirrus_modeset_init(struct cirrus_device *cdev);
216void cirrus_modeset_fini(struct cirrus_device *cdev);
217
218 /* cirrus_fbdev.c */
219int cirrus_fbdev_init(struct cirrus_device *cdev);
220void cirrus_fbdev_fini(struct cirrus_device *cdev);
221
222
223
224 /* cirrus_irq.c */
225void cirrus_driver_irq_preinstall(struct drm_device *dev);
226int cirrus_driver_irq_postinstall(struct drm_device *dev);
227void cirrus_driver_irq_uninstall(struct drm_device *dev);
228irqreturn_t cirrus_driver_irq_handler(DRM_IRQ_ARGS);
229
230 /* cirrus_kms.c */
231int cirrus_driver_load(struct drm_device *dev, unsigned long flags);
232int cirrus_driver_unload(struct drm_device *dev);
233extern struct drm_ioctl_desc cirrus_ioctls[];
234extern int cirrus_max_ioctl;
235
236int cirrus_mm_init(struct cirrus_device *cirrus);
237void cirrus_mm_fini(struct cirrus_device *cirrus);
238void cirrus_ttm_placement(struct cirrus_bo *bo, int domain);
239int cirrus_bo_create(struct drm_device *dev, int size, int align,
240 uint32_t flags, struct cirrus_bo **pcirrusbo);
241int cirrus_mmap(struct file *filp, struct vm_area_struct *vma);
242int cirrus_bo_reserve(struct cirrus_bo *bo, bool no_wait);
243void cirrus_bo_unreserve(struct cirrus_bo *bo);
244int cirrus_bo_push_sysram(struct cirrus_bo *bo);
245int cirrus_bo_pin(struct cirrus_bo *bo, u32 pl_flag, u64 *gpu_addr);
246#endif /* __CIRRUS_DRV_H__ */
diff --git a/drivers/gpu/drm/cirrus/cirrus_fbdev.c b/drivers/gpu/drm/cirrus/cirrus_fbdev.c
new file mode 100644
index 000000000000..9a276a536992
--- /dev/null
+++ b/drivers/gpu/drm/cirrus/cirrus_fbdev.c
@@ -0,0 +1,307 @@
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 <linux/module.h>
12#include "drmP.h"
13#include "drm.h"
14#include "drm_fb_helper.h"
15
16#include <linux/fb.h>
17
18#include "cirrus_drv.h"
19
20static void cirrus_dirty_update(struct cirrus_fbdev *afbdev,
21 int x, int y, int width, int height)
22{
23 int i;
24 struct drm_gem_object *obj;
25 struct cirrus_bo *bo;
26 int src_offset, dst_offset;
27 int bpp = (afbdev->gfb.base.bits_per_pixel + 7)/8;
28 int ret;
29 bool unmap = false;
30
31 obj = afbdev->gfb.obj;
32 bo = gem_to_cirrus_bo(obj);
33
34 ret = cirrus_bo_reserve(bo, true);
35 if (ret) {
36 DRM_ERROR("failed to reserve fb bo\n");
37 return;
38 }
39
40 if (!bo->kmap.virtual) {
41 ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap);
42 if (ret) {
43 DRM_ERROR("failed to kmap fb updates\n");
44 cirrus_bo_unreserve(bo);
45 return;
46 }
47 unmap = true;
48 }
49 for (i = y; i < y + height; i++) {
50 /* assume equal stride for now */
51 src_offset = dst_offset = i * afbdev->gfb.base.pitches[0] + (x * bpp);
52 memcpy_toio(bo->kmap.virtual + src_offset, afbdev->sysram + src_offset, width * bpp);
53
54 }
55 if (unmap)
56 ttm_bo_kunmap(&bo->kmap);
57
58 cirrus_bo_unreserve(bo);
59}
60
61static void cirrus_fillrect(struct fb_info *info,
62 const struct fb_fillrect *rect)
63{
64 struct cirrus_fbdev *afbdev = info->par;
65 sys_fillrect(info, rect);
66 cirrus_dirty_update(afbdev, rect->dx, rect->dy, rect->width,
67 rect->height);
68}
69
70static void cirrus_copyarea(struct fb_info *info,
71 const struct fb_copyarea *area)
72{
73 struct cirrus_fbdev *afbdev = info->par;
74 sys_copyarea(info, area);
75 cirrus_dirty_update(afbdev, area->dx, area->dy, area->width,
76 area->height);
77}
78
79static void cirrus_imageblit(struct fb_info *info,
80 const struct fb_image *image)
81{
82 struct cirrus_fbdev *afbdev = info->par;
83 sys_imageblit(info, image);
84 cirrus_dirty_update(afbdev, image->dx, image->dy, image->width,
85 image->height);
86}
87
88
89static struct fb_ops cirrusfb_ops = {
90 .owner = THIS_MODULE,
91 .fb_check_var = drm_fb_helper_check_var,
92 .fb_set_par = drm_fb_helper_set_par,
93 .fb_fillrect = cirrus_fillrect,
94 .fb_copyarea = cirrus_copyarea,
95 .fb_imageblit = cirrus_imageblit,
96 .fb_pan_display = drm_fb_helper_pan_display,
97 .fb_blank = drm_fb_helper_blank,
98 .fb_setcmap = drm_fb_helper_setcmap,
99};
100
101static int cirrusfb_create_object(struct cirrus_fbdev *afbdev,
102 struct drm_mode_fb_cmd2 *mode_cmd,
103 struct drm_gem_object **gobj_p)
104{
105 struct drm_device *dev = afbdev->helper.dev;
106 u32 bpp, depth;
107 u32 size;
108 struct drm_gem_object *gobj;
109
110 int ret = 0;
111 drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp);
112
113 if (bpp > 24)
114 return -EINVAL;
115 size = mode_cmd->pitches[0] * mode_cmd->height;
116 ret = cirrus_gem_create(dev, size, true, &gobj);
117 if (ret)
118 return ret;
119
120 *gobj_p = gobj;
121 return ret;
122}
123
124static int cirrusfb_create(struct cirrus_fbdev *gfbdev,
125 struct drm_fb_helper_surface_size *sizes)
126{
127 struct drm_device *dev = gfbdev->helper.dev;
128 struct cirrus_device *cdev = gfbdev->helper.dev->dev_private;
129 struct fb_info *info;
130 struct drm_framebuffer *fb;
131 struct drm_mode_fb_cmd2 mode_cmd;
132 struct device *device = &dev->pdev->dev;
133 void *sysram;
134 struct drm_gem_object *gobj = NULL;
135 struct cirrus_bo *bo = NULL;
136 int size, ret;
137
138 mode_cmd.width = sizes->surface_width;
139 mode_cmd.height = sizes->surface_height;
140 mode_cmd.pitches[0] = mode_cmd.width * ((sizes->surface_bpp + 7) / 8);
141 mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
142 sizes->surface_depth);
143 size = mode_cmd.pitches[0] * mode_cmd.height;
144
145 ret = cirrusfb_create_object(gfbdev, &mode_cmd, &gobj);
146 if (ret) {
147 DRM_ERROR("failed to create fbcon backing object %d\n", ret);
148 return ret;
149 }
150
151 bo = gem_to_cirrus_bo(gobj);
152
153 sysram = vmalloc(size);
154 if (!sysram)
155 return -ENOMEM;
156
157 info = framebuffer_alloc(0, device);
158 if (info == NULL)
159 return -ENOMEM;
160
161 info->par = gfbdev;
162
163 ret = cirrus_framebuffer_init(cdev->dev, &gfbdev->gfb, &mode_cmd, gobj);
164 if (ret)
165 return ret;
166
167 gfbdev->sysram = sysram;
168 gfbdev->size = size;
169
170 fb = &gfbdev->gfb.base;
171 if (!fb) {
172 DRM_INFO("fb is NULL\n");
173 return -EINVAL;
174 }
175
176 /* setup helper */
177 gfbdev->helper.fb = fb;
178 gfbdev->helper.fbdev = info;
179
180 strcpy(info->fix.id, "cirrusdrmfb");
181
182
183 info->flags = FBINFO_DEFAULT;
184 info->fbops = &cirrusfb_ops;
185
186 drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth);
187 drm_fb_helper_fill_var(info, &gfbdev->helper, sizes->fb_width,
188 sizes->fb_height);
189
190 /* setup aperture base/size for vesafb takeover */
191 info->apertures = alloc_apertures(1);
192 if (!info->apertures) {
193 ret = -ENOMEM;
194 goto out_iounmap;
195 }
196 info->apertures->ranges[0].base = cdev->dev->mode_config.fb_base;
197 info->apertures->ranges[0].size = cdev->mc.vram_size;
198
199 info->screen_base = sysram;
200 info->screen_size = size;
201
202 info->fix.mmio_start = 0;
203 info->fix.mmio_len = 0;
204
205 ret = fb_alloc_cmap(&info->cmap, 256, 0);
206 if (ret) {
207 DRM_ERROR("%s: can't allocate color map\n", info->fix.id);
208 ret = -ENOMEM;
209 goto out_iounmap;
210 }
211
212 DRM_INFO("fb mappable at 0x%lX\n", info->fix.smem_start);
213 DRM_INFO("vram aper at 0x%lX\n", (unsigned long)info->fix.smem_start);
214 DRM_INFO("size %lu\n", (unsigned long)info->fix.smem_len);
215 DRM_INFO("fb depth is %d\n", fb->depth);
216 DRM_INFO(" pitch is %d\n", fb->pitches[0]);
217
218 return 0;
219out_iounmap:
220 return ret;
221}
222
223static int cirrus_fb_find_or_create_single(struct drm_fb_helper *helper,
224 struct drm_fb_helper_surface_size
225 *sizes)
226{
227 struct cirrus_fbdev *gfbdev = (struct cirrus_fbdev *)helper;
228 int new_fb = 0;
229 int ret;
230
231 if (!helper->fb) {
232 ret = cirrusfb_create(gfbdev, sizes);
233 if (ret)
234 return ret;
235 new_fb = 1;
236 }
237 return new_fb;
238}
239
240static int cirrus_fbdev_destroy(struct drm_device *dev,
241 struct cirrus_fbdev *gfbdev)
242{
243 struct fb_info *info;
244 struct cirrus_framebuffer *gfb = &gfbdev->gfb;
245
246 if (gfbdev->helper.fbdev) {
247 info = gfbdev->helper.fbdev;
248
249 unregister_framebuffer(info);
250 if (info->cmap.len)
251 fb_dealloc_cmap(&info->cmap);
252 framebuffer_release(info);
253 }
254
255 if (gfb->obj) {
256 drm_gem_object_unreference_unlocked(gfb->obj);
257 gfb->obj = NULL;
258 }
259
260 vfree(gfbdev->sysram);
261 drm_fb_helper_fini(&gfbdev->helper);
262 drm_framebuffer_cleanup(&gfb->base);
263
264 return 0;
265}
266
267static struct drm_fb_helper_funcs cirrus_fb_helper_funcs = {
268 .gamma_set = cirrus_crtc_fb_gamma_set,
269 .gamma_get = cirrus_crtc_fb_gamma_get,
270 .fb_probe = cirrus_fb_find_or_create_single,
271};
272
273int cirrus_fbdev_init(struct cirrus_device *cdev)
274{
275 struct cirrus_fbdev *gfbdev;
276 int ret;
277 int bpp_sel = 24;
278
279 /*bpp_sel = 8;*/
280 gfbdev = kzalloc(sizeof(struct cirrus_fbdev), GFP_KERNEL);
281 if (!gfbdev)
282 return -ENOMEM;
283
284 cdev->mode_info.gfbdev = gfbdev;
285 gfbdev->helper.funcs = &cirrus_fb_helper_funcs;
286
287 ret = drm_fb_helper_init(cdev->dev, &gfbdev->helper,
288 cdev->num_crtc, CIRRUSFB_CONN_LIMIT);
289 if (ret) {
290 kfree(gfbdev);
291 return ret;
292 }
293 drm_fb_helper_single_add_all_connectors(&gfbdev->helper);
294 drm_fb_helper_initial_config(&gfbdev->helper, bpp_sel);
295
296 return 0;
297}
298
299void cirrus_fbdev_fini(struct cirrus_device *cdev)
300{
301 if (!cdev->mode_info.gfbdev)
302 return;
303
304 cirrus_fbdev_destroy(cdev->dev, cdev->mode_info.gfbdev);
305 kfree(cdev->mode_info.gfbdev);
306 cdev->mode_info.gfbdev = NULL;
307}
diff --git a/drivers/gpu/drm/cirrus/cirrus_main.c b/drivers/gpu/drm/cirrus/cirrus_main.c
new file mode 100644
index 000000000000..e3c122578417
--- /dev/null
+++ b/drivers/gpu/drm/cirrus/cirrus_main.c
@@ -0,0 +1,335 @@
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 "drmP.h"
12#include "drm.h"
13#include "drm_crtc_helper.h"
14
15#include "cirrus_drv.h"
16
17
18static void cirrus_user_framebuffer_destroy(struct drm_framebuffer *fb)
19{
20 struct cirrus_framebuffer *cirrus_fb = to_cirrus_framebuffer(fb);
21 if (cirrus_fb->obj)
22 drm_gem_object_unreference_unlocked(cirrus_fb->obj);
23 drm_framebuffer_cleanup(fb);
24 kfree(fb);
25}
26
27static int cirrus_user_framebuffer_create_handle(struct drm_framebuffer *fb,
28 struct drm_file *file_priv,
29 unsigned int *handle)
30{
31 return 0;
32}
33
34static const struct drm_framebuffer_funcs cirrus_fb_funcs = {
35 .destroy = cirrus_user_framebuffer_destroy,
36 .create_handle = cirrus_user_framebuffer_create_handle,
37};
38
39int cirrus_framebuffer_init(struct drm_device *dev,
40 struct cirrus_framebuffer *gfb,
41 struct drm_mode_fb_cmd2 *mode_cmd,
42 struct drm_gem_object *obj)
43{
44 int ret;
45
46 ret = drm_framebuffer_init(dev, &gfb->base, &cirrus_fb_funcs);
47 if (ret) {
48 DRM_ERROR("drm_framebuffer_init failed: %d\n", ret);
49 return ret;
50 }
51 drm_helper_mode_fill_fb_struct(&gfb->base, mode_cmd);
52 gfb->obj = obj;
53 return 0;
54}
55
56static struct drm_framebuffer *
57cirrus_user_framebuffer_create(struct drm_device *dev,
58 struct drm_file *filp,
59 struct drm_mode_fb_cmd2 *mode_cmd)
60{
61 struct drm_gem_object *obj;
62 struct cirrus_framebuffer *cirrus_fb;
63 int ret;
64 u32 bpp, depth;
65
66 drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp);
67 /* cirrus can't handle > 24bpp framebuffers at all */
68 if (bpp > 24)
69 return ERR_PTR(-EINVAL);
70
71 obj = drm_gem_object_lookup(dev, filp, mode_cmd->handles[0]);
72 if (obj == NULL)
73 return ERR_PTR(-ENOENT);
74
75 cirrus_fb = kzalloc(sizeof(*cirrus_fb), GFP_KERNEL);
76 if (!cirrus_fb) {
77 drm_gem_object_unreference_unlocked(obj);
78 return ERR_PTR(-ENOMEM);
79 }
80
81 ret = cirrus_framebuffer_init(dev, cirrus_fb, mode_cmd, obj);
82 if (ret) {
83 drm_gem_object_unreference_unlocked(obj);
84 kfree(cirrus_fb);
85 return ERR_PTR(ret);
86 }
87 return &cirrus_fb->base;
88}
89
90static const struct drm_mode_config_funcs cirrus_mode_funcs = {
91 .fb_create = cirrus_user_framebuffer_create,
92};
93
94/* Unmap the framebuffer from the core and release the memory */
95static void cirrus_vram_fini(struct cirrus_device *cdev)
96{
97 iounmap(cdev->rmmio);
98 cdev->rmmio = NULL;
99 if (cdev->mc.vram_base)
100 release_mem_region(cdev->mc.vram_base, cdev->mc.vram_size);
101}
102
103/* Map the framebuffer from the card and configure the core */
104static int cirrus_vram_init(struct cirrus_device *cdev)
105{
106 /* BAR 0 is VRAM */
107 cdev->mc.vram_base = pci_resource_start(cdev->dev->pdev, 0);
108 /* We have 4MB of VRAM */
109 cdev->mc.vram_size = 4 * 1024 * 1024;
110
111 if (!request_mem_region(cdev->mc.vram_base, cdev->mc.vram_size,
112 "cirrusdrmfb_vram")) {
113 DRM_ERROR("can't reserve VRAM\n");
114 return -ENXIO;
115 }
116
117 return 0;
118}
119
120/*
121 * Our emulated hardware has two sets of memory. One is video RAM and can
122 * simply be used as a linear framebuffer - the other provides mmio access
123 * to the display registers. The latter can also be accessed via IO port
124 * access, but we map the range and use mmio to program them instead
125 */
126
127int cirrus_device_init(struct cirrus_device *cdev,
128 struct drm_device *ddev,
129 struct pci_dev *pdev, uint32_t flags)
130{
131 int ret;
132
133 cdev->dev = ddev;
134 cdev->flags = flags;
135
136 /* Hardcode the number of CRTCs to 1 */
137 cdev->num_crtc = 1;
138
139 /* BAR 0 is the framebuffer, BAR 1 contains registers */
140 cdev->rmmio_base = pci_resource_start(cdev->dev->pdev, 1);
141 cdev->rmmio_size = pci_resource_len(cdev->dev->pdev, 1);
142
143 if (!request_mem_region(cdev->rmmio_base, cdev->rmmio_size,
144 "cirrusdrmfb_mmio")) {
145 DRM_ERROR("can't reserve mmio registers\n");
146 return -ENOMEM;
147 }
148
149 cdev->rmmio = ioremap(cdev->rmmio_base, cdev->rmmio_size);
150
151 if (cdev->rmmio == NULL)
152 return -ENOMEM;
153
154 ret = cirrus_vram_init(cdev);
155 if (ret) {
156 release_mem_region(cdev->rmmio_base, cdev->rmmio_size);
157 return ret;
158 }
159
160 return 0;
161}
162
163void cirrus_device_fini(struct cirrus_device *cdev)
164{
165 release_mem_region(cdev->rmmio_base, cdev->rmmio_size);
166 cirrus_vram_fini(cdev);
167}
168
169/*
170 * Functions here will be called by the core once it's bound the driver to
171 * a PCI device
172 */
173
174int cirrus_driver_load(struct drm_device *dev, unsigned long flags)
175{
176 struct cirrus_device *cdev;
177 int r;
178
179 cdev = kzalloc(sizeof(struct cirrus_device), GFP_KERNEL);
180 if (cdev == NULL)
181 return -ENOMEM;
182 dev->dev_private = (void *)cdev;
183
184 r = cirrus_device_init(cdev, dev, dev->pdev, flags);
185 if (r) {
186 dev_err(&dev->pdev->dev, "Fatal error during GPU init: %d\n", r);
187 goto out;
188 }
189
190 r = cirrus_mm_init(cdev);
191 if (r)
192 dev_err(&dev->pdev->dev, "fatal err on mm init\n");
193
194 r = cirrus_modeset_init(cdev);
195 if (r)
196 dev_err(&dev->pdev->dev, "Fatal error during modeset init: %d\n", r);
197
198 dev->mode_config.funcs = (void *)&cirrus_mode_funcs;
199out:
200 if (r)
201 cirrus_driver_unload(dev);
202 return r;
203}
204
205int cirrus_driver_unload(struct drm_device *dev)
206{
207 struct cirrus_device *cdev = dev->dev_private;
208
209 if (cdev == NULL)
210 return 0;
211 cirrus_modeset_fini(cdev);
212 cirrus_mm_fini(cdev);
213 cirrus_device_fini(cdev);
214 kfree(cdev);
215 dev->dev_private = NULL;
216 return 0;
217}
218
219int cirrus_gem_create(struct drm_device *dev,
220 u32 size, bool iskernel,
221 struct drm_gem_object **obj)
222{
223 struct cirrus_bo *cirrusbo;
224 int ret;
225
226 *obj = NULL;
227
228 size = roundup(size, PAGE_SIZE);
229 if (size == 0)
230 return -EINVAL;
231
232 ret = cirrus_bo_create(dev, size, 0, 0, &cirrusbo);
233 if (ret) {
234 if (ret != -ERESTARTSYS)
235 DRM_ERROR("failed to allocate GEM object\n");
236 return ret;
237 }
238 *obj = &cirrusbo->gem;
239 return 0;
240}
241
242int cirrus_dumb_create(struct drm_file *file,
243 struct drm_device *dev,
244 struct drm_mode_create_dumb *args)
245{
246 int ret;
247 struct drm_gem_object *gobj;
248 u32 handle;
249
250 args->pitch = args->width * ((args->bpp + 7) / 8);
251 args->size = args->pitch * args->height;
252
253 ret = cirrus_gem_create(dev, args->size, false,
254 &gobj);
255 if (ret)
256 return ret;
257
258 ret = drm_gem_handle_create(file, gobj, &handle);
259 drm_gem_object_unreference_unlocked(gobj);
260 if (ret)
261 return ret;
262
263 args->handle = handle;
264 return 0;
265}
266
267int cirrus_dumb_destroy(struct drm_file *file,
268 struct drm_device *dev,
269 uint32_t handle)
270{
271 return drm_gem_handle_delete(file, handle);
272}
273
274int cirrus_gem_init_object(struct drm_gem_object *obj)
275{
276 BUG();
277 return 0;
278}
279
280void cirrus_bo_unref(struct cirrus_bo **bo)
281{
282 struct ttm_buffer_object *tbo;
283
284 if ((*bo) == NULL)
285 return;
286
287 tbo = &((*bo)->bo);
288 ttm_bo_unref(&tbo);
289 if (tbo == NULL)
290 *bo = NULL;
291
292}
293
294void cirrus_gem_free_object(struct drm_gem_object *obj)
295{
296 struct cirrus_bo *cirrus_bo = gem_to_cirrus_bo(obj);
297
298 if (!cirrus_bo)
299 return;
300 cirrus_bo_unref(&cirrus_bo);
301}
302
303
304static inline u64 cirrus_bo_mmap_offset(struct cirrus_bo *bo)
305{
306 return bo->bo.addr_space_offset;
307}
308
309int
310cirrus_dumb_mmap_offset(struct drm_file *file,
311 struct drm_device *dev,
312 uint32_t handle,
313 uint64_t *offset)
314{
315 struct drm_gem_object *obj;
316 int ret;
317 struct cirrus_bo *bo;
318
319 mutex_lock(&dev->struct_mutex);
320 obj = drm_gem_object_lookup(dev, file, handle);
321 if (obj == NULL) {
322 ret = -ENOENT;
323 goto out_unlock;
324 }
325
326 bo = gem_to_cirrus_bo(obj);
327 *offset = cirrus_bo_mmap_offset(bo);
328
329 drm_gem_object_unreference(obj);
330 ret = 0;
331out_unlock:
332 mutex_unlock(&dev->struct_mutex);
333 return ret;
334
335}
diff --git a/drivers/gpu/drm/cirrus/cirrus_mode.c b/drivers/gpu/drm/cirrus/cirrus_mode.c
new file mode 100644
index 000000000000..100f6308c509
--- /dev/null
+++ b/drivers/gpu/drm/cirrus/cirrus_mode.c
@@ -0,0 +1,629 @@
1
2/*
3 * Copyright 2012 Red Hat
4 *
5 * This file is subject to the terms and conditions of the GNU General
6 * Public License version 2. See the file COPYING in the main
7 * directory of this archive for more details.
8 *
9 * Authors: Matthew Garrett
10 * Dave Airlie
11 *
12 * Portions of this code derived from cirrusfb.c:
13 * drivers/video/cirrusfb.c - driver for Cirrus Logic chipsets
14 *
15 * Copyright 1999-2001 Jeff Garzik <jgarzik@pobox.com>
16 */
17#include "drmP.h"
18#include "drm.h"
19#include "drm_crtc_helper.h"
20
21#include <video/cirrus.h>
22
23#include "cirrus_drv.h"
24
25#define CIRRUS_LUT_SIZE 256
26
27#define PALETTE_INDEX 0x8
28#define PALETTE_DATA 0x9
29
30/*
31 * This file contains setup code for the CRTC.
32 */
33
34static void cirrus_crtc_load_lut(struct drm_crtc *crtc)
35{
36 struct cirrus_crtc *cirrus_crtc = to_cirrus_crtc(crtc);
37 struct drm_device *dev = crtc->dev;
38 struct cirrus_device *cdev = dev->dev_private;
39 int i;
40
41 if (!crtc->enabled)
42 return;
43
44 for (i = 0; i < CIRRUS_LUT_SIZE; i++) {
45 /* VGA registers */
46 WREG8(PALETTE_INDEX, i);
47 WREG8(PALETTE_DATA, cirrus_crtc->lut_r[i]);
48 WREG8(PALETTE_DATA, cirrus_crtc->lut_g[i]);
49 WREG8(PALETTE_DATA, cirrus_crtc->lut_b[i]);
50 }
51}
52
53/*
54 * The DRM core requires DPMS functions, but they make little sense in our
55 * case and so are just stubs
56 */
57
58static void cirrus_crtc_dpms(struct drm_crtc *crtc, int mode)
59{
60 struct drm_device *dev = crtc->dev;
61 struct cirrus_device *cdev = dev->dev_private;
62 u8 sr01, gr0e;
63
64 switch (mode) {
65 case DRM_MODE_DPMS_ON:
66 sr01 = 0x00;
67 gr0e = 0x00;
68 break;
69 case DRM_MODE_DPMS_STANDBY:
70 sr01 = 0x20;
71 gr0e = 0x02;
72 break;
73 case DRM_MODE_DPMS_SUSPEND:
74 sr01 = 0x20;
75 gr0e = 0x04;
76 break;
77 case DRM_MODE_DPMS_OFF:
78 sr01 = 0x20;
79 gr0e = 0x06;
80 break;
81 default:
82 return;
83 }
84
85 WREG8(SEQ_INDEX, 0x1);
86 sr01 |= RREG8(SEQ_DATA) & ~0x20;
87 WREG_SEQ(0x1, sr01);
88
89 WREG8(GFX_INDEX, 0xe);
90 gr0e |= RREG8(GFX_DATA) & ~0x06;
91 WREG_GFX(0xe, gr0e);
92}
93
94/*
95 * The core passes the desired mode to the CRTC code to see whether any
96 * CRTC-specific modifications need to be made to it. We're in a position
97 * to just pass that straight through, so this does nothing
98 */
99static bool cirrus_crtc_mode_fixup(struct drm_crtc *crtc,
100 struct drm_display_mode *mode,
101 struct drm_display_mode *adjusted_mode)
102{
103 return true;
104}
105
106void cirrus_set_start_address(struct drm_crtc *crtc, unsigned offset)
107{
108 struct cirrus_device *cdev = crtc->dev->dev_private;
109 u32 addr;
110 u8 tmp;
111
112 addr = offset >> 2;
113 WREG_CRT(0x0c, (u8)((addr >> 8) & 0xff));
114 WREG_CRT(0x0d, (u8)(addr & 0xff));
115
116 WREG8(CRT_INDEX, 0x1b);
117 tmp = RREG8(CRT_DATA);
118 tmp &= 0xf2;
119 tmp |= (addr >> 16) & 0x01;
120 tmp |= (addr >> 15) & 0x0c;
121 WREG_CRT(0x1b, tmp);
122 WREG8(CRT_INDEX, 0x1d);
123 tmp = RREG8(CRT_DATA);
124 tmp &= 0x7f;
125 tmp |= (addr >> 12) & 0x80;
126 WREG_CRT(0x1d, tmp);
127}
128
129/* cirrus is different - we will force move buffers out of VRAM */
130static int cirrus_crtc_do_set_base(struct drm_crtc *crtc,
131 struct drm_framebuffer *fb,
132 int x, int y, int atomic)
133{
134 struct cirrus_device *cdev = crtc->dev->dev_private;
135 struct drm_gem_object *obj;
136 struct cirrus_framebuffer *cirrus_fb;
137 struct cirrus_bo *bo;
138 int ret;
139 u64 gpu_addr;
140
141 /* push the previous fb to system ram */
142 if (!atomic && fb) {
143 cirrus_fb = to_cirrus_framebuffer(fb);
144 obj = cirrus_fb->obj;
145 bo = gem_to_cirrus_bo(obj);
146 ret = cirrus_bo_reserve(bo, false);
147 if (ret)
148 return ret;
149 cirrus_bo_push_sysram(bo);
150 cirrus_bo_unreserve(bo);
151 }
152
153 cirrus_fb = to_cirrus_framebuffer(crtc->fb);
154 obj = cirrus_fb->obj;
155 bo = gem_to_cirrus_bo(obj);
156
157 ret = cirrus_bo_reserve(bo, false);
158 if (ret)
159 return ret;
160
161 ret = cirrus_bo_pin(bo, TTM_PL_FLAG_VRAM, &gpu_addr);
162 if (ret) {
163 cirrus_bo_unreserve(bo);
164 return ret;
165 }
166
167 if (&cdev->mode_info.gfbdev->gfb == cirrus_fb) {
168 /* if pushing console in kmap it */
169 ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap);
170 if (ret)
171 DRM_ERROR("failed to kmap fbcon\n");
172 }
173 cirrus_bo_unreserve(bo);
174
175 cirrus_set_start_address(crtc, (u32)gpu_addr);
176 return 0;
177}
178
179static int cirrus_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
180 struct drm_framebuffer *old_fb)
181{
182 return cirrus_crtc_do_set_base(crtc, old_fb, x, y, 0);
183}
184
185/*
186 * The meat of this driver. The core passes us a mode and we have to program
187 * it. The modesetting here is the bare minimum required to satisfy the qemu
188 * emulation of this hardware, and running this against a real device is
189 * likely to result in an inadequately programmed mode. We've already had
190 * the opportunity to modify the mode, so whatever we receive here should
191 * be something that can be correctly programmed and displayed
192 */
193static int cirrus_crtc_mode_set(struct drm_crtc *crtc,
194 struct drm_display_mode *mode,
195 struct drm_display_mode *adjusted_mode,
196 int x, int y, struct drm_framebuffer *old_fb)
197{
198 struct drm_device *dev = crtc->dev;
199 struct cirrus_device *cdev = dev->dev_private;
200 int hsyncstart, hsyncend, htotal, hdispend;
201 int vtotal, vdispend;
202 int tmp;
203 int sr07 = 0, hdr = 0;
204
205 htotal = mode->htotal / 8;
206 hsyncend = mode->hsync_end / 8;
207 hsyncstart = mode->hsync_start / 8;
208 hdispend = mode->hdisplay / 8;
209
210 vtotal = mode->vtotal;
211 vdispend = mode->vdisplay;
212
213 vdispend -= 1;
214 vtotal -= 2;
215
216 htotal -= 5;
217 hdispend -= 1;
218 hsyncstart += 1;
219 hsyncend += 1;
220
221 WREG_CRT(VGA_CRTC_V_SYNC_END, 0x20);
222 WREG_CRT(VGA_CRTC_H_TOTAL, htotal);
223 WREG_CRT(VGA_CRTC_H_DISP, hdispend);
224 WREG_CRT(VGA_CRTC_H_SYNC_START, hsyncstart);
225 WREG_CRT(VGA_CRTC_H_SYNC_END, hsyncend);
226 WREG_CRT(VGA_CRTC_V_TOTAL, vtotal & 0xff);
227 WREG_CRT(VGA_CRTC_V_DISP_END, vdispend & 0xff);
228
229 tmp = 0x40;
230 if ((vdispend + 1) & 512)
231 tmp |= 0x20;
232 WREG_CRT(VGA_CRTC_MAX_SCAN, tmp);
233
234 /*
235 * Overflow bits for values that don't fit in the standard registers
236 */
237 tmp = 16;
238 if (vtotal & 256)
239 tmp |= 1;
240 if (vdispend & 256)
241 tmp |= 2;
242 if ((vdispend + 1) & 256)
243 tmp |= 8;
244 if (vtotal & 512)
245 tmp |= 32;
246 if (vdispend & 512)
247 tmp |= 64;
248 WREG_CRT(VGA_CRTC_OVERFLOW, tmp);
249
250 tmp = 0;
251
252 /* More overflow bits */
253
254 if ((htotal + 5) & 64)
255 tmp |= 16;
256 if ((htotal + 5) & 128)
257 tmp |= 32;
258 if (vtotal & 256)
259 tmp |= 64;
260 if (vtotal & 512)
261 tmp |= 128;
262
263 WREG_CRT(CL_CRT1A, tmp);
264
265 /* Disable Hercules/CGA compatibility */
266 WREG_CRT(VGA_CRTC_MODE, 0x03);
267
268 WREG8(SEQ_INDEX, 0x7);
269 sr07 = RREG8(SEQ_DATA);
270 sr07 &= 0xe0;
271 hdr = 0;
272 switch (crtc->fb->bits_per_pixel) {
273 case 8:
274 sr07 |= 0x11;
275 break;
276 case 16:
277 sr07 |= 0xc1;
278 hdr = 0xc0;
279 break;
280 case 24:
281 sr07 |= 0x15;
282 hdr = 0xc5;
283 break;
284 case 32:
285 sr07 |= 0x19;
286 hdr = 0xc5;
287 break;
288 default:
289 return -1;
290 }
291
292 WREG_SEQ(0x7, sr07);
293
294 /* Program the pitch */
295 tmp = crtc->fb->pitches[0] / 8;
296 WREG_CRT(VGA_CRTC_OFFSET, tmp);
297
298 /* Enable extended blanking and pitch bits, and enable full memory */
299 tmp = 0x22;
300 tmp |= (crtc->fb->pitches[0] >> 7) & 0x10;
301 tmp |= (crtc->fb->pitches[0] >> 6) & 0x40;
302 WREG_CRT(0x1b, tmp);
303
304 /* Enable high-colour modes */
305 WREG_GFX(VGA_GFX_MODE, 0x40);
306
307 /* And set graphics mode */
308 WREG_GFX(VGA_GFX_MISC, 0x01);
309
310 WREG_HDR(hdr);
311 cirrus_crtc_do_set_base(crtc, old_fb, x, y, 0);
312 return 0;
313}
314
315/*
316 * This is called before a mode is programmed. A typical use might be to
317 * enable DPMS during the programming to avoid seeing intermediate stages,
318 * but that's not relevant to us
319 */
320static void cirrus_crtc_prepare(struct drm_crtc *crtc)
321{
322}
323
324/*
325 * This is called after a mode is programmed. It should reverse anything done
326 * by the prepare function
327 */
328static void cirrus_crtc_commit(struct drm_crtc *crtc)
329{
330}
331
332/*
333 * The core can pass us a set of gamma values to program. We actually only
334 * use this for 8-bit mode so can't perform smooth fades on deeper modes,
335 * but it's a requirement that we provide the function
336 */
337static void cirrus_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
338 u16 *blue, uint32_t start, uint32_t size)
339{
340 struct cirrus_crtc *cirrus_crtc = to_cirrus_crtc(crtc);
341 int i;
342
343 if (size != CIRRUS_LUT_SIZE)
344 return;
345
346 for (i = 0; i < CIRRUS_LUT_SIZE; i++) {
347 cirrus_crtc->lut_r[i] = red[i];
348 cirrus_crtc->lut_g[i] = green[i];
349 cirrus_crtc->lut_b[i] = blue[i];
350 }
351 cirrus_crtc_load_lut(crtc);
352}
353
354/* Simple cleanup function */
355static void cirrus_crtc_destroy(struct drm_crtc *crtc)
356{
357 struct cirrus_crtc *cirrus_crtc = to_cirrus_crtc(crtc);
358
359 drm_crtc_cleanup(crtc);
360 kfree(cirrus_crtc);
361}
362
363/* These provide the minimum set of functions required to handle a CRTC */
364static const struct drm_crtc_funcs cirrus_crtc_funcs = {
365 .gamma_set = cirrus_crtc_gamma_set,
366 .set_config = drm_crtc_helper_set_config,
367 .destroy = cirrus_crtc_destroy,
368};
369
370static const struct drm_crtc_helper_funcs cirrus_helper_funcs = {
371 .dpms = cirrus_crtc_dpms,
372 .mode_fixup = cirrus_crtc_mode_fixup,
373 .mode_set = cirrus_crtc_mode_set,
374 .mode_set_base = cirrus_crtc_mode_set_base,
375 .prepare = cirrus_crtc_prepare,
376 .commit = cirrus_crtc_commit,
377 .load_lut = cirrus_crtc_load_lut,
378};
379
380/* CRTC setup */
381static void cirrus_crtc_init(struct drm_device *dev)
382{
383 struct cirrus_device *cdev = dev->dev_private;
384 struct cirrus_crtc *cirrus_crtc;
385 int i;
386
387 cirrus_crtc = kzalloc(sizeof(struct cirrus_crtc) +
388 (CIRRUSFB_CONN_LIMIT * sizeof(struct drm_connector *)),
389 GFP_KERNEL);
390
391 if (cirrus_crtc == NULL)
392 return;
393
394 drm_crtc_init(dev, &cirrus_crtc->base, &cirrus_crtc_funcs);
395
396 drm_mode_crtc_set_gamma_size(&cirrus_crtc->base, CIRRUS_LUT_SIZE);
397 cdev->mode_info.crtc = cirrus_crtc;
398
399 for (i = 0; i < CIRRUS_LUT_SIZE; i++) {
400 cirrus_crtc->lut_r[i] = i;
401 cirrus_crtc->lut_g[i] = i;
402 cirrus_crtc->lut_b[i] = i;
403 }
404
405 drm_crtc_helper_add(&cirrus_crtc->base, &cirrus_helper_funcs);
406}
407
408/** Sets the color ramps on behalf of fbcon */
409void cirrus_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
410 u16 blue, int regno)
411{
412 struct cirrus_crtc *cirrus_crtc = to_cirrus_crtc(crtc);
413
414 cirrus_crtc->lut_r[regno] = red;
415 cirrus_crtc->lut_g[regno] = green;
416 cirrus_crtc->lut_b[regno] = blue;
417}
418
419/** Gets the color ramps on behalf of fbcon */
420void cirrus_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
421 u16 *blue, int regno)
422{
423 struct cirrus_crtc *cirrus_crtc = to_cirrus_crtc(crtc);
424
425 *red = cirrus_crtc->lut_r[regno];
426 *green = cirrus_crtc->lut_g[regno];
427 *blue = cirrus_crtc->lut_b[regno];
428}
429
430
431static bool cirrus_encoder_mode_fixup(struct drm_encoder *encoder,
432 struct drm_display_mode *mode,
433 struct drm_display_mode *adjusted_mode)
434{
435 return true;
436}
437
438static void cirrus_encoder_mode_set(struct drm_encoder *encoder,
439 struct drm_display_mode *mode,
440 struct drm_display_mode *adjusted_mode)
441{
442}
443
444static void cirrus_encoder_dpms(struct drm_encoder *encoder, int state)
445{
446 return;
447}
448
449static void cirrus_encoder_prepare(struct drm_encoder *encoder)
450{
451}
452
453static void cirrus_encoder_commit(struct drm_encoder *encoder)
454{
455}
456
457void cirrus_encoder_destroy(struct drm_encoder *encoder)
458{
459 struct cirrus_encoder *cirrus_encoder = to_cirrus_encoder(encoder);
460 drm_encoder_cleanup(encoder);
461 kfree(cirrus_encoder);
462}
463
464static const struct drm_encoder_helper_funcs cirrus_encoder_helper_funcs = {
465 .dpms = cirrus_encoder_dpms,
466 .mode_fixup = cirrus_encoder_mode_fixup,
467 .mode_set = cirrus_encoder_mode_set,
468 .prepare = cirrus_encoder_prepare,
469 .commit = cirrus_encoder_commit,
470};
471
472static const struct drm_encoder_funcs cirrus_encoder_encoder_funcs = {
473 .destroy = cirrus_encoder_destroy,
474};
475
476static struct drm_encoder *cirrus_encoder_init(struct drm_device *dev)
477{
478 struct drm_encoder *encoder;
479 struct cirrus_encoder *cirrus_encoder;
480
481 cirrus_encoder = kzalloc(sizeof(struct cirrus_encoder), GFP_KERNEL);
482 if (!cirrus_encoder)
483 return NULL;
484
485 encoder = &cirrus_encoder->base;
486 encoder->possible_crtcs = 0x1;
487
488 drm_encoder_init(dev, encoder, &cirrus_encoder_encoder_funcs,
489 DRM_MODE_ENCODER_DAC);
490 drm_encoder_helper_add(encoder, &cirrus_encoder_helper_funcs);
491
492 return encoder;
493}
494
495
496int cirrus_vga_get_modes(struct drm_connector *connector)
497{
498 /* Just add a static list of modes */
499 drm_add_modes_noedid(connector, 640, 480);
500 drm_add_modes_noedid(connector, 800, 600);
501 drm_add_modes_noedid(connector, 1024, 768);
502 drm_add_modes_noedid(connector, 1280, 1024);
503
504 return 4;
505}
506
507static int cirrus_vga_mode_valid(struct drm_connector *connector,
508 struct drm_display_mode *mode)
509{
510 /* Any mode we've added is valid */
511 return MODE_OK;
512}
513
514struct drm_encoder *cirrus_connector_best_encoder(struct drm_connector
515 *connector)
516{
517 int enc_id = connector->encoder_ids[0];
518 struct drm_mode_object *obj;
519 struct drm_encoder *encoder;
520
521 /* pick the encoder ids */
522 if (enc_id) {
523 obj =
524 drm_mode_object_find(connector->dev, enc_id,
525 DRM_MODE_OBJECT_ENCODER);
526 if (!obj)
527 return NULL;
528 encoder = obj_to_encoder(obj);
529 return encoder;
530 }
531 return NULL;
532}
533
534static enum drm_connector_status cirrus_vga_detect(struct drm_connector
535 *connector, bool force)
536{
537 return connector_status_connected;
538}
539
540static void cirrus_connector_destroy(struct drm_connector *connector)
541{
542 drm_connector_cleanup(connector);
543 kfree(connector);
544}
545
546struct drm_connector_helper_funcs cirrus_vga_connector_helper_funcs = {
547 .get_modes = cirrus_vga_get_modes,
548 .mode_valid = cirrus_vga_mode_valid,
549 .best_encoder = cirrus_connector_best_encoder,
550};
551
552struct drm_connector_funcs cirrus_vga_connector_funcs = {
553 .dpms = drm_helper_connector_dpms,
554 .detect = cirrus_vga_detect,
555 .fill_modes = drm_helper_probe_single_connector_modes,
556 .destroy = cirrus_connector_destroy,
557};
558
559static struct drm_connector *cirrus_vga_init(struct drm_device *dev)
560{
561 struct drm_connector *connector;
562 struct cirrus_connector *cirrus_connector;
563
564 cirrus_connector = kzalloc(sizeof(struct cirrus_connector), GFP_KERNEL);
565 if (!cirrus_connector)
566 return NULL;
567
568 connector = &cirrus_connector->base;
569
570 drm_connector_init(dev, connector,
571 &cirrus_vga_connector_funcs, DRM_MODE_CONNECTOR_VGA);
572
573 drm_connector_helper_add(connector, &cirrus_vga_connector_helper_funcs);
574
575 return connector;
576}
577
578
579int cirrus_modeset_init(struct cirrus_device *cdev)
580{
581 struct drm_encoder *encoder;
582 struct drm_connector *connector;
583 int ret;
584
585 drm_mode_config_init(cdev->dev);
586 cdev->mode_info.mode_config_initialized = true;
587
588 cdev->dev->mode_config.max_width = CIRRUS_MAX_FB_WIDTH;
589 cdev->dev->mode_config.max_height = CIRRUS_MAX_FB_HEIGHT;
590
591 cdev->dev->mode_config.fb_base = cdev->mc.vram_base;
592 cdev->dev->mode_config.preferred_depth = 24;
593 /* don't prefer a shadow on virt GPU */
594 cdev->dev->mode_config.prefer_shadow = 0;
595
596 cirrus_crtc_init(cdev->dev);
597
598 encoder = cirrus_encoder_init(cdev->dev);
599 if (!encoder) {
600 DRM_ERROR("cirrus_encoder_init failed\n");
601 return -1;
602 }
603
604 connector = cirrus_vga_init(cdev->dev);
605 if (!connector) {
606 DRM_ERROR("cirrus_vga_init failed\n");
607 return -1;
608 }
609
610 drm_mode_connector_attach_encoder(connector, encoder);
611
612 ret = cirrus_fbdev_init(cdev);
613 if (ret) {
614 DRM_ERROR("cirrus_fbdev_init failed\n");
615 return ret;
616 }
617
618 return 0;
619}
620
621void cirrus_modeset_fini(struct cirrus_device *cdev)
622{
623 cirrus_fbdev_fini(cdev);
624
625 if (cdev->mode_info.mode_config_initialized) {
626 drm_mode_config_cleanup(cdev->dev);
627 cdev->mode_info.mode_config_initialized = false;
628 }
629}
diff --git a/drivers/gpu/drm/cirrus/cirrus_ttm.c b/drivers/gpu/drm/cirrus/cirrus_ttm.c
new file mode 100644
index 000000000000..ae2f08ff3808
--- /dev/null
+++ b/drivers/gpu/drm/cirrus/cirrus_ttm.c
@@ -0,0 +1,453 @@
1/*
2 * Copyright 2012 Red Hat Inc.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the
6 * "Software"), to deal in the Software without restriction, including
7 * without limitation the rights to use, copy, modify, merge, publish,
8 * distribute, sub license, and/or sell copies of the Software, and to
9 * permit persons to whom the Software is furnished to do so, subject to
10 * the following conditions:
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
13 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
14 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
15 * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
16 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
17 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
18 * USE OR OTHER DEALINGS IN THE SOFTWARE.
19 *
20 * The above copyright notice and this permission notice (including the
21 * next paragraph) shall be included in all copies or substantial portions
22 * of the Software.
23 *
24 */
25/*
26 * Authors: Dave Airlie <airlied@redhat.com>
27 */
28#include "drmP.h"
29#include "cirrus_drv.h"
30#include <ttm/ttm_page_alloc.h>
31
32static inline struct cirrus_device *
33cirrus_bdev(struct ttm_bo_device *bd)
34{
35 return container_of(bd, struct cirrus_device, ttm.bdev);
36}
37
38static int
39cirrus_ttm_mem_global_init(struct drm_global_reference *ref)
40{
41 return ttm_mem_global_init(ref->object);
42}
43
44static void
45cirrus_ttm_mem_global_release(struct drm_global_reference *ref)
46{
47 ttm_mem_global_release(ref->object);
48}
49
50static int cirrus_ttm_global_init(struct cirrus_device *cirrus)
51{
52 struct drm_global_reference *global_ref;
53 int r;
54
55 global_ref = &cirrus->ttm.mem_global_ref;
56 global_ref->global_type = DRM_GLOBAL_TTM_MEM;
57 global_ref->size = sizeof(struct ttm_mem_global);
58 global_ref->init = &cirrus_ttm_mem_global_init;
59 global_ref->release = &cirrus_ttm_mem_global_release;
60 r = drm_global_item_ref(global_ref);
61 if (r != 0) {
62 DRM_ERROR("Failed setting up TTM memory accounting "
63 "subsystem.\n");
64 return r;
65 }
66
67 cirrus->ttm.bo_global_ref.mem_glob =
68 cirrus->ttm.mem_global_ref.object;
69 global_ref = &cirrus->ttm.bo_global_ref.ref;
70 global_ref->global_type = DRM_GLOBAL_TTM_BO;
71 global_ref->size = sizeof(struct ttm_bo_global);
72 global_ref->init = &ttm_bo_global_init;
73 global_ref->release = &ttm_bo_global_release;
74 r = drm_global_item_ref(global_ref);
75 if (r != 0) {
76 DRM_ERROR("Failed setting up TTM BO subsystem.\n");
77 drm_global_item_unref(&cirrus->ttm.mem_global_ref);
78 return r;
79 }
80 return 0;
81}
82
83void
84cirrus_ttm_global_release(struct cirrus_device *cirrus)
85{
86 if (cirrus->ttm.mem_global_ref.release == NULL)
87 return;
88
89 drm_global_item_unref(&cirrus->ttm.bo_global_ref.ref);
90 drm_global_item_unref(&cirrus->ttm.mem_global_ref);
91 cirrus->ttm.mem_global_ref.release = NULL;
92}
93
94
95static void cirrus_bo_ttm_destroy(struct ttm_buffer_object *tbo)
96{
97 struct cirrus_bo *bo;
98
99 bo = container_of(tbo, struct cirrus_bo, bo);
100
101 drm_gem_object_release(&bo->gem);
102 kfree(bo);
103}
104
105bool cirrus_ttm_bo_is_cirrus_bo(struct ttm_buffer_object *bo)
106{
107 if (bo->destroy == &cirrus_bo_ttm_destroy)
108 return true;
109 return false;
110}
111
112static int
113cirrus_bo_init_mem_type(struct ttm_bo_device *bdev, uint32_t type,
114 struct ttm_mem_type_manager *man)
115{
116 switch (type) {
117 case TTM_PL_SYSTEM:
118 man->flags = TTM_MEMTYPE_FLAG_MAPPABLE;
119 man->available_caching = TTM_PL_MASK_CACHING;
120 man->default_caching = TTM_PL_FLAG_CACHED;
121 break;
122 case TTM_PL_VRAM:
123 man->func = &ttm_bo_manager_func;
124 man->flags = TTM_MEMTYPE_FLAG_FIXED |
125 TTM_MEMTYPE_FLAG_MAPPABLE;
126 man->available_caching = TTM_PL_FLAG_UNCACHED |
127 TTM_PL_FLAG_WC;
128 man->default_caching = TTM_PL_FLAG_WC;
129 break;
130 default:
131 DRM_ERROR("Unsupported memory type %u\n", (unsigned)type);
132 return -EINVAL;
133 }
134 return 0;
135}
136
137static void
138cirrus_bo_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *pl)
139{
140 struct cirrus_bo *cirrusbo = cirrus_bo(bo);
141
142 if (!cirrus_ttm_bo_is_cirrus_bo(bo))
143 return;
144
145 cirrus_ttm_placement(cirrusbo, TTM_PL_FLAG_SYSTEM);
146 *pl = cirrusbo->placement;
147}
148
149static int cirrus_bo_verify_access(struct ttm_buffer_object *bo, struct file *filp)
150{
151 return 0;
152}
153
154static int cirrus_ttm_io_mem_reserve(struct ttm_bo_device *bdev,
155 struct ttm_mem_reg *mem)
156{
157 struct ttm_mem_type_manager *man = &bdev->man[mem->mem_type];
158 struct cirrus_device *cirrus = cirrus_bdev(bdev);
159
160 mem->bus.addr = NULL;
161 mem->bus.offset = 0;
162 mem->bus.size = mem->num_pages << PAGE_SHIFT;
163 mem->bus.base = 0;
164 mem->bus.is_iomem = false;
165 if (!(man->flags & TTM_MEMTYPE_FLAG_MAPPABLE))
166 return -EINVAL;
167 switch (mem->mem_type) {
168 case TTM_PL_SYSTEM:
169 /* system memory */
170 return 0;
171 case TTM_PL_VRAM:
172 mem->bus.offset = mem->start << PAGE_SHIFT;
173 mem->bus.base = pci_resource_start(cirrus->dev->pdev, 0);
174 mem->bus.is_iomem = true;
175 break;
176 default:
177 return -EINVAL;
178 break;
179 }
180 return 0;
181}
182
183static void cirrus_ttm_io_mem_free(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
184{
185}
186
187static int cirrus_bo_move(struct ttm_buffer_object *bo,
188 bool evict, bool interruptible,
189 bool no_wait_reserve, bool no_wait_gpu,
190 struct ttm_mem_reg *new_mem)
191{
192 int r;
193 r = ttm_bo_move_memcpy(bo, evict, no_wait_reserve, no_wait_gpu, new_mem);
194 return r;
195}
196
197
198static void cirrus_ttm_backend_destroy(struct ttm_tt *tt)
199{
200 ttm_tt_fini(tt);
201 kfree(tt);
202}
203
204static struct ttm_backend_func cirrus_tt_backend_func = {
205 .destroy = &cirrus_ttm_backend_destroy,
206};
207
208
209struct ttm_tt *cirrus_ttm_tt_create(struct ttm_bo_device *bdev,
210 unsigned long size, uint32_t page_flags,
211 struct page *dummy_read_page)
212{
213 struct ttm_tt *tt;
214
215 tt = kzalloc(sizeof(struct ttm_tt), GFP_KERNEL);
216 if (tt == NULL)
217 return NULL;
218 tt->func = &cirrus_tt_backend_func;
219 if (ttm_tt_init(tt, bdev, size, page_flags, dummy_read_page)) {
220 kfree(tt);
221 return NULL;
222 }
223 return tt;
224}
225
226static int cirrus_ttm_tt_populate(struct ttm_tt *ttm)
227{
228 return ttm_pool_populate(ttm);
229}
230
231static void cirrus_ttm_tt_unpopulate(struct ttm_tt *ttm)
232{
233 ttm_pool_unpopulate(ttm);
234}
235
236struct ttm_bo_driver cirrus_bo_driver = {
237 .ttm_tt_create = cirrus_ttm_tt_create,
238 .ttm_tt_populate = cirrus_ttm_tt_populate,
239 .ttm_tt_unpopulate = cirrus_ttm_tt_unpopulate,
240 .init_mem_type = cirrus_bo_init_mem_type,
241 .evict_flags = cirrus_bo_evict_flags,
242 .move = cirrus_bo_move,
243 .verify_access = cirrus_bo_verify_access,
244 .io_mem_reserve = &cirrus_ttm_io_mem_reserve,
245 .io_mem_free = &cirrus_ttm_io_mem_free,
246};
247
248int cirrus_mm_init(struct cirrus_device *cirrus)
249{
250 int ret;
251 struct drm_device *dev = cirrus->dev;
252 struct ttm_bo_device *bdev = &cirrus->ttm.bdev;
253
254 ret = cirrus_ttm_global_init(cirrus);
255 if (ret)
256 return ret;
257
258 ret = ttm_bo_device_init(&cirrus->ttm.bdev,
259 cirrus->ttm.bo_global_ref.ref.object,
260 &cirrus_bo_driver, DRM_FILE_PAGE_OFFSET,
261 true);
262 if (ret) {
263 DRM_ERROR("Error initialising bo driver; %d\n", ret);
264 return ret;
265 }
266
267 ret = ttm_bo_init_mm(bdev, TTM_PL_VRAM,
268 cirrus->mc.vram_size >> PAGE_SHIFT);
269 if (ret) {
270 DRM_ERROR("Failed ttm VRAM init: %d\n", ret);
271 return ret;
272 }
273
274 cirrus->fb_mtrr = drm_mtrr_add(pci_resource_start(dev->pdev, 0),
275 pci_resource_len(dev->pdev, 0),
276 DRM_MTRR_WC);
277
278 return 0;
279}
280
281void cirrus_mm_fini(struct cirrus_device *cirrus)
282{
283 struct drm_device *dev = cirrus->dev;
284 ttm_bo_device_release(&cirrus->ttm.bdev);
285
286 cirrus_ttm_global_release(cirrus);
287
288 if (cirrus->fb_mtrr >= 0) {
289 drm_mtrr_del(cirrus->fb_mtrr,
290 pci_resource_start(dev->pdev, 0),
291 pci_resource_len(dev->pdev, 0), DRM_MTRR_WC);
292 cirrus->fb_mtrr = -1;
293 }
294}
295
296void cirrus_ttm_placement(struct cirrus_bo *bo, int domain)
297{
298 u32 c = 0;
299 bo->placement.fpfn = 0;
300 bo->placement.lpfn = 0;
301 bo->placement.placement = bo->placements;
302 bo->placement.busy_placement = bo->placements;
303 if (domain & TTM_PL_FLAG_VRAM)
304 bo->placements[c++] = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_VRAM;
305 if (domain & TTM_PL_FLAG_SYSTEM)
306 bo->placements[c++] = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM;
307 if (!c)
308 bo->placements[c++] = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM;
309 bo->placement.num_placement = c;
310 bo->placement.num_busy_placement = c;
311}
312
313int cirrus_bo_reserve(struct cirrus_bo *bo, bool no_wait)
314{
315 int ret;
316
317 ret = ttm_bo_reserve(&bo->bo, true, no_wait, false, 0);
318 if (ret) {
319 if (ret != -ERESTARTSYS)
320 DRM_ERROR("reserve failed %p\n", bo);
321 return ret;
322 }
323 return 0;
324}
325
326void cirrus_bo_unreserve(struct cirrus_bo *bo)
327{
328 ttm_bo_unreserve(&bo->bo);
329}
330
331int cirrus_bo_create(struct drm_device *dev, int size, int align,
332 uint32_t flags, struct cirrus_bo **pcirrusbo)
333{
334 struct cirrus_device *cirrus = dev->dev_private;
335 struct cirrus_bo *cirrusbo;
336 size_t acc_size;
337 int ret;
338
339 cirrusbo = kzalloc(sizeof(struct cirrus_bo), GFP_KERNEL);
340 if (!cirrusbo)
341 return -ENOMEM;
342
343 ret = drm_gem_object_init(dev, &cirrusbo->gem, size);
344 if (ret) {
345 kfree(cirrusbo);
346 return ret;
347 }
348
349 cirrusbo->gem.driver_private = NULL;
350 cirrusbo->bo.bdev = &cirrus->ttm.bdev;
351
352 cirrus_ttm_placement(cirrusbo, TTM_PL_FLAG_VRAM | TTM_PL_FLAG_SYSTEM);
353
354 acc_size = ttm_bo_dma_acc_size(&cirrus->ttm.bdev, size,
355 sizeof(struct cirrus_bo));
356
357 ret = ttm_bo_init(&cirrus->ttm.bdev, &cirrusbo->bo, size,
358 ttm_bo_type_device, &cirrusbo->placement,
359 align >> PAGE_SHIFT, 0, false, NULL, acc_size,
360 cirrus_bo_ttm_destroy);
361 if (ret)
362 return ret;
363
364 *pcirrusbo = cirrusbo;
365 return 0;
366}
367
368static inline u64 cirrus_bo_gpu_offset(struct cirrus_bo *bo)
369{
370 return bo->bo.offset;
371}
372
373int cirrus_bo_pin(struct cirrus_bo *bo, u32 pl_flag, u64 *gpu_addr)
374{
375 int i, ret;
376
377 if (bo->pin_count) {
378 bo->pin_count++;
379 if (gpu_addr)
380 *gpu_addr = cirrus_bo_gpu_offset(bo);
381 }
382
383 cirrus_ttm_placement(bo, pl_flag);
384 for (i = 0; i < bo->placement.num_placement; i++)
385 bo->placements[i] |= TTM_PL_FLAG_NO_EVICT;
386 ret = ttm_bo_validate(&bo->bo, &bo->placement, false, false, false);
387 if (ret)
388 return ret;
389
390 bo->pin_count = 1;
391 if (gpu_addr)
392 *gpu_addr = cirrus_bo_gpu_offset(bo);
393 return 0;
394}
395
396int cirrus_bo_unpin(struct cirrus_bo *bo)
397{
398 int i, ret;
399 if (!bo->pin_count) {
400 DRM_ERROR("unpin bad %p\n", bo);
401 return 0;
402 }
403 bo->pin_count--;
404 if (bo->pin_count)
405 return 0;
406
407 for (i = 0; i < bo->placement.num_placement ; i++)
408 bo->placements[i] &= ~TTM_PL_FLAG_NO_EVICT;
409 ret = ttm_bo_validate(&bo->bo, &bo->placement, false, false, false);
410 if (ret)
411 return ret;
412
413 return 0;
414}
415
416int cirrus_bo_push_sysram(struct cirrus_bo *bo)
417{
418 int i, ret;
419 if (!bo->pin_count) {
420 DRM_ERROR("unpin bad %p\n", bo);
421 return 0;
422 }
423 bo->pin_count--;
424 if (bo->pin_count)
425 return 0;
426
427 if (bo->kmap.virtual)
428 ttm_bo_kunmap(&bo->kmap);
429
430 cirrus_ttm_placement(bo, TTM_PL_FLAG_SYSTEM);
431 for (i = 0; i < bo->placement.num_placement ; i++)
432 bo->placements[i] |= TTM_PL_FLAG_NO_EVICT;
433
434 ret = ttm_bo_validate(&bo->bo, &bo->placement, false, false, false);
435 if (ret) {
436 DRM_ERROR("pushing to VRAM failed\n");
437 return ret;
438 }
439 return 0;
440}
441
442int cirrus_mmap(struct file *filp, struct vm_area_struct *vma)
443{
444 struct drm_file *file_priv;
445 struct cirrus_device *cirrus;
446
447 if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET))
448 return drm_mmap(filp, vma);
449
450 file_priv = filp->private_data;
451 cirrus = file_priv->minor->dev->dev_private;
452 return ttm_bo_mmap(filp, vma, &cirrus->ttm.bdev);
453}