aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/mgag200
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/mgag200')
-rw-r--r--drivers/gpu/drm/mgag200/Kconfig15
-rw-r--r--drivers/gpu/drm/mgag200/Makefile5
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_drv.c116
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_drv.h276
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_fb.c294
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_i2c.c156
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_main.c388
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_mode.c1533
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_reg.h661
-rw-r--r--drivers/gpu/drm/mgag200/mgag200_ttm.c452
10 files changed, 3896 insertions, 0 deletions
diff --git a/drivers/gpu/drm/mgag200/Kconfig b/drivers/gpu/drm/mgag200/Kconfig
new file mode 100644
index 000000000000..d63013497f66
--- /dev/null
+++ b/drivers/gpu/drm/mgag200/Kconfig
@@ -0,0 +1,15 @@
1config DRM_MGAG200
2 tristate "Kernel modesetting driver for MGA G200 server engines"
3 depends on DRM && PCI && EXPERIMENTAL
4 select FB_SYS_FILLRECT
5 select FB_SYS_COPYAREA
6 select FB_SYS_IMAGEBLIT
7 select DRM_KMS_HELPER
8 select DRM_TTM
9 help
10 This is a KMS driver for the MGA G200 server chips, it
11 does not support the original MGA G200 or any of the desktop
12 chips. It requires 0.3.0 of the modesetting userspace driver,
13 and a version of mga driver that will fail on KMS enabled
14 devices.
15
diff --git a/drivers/gpu/drm/mgag200/Makefile b/drivers/gpu/drm/mgag200/Makefile
new file mode 100644
index 000000000000..7db592eedbf1
--- /dev/null
+++ b/drivers/gpu/drm/mgag200/Makefile
@@ -0,0 +1,5 @@
1ccflags-y := -Iinclude/drm
2mgag200-y := mgag200_main.o mgag200_mode.o \
3 mgag200_drv.o mgag200_fb.o mgag200_i2c.o mgag200_ttm.o
4
5obj-$(CONFIG_DRM_MGAG200) += mgag200.o
diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.c b/drivers/gpu/drm/mgag200/mgag200_drv.c
new file mode 100644
index 000000000000..3c8e04f54713
--- /dev/null
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.c
@@ -0,0 +1,116 @@
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 <linux/console.h>
13#include "drmP.h"
14#include "drm.h"
15
16#include "mgag200_drv.h"
17
18#include "drm_pciids.h"
19
20/*
21 * This is the generic driver code. This binds the driver to the drm core,
22 * which then performs further device association and calls our graphics init
23 * functions
24 */
25int mgag200_modeset = -1;
26
27MODULE_PARM_DESC(modeset, "Disable/Enable modesetting");
28module_param_named(modeset, mgag200_modeset, int, 0400);
29
30static struct drm_driver driver;
31
32static DEFINE_PCI_DEVICE_TABLE(pciidlist) = {
33 { PCI_VENDOR_ID_MATROX, 0x522, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_SE_A },
34 { PCI_VENDOR_ID_MATROX, 0x524, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_SE_B },
35 { PCI_VENDOR_ID_MATROX, 0x530, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_EV },
36 { PCI_VENDOR_ID_MATROX, 0x532, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_WB },
37 { PCI_VENDOR_ID_MATROX, 0x533, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_EH },
38 { PCI_VENDOR_ID_MATROX, 0x534, PCI_ANY_ID, PCI_ANY_ID, 0, 0, G200_ER },
39 {0,}
40};
41
42MODULE_DEVICE_TABLE(pci, pciidlist);
43
44static int __devinit
45mga_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
46{
47 return drm_get_pci_dev(pdev, ent, &driver);
48}
49
50static void mga_pci_remove(struct pci_dev *pdev)
51{
52 struct drm_device *dev = pci_get_drvdata(pdev);
53
54 drm_put_dev(dev);
55}
56
57static const struct file_operations mgag200_driver_fops = {
58 .owner = THIS_MODULE,
59 .open = drm_open,
60 .release = drm_release,
61 .unlocked_ioctl = drm_ioctl,
62 .mmap = mgag200_mmap,
63 .poll = drm_poll,
64 .fasync = drm_fasync,
65 .read = drm_read,
66};
67
68static struct drm_driver driver = {
69 .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_USE_MTRR,
70 .load = mgag200_driver_load,
71 .unload = mgag200_driver_unload,
72 .fops = &mgag200_driver_fops,
73 .name = DRIVER_NAME,
74 .desc = DRIVER_DESC,
75 .date = DRIVER_DATE,
76 .major = DRIVER_MAJOR,
77 .minor = DRIVER_MINOR,
78 .patchlevel = DRIVER_PATCHLEVEL,
79
80 .gem_init_object = mgag200_gem_init_object,
81 .gem_free_object = mgag200_gem_free_object,
82 .dumb_create = mgag200_dumb_create,
83 .dumb_map_offset = mgag200_dumb_mmap_offset,
84 .dumb_destroy = mgag200_dumb_destroy,
85};
86
87static struct pci_driver mgag200_pci_driver = {
88 .name = DRIVER_NAME,
89 .id_table = pciidlist,
90 .probe = mga_pci_probe,
91 .remove = mga_pci_remove,
92};
93
94static int __init mgag200_init(void)
95{
96#ifdef CONFIG_VGA_CONSOLE
97 if (vgacon_text_force() && mgag200_modeset == -1)
98 return -EINVAL;
99#endif
100
101 if (mgag200_modeset == 0)
102 return -EINVAL;
103 return drm_pci_init(&driver, &mgag200_pci_driver);
104}
105
106static void __exit mgag200_exit(void)
107{
108 drm_pci_exit(&driver, &mgag200_pci_driver);
109}
110
111module_init(mgag200_init);
112module_exit(mgag200_exit);
113
114MODULE_AUTHOR(DRIVER_AUTHOR);
115MODULE_DESCRIPTION(DRIVER_DESC);
116MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/mgag200/mgag200_drv.h b/drivers/gpu/drm/mgag200/mgag200_drv.h
new file mode 100644
index 000000000000..6f13b3563234
--- /dev/null
+++ b/drivers/gpu/drm/mgag200/mgag200_drv.h
@@ -0,0 +1,276 @@
1/*
2 * Copyright 2010 Matt Turner.
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 * Matt Turner
11 * Dave Airlie
12 */
13#ifndef __MGAG200_DRV_H__
14#define __MGAG200_DRV_H__
15
16#include <video/vga.h>
17
18#include "drm/drm_fb_helper.h"
19#include "ttm/ttm_bo_api.h"
20#include "ttm/ttm_bo_driver.h"
21#include "ttm/ttm_placement.h"
22#include "ttm/ttm_memory.h"
23#include "ttm/ttm_module.h"
24
25#include <linux/i2c.h>
26#include <linux/i2c-algo-bit.h>
27
28#include "mgag200_reg.h"
29
30#define DRIVER_AUTHOR "Matthew Garrett"
31
32#define DRIVER_NAME "mgag200"
33#define DRIVER_DESC "MGA G200 SE"
34#define DRIVER_DATE "20110418"
35
36#define DRIVER_MAJOR 1
37#define DRIVER_MINOR 0
38#define DRIVER_PATCHLEVEL 0
39
40#define MGAG200FB_CONN_LIMIT 1
41
42#define RREG8(reg) ioread8(((void __iomem *)mdev->rmmio) + (reg))
43#define WREG8(reg, v) iowrite8(v, ((void __iomem *)mdev->rmmio) + (reg))
44#define RREG32(reg) ioread32(((void __iomem *)mdev->rmmio) + (reg))
45#define WREG32(reg, v) iowrite32(v, ((void __iomem *)mdev->rmmio) + (reg))
46
47#define ATTR_INDEX 0x1fc0
48#define ATTR_DATA 0x1fc1
49
50#define WREG_ATTR(reg, v) \
51 do { \
52 RREG8(0x1fda); \
53 WREG8(ATTR_INDEX, reg); \
54 WREG8(ATTR_DATA, v); \
55 } while (0) \
56
57#define WREG_SEQ(reg, v) \
58 do { \
59 WREG8(MGAREG_SEQ_INDEX, reg); \
60 WREG8(MGAREG_SEQ_DATA, v); \
61 } while (0) \
62
63#define WREG_CRT(reg, v) \
64 do { \
65 WREG8(MGAREG_CRTC_INDEX, reg); \
66 WREG8(MGAREG_CRTC_DATA, v); \
67 } while (0) \
68
69
70#define WREG_ECRT(reg, v) \
71 do { \
72 WREG8(MGAREG_CRTCEXT_INDEX, reg); \
73 WREG8(MGAREG_CRTCEXT_DATA, v); \
74 } while (0) \
75
76#define GFX_INDEX 0x1fce
77#define GFX_DATA 0x1fcf
78
79#define WREG_GFX(reg, v) \
80 do { \
81 WREG8(GFX_INDEX, reg); \
82 WREG8(GFX_DATA, v); \
83 } while (0) \
84
85#define DAC_INDEX 0x3c00
86#define DAC_DATA 0x3c0a
87
88#define WREG_DAC(reg, v) \
89 do { \
90 WREG8(DAC_INDEX, reg); \
91 WREG8(DAC_DATA, v); \
92 } while (0) \
93
94#define MGA_MISC_OUT 0x1fc2
95#define MGA_MISC_IN 0x1fcc
96
97#define MGAG200_MAX_FB_HEIGHT 4096
98#define MGAG200_MAX_FB_WIDTH 4096
99
100#define MATROX_DPMS_CLEARED (-1)
101
102#define to_mga_crtc(x) container_of(x, struct mga_crtc, base)
103#define to_mga_encoder(x) container_of(x, struct mga_encoder, base)
104#define to_mga_connector(x) container_of(x, struct mga_connector, base)
105#define to_mga_framebuffer(x) container_of(x, struct mga_framebuffer, base)
106
107struct mga_framebuffer {
108 struct drm_framebuffer base;
109 struct drm_gem_object *obj;
110};
111
112struct mga_fbdev {
113 struct drm_fb_helper helper;
114 struct mga_framebuffer mfb;
115 struct list_head fbdev_list;
116 void *sysram;
117 int size;
118 struct ttm_bo_kmap_obj mapping;
119};
120
121struct mga_crtc {
122 struct drm_crtc base;
123 u8 lut_r[256], lut_g[256], lut_b[256];
124 int last_dpms;
125 bool enabled;
126};
127
128struct mga_mode_info {
129 bool mode_config_initialized;
130 struct mga_crtc *crtc;
131};
132
133struct mga_encoder {
134 struct drm_encoder base;
135 int last_dpms;
136};
137
138
139struct mga_i2c_chan {
140 struct i2c_adapter adapter;
141 struct drm_device *dev;
142 struct i2c_algo_bit_data bit;
143 int data, clock;
144};
145
146struct mga_connector {
147 struct drm_connector base;
148 struct mga_i2c_chan *i2c;
149};
150
151
152struct mga_mc {
153 resource_size_t vram_size;
154 resource_size_t vram_base;
155 resource_size_t vram_window;
156};
157
158enum mga_type {
159 G200_SE_A,
160 G200_SE_B,
161 G200_WB,
162 G200_EV,
163 G200_EH,
164 G200_ER,
165};
166
167#define IS_G200_SE(mdev) (mdev->type == G200_SE_A || mdev->type == G200_SE_B)
168
169struct mga_device {
170 struct drm_device *dev;
171 unsigned long flags;
172
173 resource_size_t rmmio_base;
174 resource_size_t rmmio_size;
175 void __iomem *rmmio;
176
177 drm_local_map_t *framebuffer;
178
179 struct mga_mc mc;
180 struct mga_mode_info mode_info;
181
182 struct mga_fbdev *mfbdev;
183
184 bool suspended;
185 int num_crtc;
186 enum mga_type type;
187 int has_sdram;
188 struct drm_display_mode mode;
189
190 int bpp_shifts[4];
191
192 int fb_mtrr;
193
194 struct {
195 struct drm_global_reference mem_global_ref;
196 struct ttm_bo_global_ref bo_global_ref;
197 struct ttm_bo_device bdev;
198 atomic_t validate_sequence;
199 } ttm;
200
201 u32 reg_1e24; /* SE model number */
202};
203
204
205struct mgag200_bo {
206 struct ttm_buffer_object bo;
207 struct ttm_placement placement;
208 struct ttm_bo_kmap_obj kmap;
209 struct drm_gem_object gem;
210 u32 placements[3];
211 int pin_count;
212};
213#define gem_to_mga_bo(gobj) container_of((gobj), struct mgag200_bo, gem)
214
215static inline struct mgag200_bo *
216mgag200_bo(struct ttm_buffer_object *bo)
217{
218 return container_of(bo, struct mgag200_bo, bo);
219}
220 /* mga_crtc.c */
221void mga_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
222 u16 blue, int regno);
223void mga_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
224 u16 *blue, int regno);
225
226 /* mgag200_mode.c */
227int mgag200_modeset_init(struct mga_device *mdev);
228void mgag200_modeset_fini(struct mga_device *mdev);
229
230 /* mga_fbdev.c */
231int mgag200_fbdev_init(struct mga_device *mdev);
232void mgag200_fbdev_fini(struct mga_device *mdev);
233
234 /* mgag200_main.c */
235int mgag200_framebuffer_init(struct drm_device *dev,
236 struct mga_framebuffer *mfb,
237 struct drm_mode_fb_cmd2 *mode_cmd,
238 struct drm_gem_object *obj);
239
240
241int mgag200_driver_load(struct drm_device *dev, unsigned long flags);
242int mgag200_driver_unload(struct drm_device *dev);
243int mgag200_gem_create(struct drm_device *dev,
244 u32 size, bool iskernel,
245 struct drm_gem_object **obj);
246int mgag200_gem_init_object(struct drm_gem_object *obj);
247int mgag200_dumb_create(struct drm_file *file,
248 struct drm_device *dev,
249 struct drm_mode_create_dumb *args);
250int mgag200_dumb_destroy(struct drm_file *file,
251 struct drm_device *dev,
252 uint32_t handle);
253void mgag200_gem_free_object(struct drm_gem_object *obj);
254int
255mgag200_dumb_mmap_offset(struct drm_file *file,
256 struct drm_device *dev,
257 uint32_t handle,
258 uint64_t *offset);
259 /* mga_i2c.c */
260struct mga_i2c_chan *mgag200_i2c_create(struct drm_device *dev);
261void mgag200_i2c_destroy(struct mga_i2c_chan *i2c);
262
263#define DRM_FILE_PAGE_OFFSET (0x100000000ULL >> PAGE_SHIFT)
264void mgag200_ttm_placement(struct mgag200_bo *bo, int domain);
265
266int mgag200_bo_reserve(struct mgag200_bo *bo, bool no_wait);
267void mgag200_bo_unreserve(struct mgag200_bo *bo);
268int mgag200_bo_create(struct drm_device *dev, int size, int align,
269 uint32_t flags, struct mgag200_bo **pastbo);
270int mgag200_mm_init(struct mga_device *mdev);
271void mgag200_mm_fini(struct mga_device *mdev);
272int mgag200_mmap(struct file *filp, struct vm_area_struct *vma);
273int mgag200_bo_pin(struct mgag200_bo *bo, u32 pl_flag, u64 *gpu_addr);
274int mgag200_bo_unpin(struct mgag200_bo *bo);
275int mgag200_bo_push_sysram(struct mgag200_bo *bo);
276#endif /* __MGAG200_DRV_H__ */
diff --git a/drivers/gpu/drm/mgag200/mgag200_fb.c b/drivers/gpu/drm/mgag200/mgag200_fb.c
new file mode 100644
index 000000000000..880d3369760e
--- /dev/null
+++ b/drivers/gpu/drm/mgag200/mgag200_fb.c
@@ -0,0 +1,294 @@
1/*
2 * Copyright 2010 Matt Turner.
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 * Matt Turner
11 * Dave Airlie
12 */
13#include <linux/module.h>
14#include "drmP.h"
15#include "drm.h"
16#include "drm_fb_helper.h"
17
18#include <linux/fb.h>
19
20#include "mgag200_drv.h"
21
22static void mga_dirty_update(struct mga_fbdev *mfbdev,
23 int x, int y, int width, int height)
24{
25 int i;
26 struct drm_gem_object *obj;
27 struct mgag200_bo *bo;
28 int src_offset, dst_offset;
29 int bpp = (mfbdev->mfb.base.bits_per_pixel + 7)/8;
30 int ret;
31 bool unmap = false;
32
33 obj = mfbdev->mfb.obj;
34 bo = gem_to_mga_bo(obj);
35
36 ret = mgag200_bo_reserve(bo, true);
37 if (ret) {
38 DRM_ERROR("failed to reserve fb bo\n");
39 return;
40 }
41
42 if (!bo->kmap.virtual) {
43 ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap);
44 if (ret) {
45 DRM_ERROR("failed to kmap fb updates\n");
46 mgag200_bo_unreserve(bo);
47 return;
48 }
49 unmap = true;
50 }
51 for (i = y; i < y + height; i++) {
52 /* assume equal stride for now */
53 src_offset = dst_offset = i * mfbdev->mfb.base.pitches[0] + (x * bpp);
54 memcpy_toio(bo->kmap.virtual + src_offset, mfbdev->sysram + src_offset, width * bpp);
55
56 }
57 if (unmap)
58 ttm_bo_kunmap(&bo->kmap);
59
60 mgag200_bo_unreserve(bo);
61}
62
63static void mga_fillrect(struct fb_info *info,
64 const struct fb_fillrect *rect)
65{
66 struct mga_fbdev *mfbdev = info->par;
67 sys_fillrect(info, rect);
68 mga_dirty_update(mfbdev, rect->dx, rect->dy, rect->width,
69 rect->height);
70}
71
72static void mga_copyarea(struct fb_info *info,
73 const struct fb_copyarea *area)
74{
75 struct mga_fbdev *mfbdev = info->par;
76 sys_copyarea(info, area);
77 mga_dirty_update(mfbdev, area->dx, area->dy, area->width,
78 area->height);
79}
80
81static void mga_imageblit(struct fb_info *info,
82 const struct fb_image *image)
83{
84 struct mga_fbdev *mfbdev = info->par;
85 sys_imageblit(info, image);
86 mga_dirty_update(mfbdev, image->dx, image->dy, image->width,
87 image->height);
88}
89
90
91static struct fb_ops mgag200fb_ops = {
92 .owner = THIS_MODULE,
93 .fb_check_var = drm_fb_helper_check_var,
94 .fb_set_par = drm_fb_helper_set_par,
95 .fb_fillrect = mga_fillrect,
96 .fb_copyarea = mga_copyarea,
97 .fb_imageblit = mga_imageblit,
98 .fb_pan_display = drm_fb_helper_pan_display,
99 .fb_blank = drm_fb_helper_blank,
100 .fb_setcmap = drm_fb_helper_setcmap,
101};
102
103static int mgag200fb_create_object(struct mga_fbdev *afbdev,
104 struct drm_mode_fb_cmd2 *mode_cmd,
105 struct drm_gem_object **gobj_p)
106{
107 struct drm_device *dev = afbdev->helper.dev;
108 u32 bpp, depth;
109 u32 size;
110 struct drm_gem_object *gobj;
111
112 int ret = 0;
113 drm_fb_get_bpp_depth(mode_cmd->pixel_format, &depth, &bpp);
114
115 size = mode_cmd->pitches[0] * mode_cmd->height;
116 ret = mgag200_gem_create(dev, size, true, &gobj);
117 if (ret)
118 return ret;
119
120 *gobj_p = gobj;
121 return ret;
122}
123
124static int mgag200fb_create(struct mga_fbdev *mfbdev,
125 struct drm_fb_helper_surface_size *sizes)
126{
127 struct drm_device *dev = mfbdev->helper.dev;
128 struct drm_mode_fb_cmd2 mode_cmd;
129 struct mga_device *mdev = dev->dev_private;
130 struct fb_info *info;
131 struct drm_framebuffer *fb;
132 struct drm_gem_object *gobj = NULL;
133 struct device *device = &dev->pdev->dev;
134 struct mgag200_bo *bo;
135 int ret;
136 void *sysram;
137 int size;
138
139 mode_cmd.width = sizes->surface_width;
140 mode_cmd.height = sizes->surface_height;
141 mode_cmd.pitches[0] = mode_cmd.width * ((sizes->surface_bpp + 7) / 8);
142
143 mode_cmd.pixel_format = drm_mode_legacy_fb_format(sizes->surface_bpp,
144 sizes->surface_depth);
145 size = mode_cmd.pitches[0] * mode_cmd.height;
146
147 ret = mgag200fb_create_object(mfbdev, &mode_cmd, &gobj);
148 if (ret) {
149 DRM_ERROR("failed to create fbcon backing object %d\n", ret);
150 return ret;
151 }
152 bo = gem_to_mga_bo(gobj);
153
154 sysram = vmalloc(size);
155 if (!sysram)
156 return -ENOMEM;
157
158 info = framebuffer_alloc(0, device);
159 if (info == NULL)
160 return -ENOMEM;
161
162 info->par = mfbdev;
163
164 ret = mgag200_framebuffer_init(dev, &mfbdev->mfb, &mode_cmd, gobj);
165 if (ret)
166 return ret;
167
168 mfbdev->sysram = sysram;
169 mfbdev->size = size;
170
171 fb = &mfbdev->mfb.base;
172
173 /* setup helper */
174 mfbdev->helper.fb = fb;
175 mfbdev->helper.fbdev = info;
176
177 ret = fb_alloc_cmap(&info->cmap, 256, 0);
178 if (ret) {
179 DRM_ERROR("%s: can't allocate color map\n", info->fix.id);
180 ret = -ENOMEM;
181 goto out;
182 }
183
184 strcpy(info->fix.id, "mgadrmfb");
185
186 info->flags = FBINFO_DEFAULT | FBINFO_CAN_FORCE_OUTPUT;
187 info->fbops = &mgag200fb_ops;
188
189 /* setup aperture base/size for vesafb takeover */
190 info->apertures = alloc_apertures(1);
191 if (!info->apertures) {
192 ret = -ENOMEM;
193 goto out;
194 }
195 info->apertures->ranges[0].base = mdev->dev->mode_config.fb_base;
196 info->apertures->ranges[0].size = mdev->mc.vram_size;
197
198 drm_fb_helper_fill_fix(info, fb->pitches[0], fb->depth);
199 drm_fb_helper_fill_var(info, &mfbdev->helper, sizes->fb_width,
200 sizes->fb_height);
201
202 info->screen_base = sysram;
203 info->screen_size = size;
204 info->pixmap.flags = FB_PIXMAP_SYSTEM;
205
206 DRM_DEBUG_KMS("allocated %dx%d\n",
207 fb->width, fb->height);
208 return 0;
209out:
210 return ret;
211}
212
213static int mga_fb_find_or_create_single(struct drm_fb_helper *helper,
214 struct drm_fb_helper_surface_size
215 *sizes)
216{
217 struct mga_fbdev *mfbdev = (struct mga_fbdev *)helper;
218 int new_fb = 0;
219 int ret;
220
221 if (!helper->fb) {
222 ret = mgag200fb_create(mfbdev, sizes);
223 if (ret)
224 return ret;
225 new_fb = 1;
226 }
227 return new_fb;
228}
229
230static int mga_fbdev_destroy(struct drm_device *dev,
231 struct mga_fbdev *mfbdev)
232{
233 struct fb_info *info;
234 struct mga_framebuffer *mfb = &mfbdev->mfb;
235
236 if (mfbdev->helper.fbdev) {
237 info = mfbdev->helper.fbdev;
238
239 unregister_framebuffer(info);
240 if (info->cmap.len)
241 fb_dealloc_cmap(&info->cmap);
242 framebuffer_release(info);
243 }
244
245 if (mfb->obj) {
246 drm_gem_object_unreference_unlocked(mfb->obj);
247 mfb->obj = NULL;
248 }
249 drm_fb_helper_fini(&mfbdev->helper);
250 vfree(mfbdev->sysram);
251 drm_framebuffer_cleanup(&mfb->base);
252
253 return 0;
254}
255
256static struct drm_fb_helper_funcs mga_fb_helper_funcs = {
257 .gamma_set = mga_crtc_fb_gamma_set,
258 .gamma_get = mga_crtc_fb_gamma_get,
259 .fb_probe = mga_fb_find_or_create_single,
260};
261
262int mgag200_fbdev_init(struct mga_device *mdev)
263{
264 struct mga_fbdev *mfbdev;
265 int ret;
266
267 mfbdev = kzalloc(sizeof(struct mga_fbdev), GFP_KERNEL);
268 if (!mfbdev)
269 return -ENOMEM;
270
271 mdev->mfbdev = mfbdev;
272 mfbdev->helper.funcs = &mga_fb_helper_funcs;
273
274 ret = drm_fb_helper_init(mdev->dev, &mfbdev->helper,
275 mdev->num_crtc, MGAG200FB_CONN_LIMIT);
276 if (ret) {
277 kfree(mfbdev);
278 return ret;
279 }
280 drm_fb_helper_single_add_all_connectors(&mfbdev->helper);
281 drm_fb_helper_initial_config(&mfbdev->helper, 32);
282
283 return 0;
284}
285
286void mgag200_fbdev_fini(struct mga_device *mdev)
287{
288 if (!mdev->mfbdev)
289 return;
290
291 mga_fbdev_destroy(mdev->dev, mdev->mfbdev);
292 kfree(mdev->mfbdev);
293 mdev->mfbdev = NULL;
294}
diff --git a/drivers/gpu/drm/mgag200/mgag200_i2c.c b/drivers/gpu/drm/mgag200/mgag200_i2c.c
new file mode 100644
index 000000000000..dd3568a1b6b0
--- /dev/null
+++ b/drivers/gpu/drm/mgag200/mgag200_i2c.c
@@ -0,0 +1,156 @@
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 <linux/export.h>
29#include <linux/i2c.h>
30#include <linux/i2c-algo-bit.h>
31#include "drmP.h"
32#include "drm.h"
33
34#include "mgag200_drv.h"
35
36static int mga_i2c_read_gpio(struct mga_device *mdev)
37{
38 WREG8(DAC_INDEX, MGA1064_GEN_IO_DATA);
39 return RREG8(DAC_DATA);
40}
41
42static void mga_i2c_set_gpio(struct mga_device *mdev, int mask, int val)
43{
44 int tmp;
45
46 WREG8(DAC_INDEX, MGA1064_GEN_IO_CTL);
47 tmp = (RREG8(DAC_DATA) & mask) | val;
48 WREG_DAC(MGA1064_GEN_IO_CTL, tmp);
49 WREG_DAC(MGA1064_GEN_IO_DATA, 0);
50}
51
52static inline void mga_i2c_set(struct mga_device *mdev, int mask, int state)
53{
54 if (state)
55 state = 0;
56 else
57 state = mask;
58 mga_i2c_set_gpio(mdev, ~mask, state);
59}
60
61static void mga_gpio_setsda(void *data, int state)
62{
63 struct mga_i2c_chan *i2c = data;
64 struct mga_device *mdev = i2c->dev->dev_private;
65 mga_i2c_set(mdev, i2c->data, state);
66}
67
68static void mga_gpio_setscl(void *data, int state)
69{
70 struct mga_i2c_chan *i2c = data;
71 struct mga_device *mdev = i2c->dev->dev_private;
72 mga_i2c_set(mdev, i2c->clock, state);
73}
74
75static int mga_gpio_getsda(void *data)
76{
77 struct mga_i2c_chan *i2c = data;
78 struct mga_device *mdev = i2c->dev->dev_private;
79 return (mga_i2c_read_gpio(mdev) & i2c->data) ? 1 : 0;
80}
81
82static int mga_gpio_getscl(void *data)
83{
84 struct mga_i2c_chan *i2c = data;
85 struct mga_device *mdev = i2c->dev->dev_private;
86 return (mga_i2c_read_gpio(mdev) & i2c->clock) ? 1 : 0;
87}
88
89struct mga_i2c_chan *mgag200_i2c_create(struct drm_device *dev)
90{
91 struct mga_device *mdev = dev->dev_private;
92 struct mga_i2c_chan *i2c;
93 int ret;
94 int data, clock;
95
96 WREG_DAC(MGA1064_GEN_IO_DATA, 0xff);
97 WREG_DAC(MGA1064_GEN_IO_CTL, 0);
98
99 switch (mdev->type) {
100 case G200_SE_A:
101 case G200_SE_B:
102 case G200_EV:
103 case G200_WB:
104 data = 1;
105 clock = 2;
106 break;
107 case G200_EH:
108 case G200_ER:
109 data = 2;
110 clock = 1;
111 break;
112 default:
113 data = 2;
114 clock = 8;
115 break;
116 }
117
118 i2c = kzalloc(sizeof(struct mga_i2c_chan), GFP_KERNEL);
119 if (!i2c)
120 return NULL;
121
122 i2c->data = data;
123 i2c->clock = clock;
124 i2c->adapter.owner = THIS_MODULE;
125 i2c->adapter.class = I2C_CLASS_DDC;
126 i2c->adapter.dev.parent = &dev->pdev->dev;
127 i2c->dev = dev;
128 i2c_set_adapdata(&i2c->adapter, i2c);
129 snprintf(i2c->adapter.name, sizeof(i2c->adapter.name), "mga i2c");
130
131 i2c->adapter.algo_data = &i2c->bit;
132
133 i2c->bit.udelay = 10;
134 i2c->bit.timeout = 2;
135 i2c->bit.data = i2c;
136 i2c->bit.setsda = mga_gpio_setsda;
137 i2c->bit.setscl = mga_gpio_setscl;
138 i2c->bit.getsda = mga_gpio_getsda;
139 i2c->bit.getscl = mga_gpio_getscl;
140
141 ret = i2c_bit_add_bus(&i2c->adapter);
142 if (ret) {
143 kfree(i2c);
144 i2c = NULL;
145 }
146 return i2c;
147}
148
149void mgag200_i2c_destroy(struct mga_i2c_chan *i2c)
150{
151 if (!i2c)
152 return;
153 i2c_del_adapter(&i2c->adapter);
154 kfree(i2c);
155}
156
diff --git a/drivers/gpu/drm/mgag200/mgag200_main.c b/drivers/gpu/drm/mgag200/mgag200_main.c
new file mode 100644
index 000000000000..636a81cd2f37
--- /dev/null
+++ b/drivers/gpu/drm/mgag200/mgag200_main.c
@@ -0,0 +1,388 @@
1/*
2 * Copyright 2010 Matt Turner.
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 * Matt Turner
11 * Dave Airlie
12 */
13#include "drmP.h"
14#include "drm.h"
15#include "drm_crtc_helper.h"
16#include "mgag200_drv.h"
17
18static void mga_user_framebuffer_destroy(struct drm_framebuffer *fb)
19{
20 struct mga_framebuffer *mga_fb = to_mga_framebuffer(fb);
21 if (mga_fb->obj)
22 drm_gem_object_unreference_unlocked(mga_fb->obj);
23 drm_framebuffer_cleanup(fb);
24 kfree(fb);
25}
26
27static int mga_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 mga_fb_funcs = {
35 .destroy = mga_user_framebuffer_destroy,
36 .create_handle = mga_user_framebuffer_create_handle,
37};
38
39int mgag200_framebuffer_init(struct drm_device *dev,
40 struct mga_framebuffer *gfb,
41 struct drm_mode_fb_cmd2 *mode_cmd,
42 struct drm_gem_object *obj)
43{
44 int ret = drm_framebuffer_init(dev, &gfb->base, &mga_fb_funcs);
45 if (ret) {
46 DRM_ERROR("drm_framebuffer_init failed: %d\n", ret);
47 return ret;
48 }
49 drm_helper_mode_fill_fb_struct(&gfb->base, mode_cmd);
50 gfb->obj = obj;
51 return 0;
52}
53
54static struct drm_framebuffer *
55mgag200_user_framebuffer_create(struct drm_device *dev,
56 struct drm_file *filp,
57 struct drm_mode_fb_cmd2 *mode_cmd)
58{
59 struct drm_gem_object *obj;
60 struct mga_framebuffer *mga_fb;
61 int ret;
62
63 obj = drm_gem_object_lookup(dev, filp, mode_cmd->handles[0]);
64 if (obj == NULL)
65 return ERR_PTR(-ENOENT);
66
67 mga_fb = kzalloc(sizeof(*mga_fb), GFP_KERNEL);
68 if (!mga_fb) {
69 drm_gem_object_unreference_unlocked(obj);
70 return ERR_PTR(-ENOMEM);
71 }
72
73 ret = mgag200_framebuffer_init(dev, mga_fb, mode_cmd, obj);
74 if (ret) {
75 drm_gem_object_unreference_unlocked(obj);
76 kfree(mga_fb);
77 return ERR_PTR(ret);
78 }
79 return &mga_fb->base;
80}
81
82static const struct drm_mode_config_funcs mga_mode_funcs = {
83 .fb_create = mgag200_user_framebuffer_create,
84};
85
86/* Unmap the framebuffer from the core and release the memory */
87static void mga_vram_fini(struct mga_device *mdev)
88{
89 pci_iounmap(mdev->dev->pdev, mdev->rmmio);
90 mdev->rmmio = NULL;
91 if (mdev->mc.vram_base)
92 release_mem_region(mdev->mc.vram_base, mdev->mc.vram_window);
93}
94
95static int mga_probe_vram(struct mga_device *mdev, void __iomem *mem)
96{
97 int offset;
98 int orig;
99 int test1, test2;
100 int orig1, orig2;
101
102 /* Probe */
103 orig = ioread16(mem);
104 iowrite16(0, mem);
105
106 for (offset = 0x100000; offset < mdev->mc.vram_window; offset += 0x4000) {
107 orig1 = ioread8(mem + offset);
108 orig2 = ioread8(mem + offset + 0x100);
109
110 iowrite16(0xaa55, mem + offset);
111 iowrite16(0xaa55, mem + offset + 0x100);
112
113 test1 = ioread16(mem + offset);
114 test2 = ioread16(mem);
115
116 iowrite16(orig1, mem + offset);
117 iowrite16(orig2, mem + offset + 0x100);
118
119 if (test1 != 0xaa55) {
120 break;
121 }
122
123 if (test2) {
124 break;
125 }
126 }
127
128 iowrite16(orig, mem);
129 return offset - 65536;
130}
131
132/* Map the framebuffer from the card and configure the core */
133static int mga_vram_init(struct mga_device *mdev)
134{
135 void __iomem *mem;
136 struct apertures_struct *aper = alloc_apertures(1);
137
138 /* BAR 0 is VRAM */
139 mdev->mc.vram_base = pci_resource_start(mdev->dev->pdev, 0);
140 mdev->mc.vram_window = pci_resource_len(mdev->dev->pdev, 0);
141
142 aper->ranges[0].base = mdev->mc.vram_base;
143 aper->ranges[0].size = mdev->mc.vram_window;
144 aper->count = 1;
145
146 remove_conflicting_framebuffers(aper, "mgafb", true);
147
148 if (!request_mem_region(mdev->mc.vram_base, mdev->mc.vram_window,
149 "mgadrmfb_vram")) {
150 DRM_ERROR("can't reserve VRAM\n");
151 return -ENXIO;
152 }
153
154 mem = pci_iomap(mdev->dev->pdev, 0, 0);
155
156 mdev->mc.vram_size = mga_probe_vram(mdev, mem);
157
158 pci_iounmap(mdev->dev->pdev, mem);
159
160 return 0;
161}
162
163static int mgag200_device_init(struct drm_device *dev,
164 uint32_t flags)
165{
166 struct mga_device *mdev = dev->dev_private;
167 int ret, option;
168
169 mdev->type = flags;
170
171 /* Hardcode the number of CRTCs to 1 */
172 mdev->num_crtc = 1;
173
174 pci_read_config_dword(dev->pdev, PCI_MGA_OPTION, &option);
175 mdev->has_sdram = !(option & (1 << 14));
176
177 /* BAR 0 is the framebuffer, BAR 1 contains registers */
178 mdev->rmmio_base = pci_resource_start(mdev->dev->pdev, 1);
179 mdev->rmmio_size = pci_resource_len(mdev->dev->pdev, 1);
180
181 if (!request_mem_region(mdev->rmmio_base, mdev->rmmio_size,
182 "mgadrmfb_mmio")) {
183 DRM_ERROR("can't reserve mmio registers\n");
184 return -ENOMEM;
185 }
186
187 mdev->rmmio = pci_iomap(dev->pdev, 1, 0);
188 if (mdev->rmmio == NULL)
189 return -ENOMEM;
190
191 /* stash G200 SE model number for later use */
192 if (IS_G200_SE(mdev))
193 mdev->reg_1e24 = RREG32(0x1e24);
194
195 ret = mga_vram_init(mdev);
196 if (ret) {
197 release_mem_region(mdev->rmmio_base, mdev->rmmio_size);
198 return ret;
199 }
200
201 mdev->bpp_shifts[0] = 0;
202 mdev->bpp_shifts[1] = 1;
203 mdev->bpp_shifts[2] = 0;
204 mdev->bpp_shifts[3] = 2;
205 return 0;
206}
207
208void mgag200_device_fini(struct mga_device *mdev)
209{
210 release_mem_region(mdev->rmmio_base, mdev->rmmio_size);
211 mga_vram_fini(mdev);
212}
213
214/*
215 * Functions here will be called by the core once it's bound the driver to
216 * a PCI device
217 */
218
219
220int mgag200_driver_load(struct drm_device *dev, unsigned long flags)
221{
222 struct mga_device *mdev;
223 int r;
224
225 mdev = kzalloc(sizeof(struct mga_device), GFP_KERNEL);
226 if (mdev == NULL)
227 return -ENOMEM;
228 dev->dev_private = (void *)mdev;
229 mdev->dev = dev;
230
231 r = mgag200_device_init(dev, flags);
232 if (r) {
233 dev_err(&dev->pdev->dev, "Fatal error during GPU init: %d\n", r);
234 goto out;
235 }
236 r = mgag200_mm_init(mdev);
237 if (r)
238 goto out;
239
240 drm_mode_config_init(dev);
241 dev->mode_config.funcs = (void *)&mga_mode_funcs;
242 dev->mode_config.min_width = 0;
243 dev->mode_config.min_height = 0;
244 dev->mode_config.preferred_depth = 24;
245 dev->mode_config.prefer_shadow = 1;
246
247 r = mgag200_modeset_init(mdev);
248 if (r)
249 dev_err(&dev->pdev->dev, "Fatal error during modeset init: %d\n", r);
250out:
251 if (r)
252 mgag200_driver_unload(dev);
253 return r;
254}
255
256int mgag200_driver_unload(struct drm_device *dev)
257{
258 struct mga_device *mdev = dev->dev_private;
259
260 if (mdev == NULL)
261 return 0;
262 mgag200_modeset_fini(mdev);
263 mgag200_fbdev_fini(mdev);
264 drm_mode_config_cleanup(dev);
265 mgag200_mm_fini(mdev);
266 mgag200_device_fini(mdev);
267 kfree(mdev);
268 dev->dev_private = NULL;
269 return 0;
270}
271
272int mgag200_gem_create(struct drm_device *dev,
273 u32 size, bool iskernel,
274 struct drm_gem_object **obj)
275{
276 struct mgag200_bo *astbo;
277 int ret;
278
279 *obj = NULL;
280
281 size = roundup(size, PAGE_SIZE);
282 if (size == 0)
283 return -EINVAL;
284
285 ret = mgag200_bo_create(dev, size, 0, 0, &astbo);
286 if (ret) {
287 if (ret != -ERESTARTSYS)
288 DRM_ERROR("failed to allocate GEM object\n");
289 return ret;
290 }
291 *obj = &astbo->gem;
292 return 0;
293}
294
295int mgag200_dumb_create(struct drm_file *file,
296 struct drm_device *dev,
297 struct drm_mode_create_dumb *args)
298{
299 int ret;
300 struct drm_gem_object *gobj;
301 u32 handle;
302
303 args->pitch = args->width * ((args->bpp + 7) / 8);
304 args->size = args->pitch * args->height;
305
306 ret = mgag200_gem_create(dev, args->size, false,
307 &gobj);
308 if (ret)
309 return ret;
310
311 ret = drm_gem_handle_create(file, gobj, &handle);
312 drm_gem_object_unreference_unlocked(gobj);
313 if (ret)
314 return ret;
315
316 args->handle = handle;
317 return 0;
318}
319
320int mgag200_dumb_destroy(struct drm_file *file,
321 struct drm_device *dev,
322 uint32_t handle)
323{
324 return drm_gem_handle_delete(file, handle);
325}
326
327int mgag200_gem_init_object(struct drm_gem_object *obj)
328{
329 BUG();
330 return 0;
331}
332
333void mgag200_bo_unref(struct mgag200_bo **bo)
334{
335 struct ttm_buffer_object *tbo;
336
337 if ((*bo) == NULL)
338 return;
339
340 tbo = &((*bo)->bo);
341 ttm_bo_unref(&tbo);
342 if (tbo == NULL)
343 *bo = NULL;
344
345}
346
347void mgag200_gem_free_object(struct drm_gem_object *obj)
348{
349 struct mgag200_bo *mgag200_bo = gem_to_mga_bo(obj);
350
351 if (!mgag200_bo)
352 return;
353 mgag200_bo_unref(&mgag200_bo);
354}
355
356
357static inline u64 mgag200_bo_mmap_offset(struct mgag200_bo *bo)
358{
359 return bo->bo.addr_space_offset;
360}
361
362int
363mgag200_dumb_mmap_offset(struct drm_file *file,
364 struct drm_device *dev,
365 uint32_t handle,
366 uint64_t *offset)
367{
368 struct drm_gem_object *obj;
369 int ret;
370 struct mgag200_bo *bo;
371
372 mutex_lock(&dev->struct_mutex);
373 obj = drm_gem_object_lookup(dev, file, handle);
374 if (obj == NULL) {
375 ret = -ENOENT;
376 goto out_unlock;
377 }
378
379 bo = gem_to_mga_bo(obj);
380 *offset = mgag200_bo_mmap_offset(bo);
381
382 drm_gem_object_unreference(obj);
383 ret = 0;
384out_unlock:
385 mutex_unlock(&dev->struct_mutex);
386 return ret;
387
388}
diff --git a/drivers/gpu/drm/mgag200/mgag200_mode.c b/drivers/gpu/drm/mgag200/mgag200_mode.c
new file mode 100644
index 000000000000..d303061b251e
--- /dev/null
+++ b/drivers/gpu/drm/mgag200/mgag200_mode.c
@@ -0,0 +1,1533 @@
1/*
2 * Copyright 2010 Matt Turner.
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 * Matt Turner
11 * Dave Airlie
12 */
13
14#include <linux/delay.h>
15
16#include "drmP.h"
17#include "drm.h"
18#include "drm_crtc_helper.h"
19
20#include "mgag200_drv.h"
21
22#define MGAG200_LUT_SIZE 256
23
24/*
25 * This file contains setup code for the CRTC.
26 */
27
28static void mga_crtc_load_lut(struct drm_crtc *crtc)
29{
30 struct mga_crtc *mga_crtc = to_mga_crtc(crtc);
31 struct drm_device *dev = crtc->dev;
32 struct mga_device *mdev = dev->dev_private;
33 int i;
34
35 if (!crtc->enabled)
36 return;
37
38 WREG8(DAC_INDEX + MGA1064_INDEX, 0);
39
40 for (i = 0; i < MGAG200_LUT_SIZE; i++) {
41 /* VGA registers */
42 WREG8(DAC_INDEX + MGA1064_COL_PAL, mga_crtc->lut_r[i]);
43 WREG8(DAC_INDEX + MGA1064_COL_PAL, mga_crtc->lut_g[i]);
44 WREG8(DAC_INDEX + MGA1064_COL_PAL, mga_crtc->lut_b[i]);
45 }
46}
47
48static inline void mga_wait_vsync(struct mga_device *mdev)
49{
50 unsigned int count = 0;
51 unsigned int status = 0;
52
53 do {
54 status = RREG32(MGAREG_Status);
55 count++;
56 } while ((status & 0x08) && (count < 250000));
57 count = 0;
58 status = 0;
59 do {
60 status = RREG32(MGAREG_Status);
61 count++;
62 } while (!(status & 0x08) && (count < 250000));
63}
64
65static inline void mga_wait_busy(struct mga_device *mdev)
66{
67 unsigned int count = 0;
68 unsigned int status = 0;
69 do {
70 status = RREG8(MGAREG_Status + 2);
71 count++;
72 } while ((status & 0x01) && (count < 500000));
73}
74
75/*
76 * The core passes the desired mode to the CRTC code to see whether any
77 * CRTC-specific modifications need to be made to it. We're in a position
78 * to just pass that straight through, so this does nothing
79 */
80static bool mga_crtc_mode_fixup(struct drm_crtc *crtc,
81 struct drm_display_mode *mode,
82 struct drm_display_mode *adjusted_mode)
83{
84 return true;
85}
86
87static int mga_g200se_set_plls(struct mga_device *mdev, long clock)
88{
89 unsigned int vcomax, vcomin, pllreffreq;
90 unsigned int delta, tmpdelta, permitteddelta;
91 unsigned int testp, testm, testn;
92 unsigned int p, m, n;
93 unsigned int computed;
94
95 m = n = p = 0;
96 vcomax = 320000;
97 vcomin = 160000;
98 pllreffreq = 25000;
99
100 delta = 0xffffffff;
101 permitteddelta = clock * 5 / 1000;
102
103 for (testp = 8; testp > 0; testp /= 2) {
104 if (clock * testp > vcomax)
105 continue;
106 if (clock * testp < vcomin)
107 continue;
108
109 for (testn = 17; testn < 256; testn++) {
110 for (testm = 1; testm < 32; testm++) {
111 computed = (pllreffreq * testn) /
112 (testm * testp);
113 if (computed > clock)
114 tmpdelta = computed - clock;
115 else
116 tmpdelta = clock - computed;
117 if (tmpdelta < delta) {
118 delta = tmpdelta;
119 m = testm - 1;
120 n = testn - 1;
121 p = testp - 1;
122 }
123 }
124 }
125 }
126
127 if (delta > permitteddelta) {
128 printk(KERN_WARNING "PLL delta too large\n");
129 return 1;
130 }
131
132 WREG_DAC(MGA1064_PIX_PLLC_M, m);
133 WREG_DAC(MGA1064_PIX_PLLC_N, n);
134 WREG_DAC(MGA1064_PIX_PLLC_P, p);
135 return 0;
136}
137
138static int mga_g200wb_set_plls(struct mga_device *mdev, long clock)
139{
140 unsigned int vcomax, vcomin, pllreffreq;
141 unsigned int delta, tmpdelta, permitteddelta;
142 unsigned int testp, testm, testn;
143 unsigned int p, m, n;
144 unsigned int computed;
145 int i, j, tmpcount, vcount;
146 bool pll_locked = false;
147 u8 tmp;
148
149 m = n = p = 0;
150 vcomax = 550000;
151 vcomin = 150000;
152 pllreffreq = 48000;
153
154 delta = 0xffffffff;
155 permitteddelta = clock * 5 / 1000;
156
157 for (testp = 1; testp < 9; testp++) {
158 if (clock * testp > vcomax)
159 continue;
160 if (clock * testp < vcomin)
161 continue;
162
163 for (testm = 1; testm < 17; testm++) {
164 for (testn = 1; testn < 151; testn++) {
165 computed = (pllreffreq * testn) /
166 (testm * testp);
167 if (computed > clock)
168 tmpdelta = computed - clock;
169 else
170 tmpdelta = clock - computed;
171 if (tmpdelta < delta) {
172 delta = tmpdelta;
173 n = testn - 1;
174 m = (testm - 1) | ((n >> 1) & 0x80);
175 p = testp - 1;
176 }
177 }
178 }
179 }
180
181 for (i = 0; i <= 32 && pll_locked == false; i++) {
182 if (i > 0) {
183 WREG8(MGAREG_CRTC_INDEX, 0x1e);
184 tmp = RREG8(MGAREG_CRTC_DATA);
185 if (tmp < 0xff)
186 WREG8(MGAREG_CRTC_DATA, tmp+1);
187 }
188
189 /* set pixclkdis to 1 */
190 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
191 tmp = RREG8(DAC_DATA);
192 tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
193 WREG_DAC(MGA1064_PIX_CLK_CTL_CLK_DIS, tmp);
194
195 WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
196 tmp = RREG8(DAC_DATA);
197 tmp |= MGA1064_REMHEADCTL_CLKDIS;
198 WREG_DAC(MGA1064_REMHEADCTL, tmp);
199
200 /* select PLL Set C */
201 tmp = RREG8(MGAREG_MEM_MISC_READ);
202 tmp |= 0x3 << 2;
203 WREG8(MGAREG_MEM_MISC_WRITE, tmp);
204
205 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
206 tmp = RREG8(DAC_DATA);
207 tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN | 0x80;
208 WREG_DAC(MGA1064_PIX_CLK_CTL, tmp);
209
210 udelay(500);
211
212 /* reset the PLL */
213 WREG8(DAC_INDEX, MGA1064_VREF_CTL);
214 tmp = RREG8(DAC_DATA);
215 tmp &= ~0x04;
216 WREG_DAC(MGA1064_VREF_CTL, tmp);
217
218 udelay(50);
219
220 /* program pixel pll register */
221 WREG_DAC(MGA1064_WB_PIX_PLLC_N, n);
222 WREG_DAC(MGA1064_WB_PIX_PLLC_M, m);
223 WREG_DAC(MGA1064_WB_PIX_PLLC_P, p);
224
225 udelay(50);
226
227 /* turn pll on */
228 WREG8(DAC_INDEX, MGA1064_VREF_CTL);
229 tmp = RREG8(DAC_DATA);
230 tmp |= 0x04;
231 WREG_DAC(MGA1064_VREF_CTL, tmp);
232
233 udelay(500);
234
235 /* select the pixel pll */
236 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
237 tmp = RREG8(DAC_DATA);
238 tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK;
239 tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL;
240 WREG_DAC(MGA1064_PIX_CLK_CTL, tmp);
241
242 WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
243 tmp = RREG8(DAC_DATA);
244 tmp &= ~MGA1064_REMHEADCTL_CLKSL_MSK;
245 tmp |= MGA1064_REMHEADCTL_CLKSL_PLL;
246 WREG_DAC(MGA1064_REMHEADCTL, tmp);
247
248 /* reset dotclock rate bit */
249 WREG8(MGAREG_SEQ_INDEX, 1);
250 tmp = RREG8(MGAREG_SEQ_DATA);
251 tmp &= ~0x8;
252 WREG8(MGAREG_SEQ_DATA, tmp);
253
254 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
255 tmp = RREG8(DAC_DATA);
256 tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
257 WREG_DAC(MGA1064_PIX_CLK_CTL, tmp);
258
259 vcount = RREG8(MGAREG_VCOUNT);
260
261 for (j = 0; j < 30 && pll_locked == false; j++) {
262 tmpcount = RREG8(MGAREG_VCOUNT);
263 if (tmpcount < vcount)
264 vcount = 0;
265 if ((tmpcount - vcount) > 2)
266 pll_locked = true;
267 else
268 udelay(5);
269 }
270 }
271 WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
272 tmp = RREG8(DAC_DATA);
273 tmp &= ~MGA1064_REMHEADCTL_CLKDIS;
274 WREG_DAC(MGA1064_REMHEADCTL, tmp);
275 return 0;
276}
277
278static int mga_g200ev_set_plls(struct mga_device *mdev, long clock)
279{
280 unsigned int vcomax, vcomin, pllreffreq;
281 unsigned int delta, tmpdelta, permitteddelta;
282 unsigned int testp, testm, testn;
283 unsigned int p, m, n;
284 unsigned int computed;
285 u8 tmp;
286
287 m = n = p = 0;
288 vcomax = 550000;
289 vcomin = 150000;
290 pllreffreq = 50000;
291
292 delta = 0xffffffff;
293 permitteddelta = clock * 5 / 1000;
294
295 for (testp = 16; testp > 0; testp--) {
296 if (clock * testp > vcomax)
297 continue;
298 if (clock * testp < vcomin)
299 continue;
300
301 for (testn = 1; testn < 257; testn++) {
302 for (testm = 1; testm < 17; testm++) {
303 computed = (pllreffreq * testn) /
304 (testm * testp);
305 if (computed > clock)
306 tmpdelta = computed - clock;
307 else
308 tmpdelta = clock - computed;
309 if (tmpdelta < delta) {
310 delta = tmpdelta;
311 n = testn - 1;
312 m = testm - 1;
313 p = testp - 1;
314 }
315 }
316 }
317 }
318
319 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
320 tmp = RREG8(DAC_DATA);
321 tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
322 WREG_DAC(MGA1064_PIX_CLK_CTL_CLK_DIS, tmp);
323
324 tmp = RREG8(MGAREG_MEM_MISC_READ);
325 tmp |= 0x3 << 2;
326 WREG8(MGAREG_MEM_MISC_WRITE, tmp);
327
328 WREG8(DAC_INDEX, MGA1064_PIX_PLL_STAT);
329 tmp = RREG8(DAC_DATA);
330 WREG_DAC(MGA1064_PIX_PLL_STAT, tmp & ~0x40);
331
332 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
333 tmp = RREG8(DAC_DATA);
334 tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
335 WREG_DAC(MGA1064_PIX_CLK_CTL, tmp);
336
337 WREG_DAC(MGA1064_EV_PIX_PLLC_M, m);
338 WREG_DAC(MGA1064_EV_PIX_PLLC_N, n);
339 WREG_DAC(MGA1064_EV_PIX_PLLC_P, p);
340
341 udelay(50);
342
343 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
344 tmp = RREG8(DAC_DATA);
345 tmp &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
346 WREG_DAC(MGA1064_PIX_CLK_CTL, tmp);
347
348 udelay(500);
349
350 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
351 tmp = RREG8(DAC_DATA);
352 tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK;
353 tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL;
354 WREG_DAC(MGA1064_PIX_CLK_CTL, tmp);
355
356 WREG8(DAC_INDEX, MGA1064_PIX_PLL_STAT);
357 tmp = RREG8(DAC_DATA);
358 WREG_DAC(MGA1064_PIX_PLL_STAT, tmp | 0x40);
359
360 tmp = RREG8(MGAREG_MEM_MISC_READ);
361 tmp |= (0x3 << 2);
362 WREG8(MGAREG_MEM_MISC_WRITE, tmp);
363
364 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
365 tmp = RREG8(DAC_DATA);
366 tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
367 WREG_DAC(MGA1064_PIX_CLK_CTL, tmp);
368
369 return 0;
370}
371
372static int mga_g200eh_set_plls(struct mga_device *mdev, long clock)
373{
374 unsigned int vcomax, vcomin, pllreffreq;
375 unsigned int delta, tmpdelta, permitteddelta;
376 unsigned int testp, testm, testn;
377 unsigned int p, m, n;
378 unsigned int computed;
379 int i, j, tmpcount, vcount;
380 u8 tmp;
381 bool pll_locked = false;
382
383 m = n = p = 0;
384 vcomax = 800000;
385 vcomin = 400000;
386 pllreffreq = 3333;
387
388 delta = 0xffffffff;
389 permitteddelta = clock * 5 / 1000;
390
391 for (testp = 16; testp > 0; testp--) {
392 if (clock * testp > vcomax)
393 continue;
394 if (clock * testp < vcomin)
395 continue;
396
397 for (testm = 1; testm < 33; testm++) {
398 for (testn = 1; testn < 257; testn++) {
399 computed = (pllreffreq * testn) /
400 (testm * testp);
401 if (computed > clock)
402 tmpdelta = computed - clock;
403 else
404 tmpdelta = clock - computed;
405 if (tmpdelta < delta) {
406 delta = tmpdelta;
407 n = testn - 1;
408 m = (testm - 1) | ((n >> 1) & 0x80);
409 p = testp - 1;
410 }
411 if ((clock * testp) >= 600000)
412 p |= 80;
413 }
414 }
415 }
416 for (i = 0; i <= 32 && pll_locked == false; i++) {
417 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
418 tmp = RREG8(DAC_DATA);
419 tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
420 WREG_DAC(MGA1064_PIX_CLK_CTL_CLK_DIS, tmp);
421
422 tmp = RREG8(MGAREG_MEM_MISC_READ);
423 tmp |= 0x3 << 2;
424 WREG8(MGAREG_MEM_MISC_WRITE, tmp);
425
426 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
427 tmp = RREG8(DAC_DATA);
428 tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
429 WREG_DAC(MGA1064_PIX_CLK_CTL, tmp);
430
431 udelay(500);
432
433 WREG_DAC(MGA1064_EH_PIX_PLLC_M, m);
434 WREG_DAC(MGA1064_EH_PIX_PLLC_N, n);
435 WREG_DAC(MGA1064_EH_PIX_PLLC_P, p);
436
437 udelay(500);
438
439 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
440 tmp = RREG8(DAC_DATA);
441 tmp &= ~MGA1064_PIX_CLK_CTL_SEL_MSK;
442 tmp |= MGA1064_PIX_CLK_CTL_SEL_PLL;
443 WREG_DAC(MGA1064_PIX_CLK_CTL, tmp);
444
445 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
446 tmp = RREG8(DAC_DATA);
447 tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
448 tmp &= ~MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
449 WREG_DAC(MGA1064_PIX_CLK_CTL, tmp);
450
451 vcount = RREG8(MGAREG_VCOUNT);
452
453 for (j = 0; j < 30 && pll_locked == false; j++) {
454 tmpcount = RREG8(MGAREG_VCOUNT);
455 if (tmpcount < vcount)
456 vcount = 0;
457 if ((tmpcount - vcount) > 2)
458 pll_locked = true;
459 else
460 udelay(5);
461 }
462 }
463
464 return 0;
465}
466
467static int mga_g200er_set_plls(struct mga_device *mdev, long clock)
468{
469 unsigned int vcomax, vcomin, pllreffreq;
470 unsigned int delta, tmpdelta;
471 unsigned int testr, testn, testm, testo;
472 unsigned int p, m, n;
473 unsigned int computed;
474 int tmp;
475
476 m = n = p = 0;
477 vcomax = 1488000;
478 vcomin = 1056000;
479 pllreffreq = 48000;
480
481 delta = 0xffffffff;
482
483 for (testr = 0; testr < 4; testr++) {
484 if (delta == 0)
485 break;
486 for (testn = 5; testn < 129; testn++) {
487 if (delta == 0)
488 break;
489 for (testm = 3; testm >= 0; testm--) {
490 if (delta == 0)
491 break;
492 for (testo = 5; testo < 33; testo++) {
493 computed = pllreffreq * (testn + 1) /
494 (testr + 1);
495 if (computed < vcomin)
496 continue;
497 if (computed > vcomax)
498 continue;
499 if (computed > clock)
500 tmpdelta = computed - clock;
501 else
502 tmpdelta = clock - computed;
503 if (tmpdelta < delta) {
504 delta = tmpdelta;
505 m = testm | (testo << 3);
506 n = testn;
507 p = testr | (testr << 3);
508 }
509 }
510 }
511 }
512 }
513
514 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
515 tmp = RREG8(DAC_DATA);
516 tmp |= MGA1064_PIX_CLK_CTL_CLK_DIS;
517 WREG_DAC(MGA1064_PIX_CLK_CTL_CLK_DIS, tmp);
518
519 WREG8(DAC_INDEX, MGA1064_REMHEADCTL);
520 tmp = RREG8(DAC_DATA);
521 tmp |= MGA1064_REMHEADCTL_CLKDIS;
522 WREG_DAC(MGA1064_REMHEADCTL, tmp);
523
524 tmp = RREG8(MGAREG_MEM_MISC_READ);
525 tmp |= (0x3<<2) | 0xc0;
526 WREG8(MGAREG_MEM_MISC_WRITE, tmp);
527
528 WREG8(DAC_INDEX, MGA1064_PIX_CLK_CTL);
529 tmp = RREG8(DAC_DATA);
530 tmp &= ~MGA1064_PIX_CLK_CTL_CLK_DIS;
531 tmp |= MGA1064_PIX_CLK_CTL_CLK_POW_DOWN;
532 WREG_DAC(MGA1064_PIX_CLK_CTL, tmp);
533
534 udelay(500);
535
536 WREG_DAC(MGA1064_ER_PIX_PLLC_N, n);
537 WREG_DAC(MGA1064_ER_PIX_PLLC_M, m);
538 WREG_DAC(MGA1064_ER_PIX_PLLC_P, p);
539
540 udelay(50);
541
542 return 0;
543}
544
545static int mga_crtc_set_plls(struct mga_device *mdev, long clock)
546{
547 switch(mdev->type) {
548 case G200_SE_A:
549 case G200_SE_B:
550 return mga_g200se_set_plls(mdev, clock);
551 break;
552 case G200_WB:
553 return mga_g200wb_set_plls(mdev, clock);
554 break;
555 case G200_EV:
556 return mga_g200ev_set_plls(mdev, clock);
557 break;
558 case G200_EH:
559 return mga_g200eh_set_plls(mdev, clock);
560 break;
561 case G200_ER:
562 return mga_g200er_set_plls(mdev, clock);
563 break;
564 }
565 return 0;
566}
567
568static void mga_g200wb_prepare(struct drm_crtc *crtc)
569{
570 struct mga_device *mdev = crtc->dev->dev_private;
571 u8 tmp;
572 int iter_max;
573
574 /* 1- The first step is to warn the BMC of an upcoming mode change.
575 * We are putting the misc<0> to output.*/
576
577 WREG8(DAC_INDEX, MGA1064_GEN_IO_CTL);
578 tmp = RREG8(DAC_DATA);
579 tmp |= 0x10;
580 WREG_DAC(MGA1064_GEN_IO_CTL, tmp);
581
582 /* we are putting a 1 on the misc<0> line */
583 WREG8(DAC_INDEX, MGA1064_GEN_IO_DATA);
584 tmp = RREG8(DAC_DATA);
585 tmp |= 0x10;
586 WREG_DAC(MGA1064_GEN_IO_DATA, tmp);
587
588 /* 2- Second step to mask and further scan request
589 * This will be done by asserting the remfreqmsk bit (XSPAREREG<7>)
590 */
591 WREG8(DAC_INDEX, MGA1064_SPAREREG);
592 tmp = RREG8(DAC_DATA);
593 tmp |= 0x80;
594 WREG_DAC(MGA1064_SPAREREG, tmp);
595
596 /* 3a- the third step is to verifu if there is an active scan
597 * We are searching for a 0 on remhsyncsts <XSPAREREG<0>)
598 */
599 iter_max = 300;
600 while (!(tmp & 0x1) && iter_max) {
601 WREG8(DAC_INDEX, MGA1064_SPAREREG);
602 tmp = RREG8(DAC_DATA);
603 udelay(1000);
604 iter_max--;
605 }
606
607 /* 3b- this step occurs only if the remove is actually scanning
608 * we are waiting for the end of the frame which is a 1 on
609 * remvsyncsts (XSPAREREG<1>)
610 */
611 if (iter_max) {
612 iter_max = 300;
613 while ((tmp & 0x2) && iter_max) {
614 WREG8(DAC_INDEX, MGA1064_SPAREREG);
615 tmp = RREG8(DAC_DATA);
616 udelay(1000);
617 iter_max--;
618 }
619 }
620}
621
622static void mga_g200wb_commit(struct drm_crtc *crtc)
623{
624 u8 tmp;
625 struct mga_device *mdev = crtc->dev->dev_private;
626
627 /* 1- The first step is to ensure that the vrsten and hrsten are set */
628 WREG8(MGAREG_CRTCEXT_INDEX, 1);
629 tmp = RREG8(MGAREG_CRTCEXT_DATA);
630 WREG8(MGAREG_CRTCEXT_DATA, tmp | 0x88);
631
632 /* 2- second step is to assert the rstlvl2 */
633 WREG8(DAC_INDEX, MGA1064_REMHEADCTL2);
634 tmp = RREG8(DAC_DATA);
635 tmp |= 0x8;
636 WREG8(DAC_DATA, tmp);
637
638 /* wait 10 us */
639 udelay(10);
640
641 /* 3- deassert rstlvl2 */
642 tmp &= ~0x08;
643 WREG8(DAC_INDEX, MGA1064_REMHEADCTL2);
644 WREG8(DAC_DATA, tmp);
645
646 /* 4- remove mask of scan request */
647 WREG8(DAC_INDEX, MGA1064_SPAREREG);
648 tmp = RREG8(DAC_DATA);
649 tmp &= ~0x80;
650 WREG8(DAC_DATA, tmp);
651
652 /* 5- put back a 0 on the misc<0> line */
653 WREG8(DAC_INDEX, MGA1064_GEN_IO_DATA);
654 tmp = RREG8(DAC_DATA);
655 tmp &= ~0x10;
656 WREG_DAC(MGA1064_GEN_IO_DATA, tmp);
657}
658
659
660void mga_set_start_address(struct drm_crtc *crtc, unsigned offset)
661{
662 struct mga_device *mdev = crtc->dev->dev_private;
663 u32 addr;
664 int count;
665
666 while (RREG8(0x1fda) & 0x08);
667 while (!(RREG8(0x1fda) & 0x08));
668
669 count = RREG8(MGAREG_VCOUNT) + 2;
670 while (RREG8(MGAREG_VCOUNT) < count);
671
672 addr = offset >> 2;
673 WREG_CRT(0x0d, (u8)(addr & 0xff));
674 WREG_CRT(0x0c, (u8)(addr >> 8) & 0xff);
675 WREG_CRT(0xaf, (u8)(addr >> 16) & 0xf);
676}
677
678
679/* ast is different - we will force move buffers out of VRAM */
680static int mga_crtc_do_set_base(struct drm_crtc *crtc,
681 struct drm_framebuffer *fb,
682 int x, int y, int atomic)
683{
684 struct mga_device *mdev = crtc->dev->dev_private;
685 struct drm_gem_object *obj;
686 struct mga_framebuffer *mga_fb;
687 struct mgag200_bo *bo;
688 int ret;
689 u64 gpu_addr;
690
691 /* push the previous fb to system ram */
692 if (!atomic && fb) {
693 mga_fb = to_mga_framebuffer(fb);
694 obj = mga_fb->obj;
695 bo = gem_to_mga_bo(obj);
696 ret = mgag200_bo_reserve(bo, false);
697 if (ret)
698 return ret;
699 mgag200_bo_push_sysram(bo);
700 mgag200_bo_unreserve(bo);
701 }
702
703 mga_fb = to_mga_framebuffer(crtc->fb);
704 obj = mga_fb->obj;
705 bo = gem_to_mga_bo(obj);
706
707 ret = mgag200_bo_reserve(bo, false);
708 if (ret)
709 return ret;
710
711 ret = mgag200_bo_pin(bo, TTM_PL_FLAG_VRAM, &gpu_addr);
712 if (ret) {
713 mgag200_bo_unreserve(bo);
714 return ret;
715 }
716
717 if (&mdev->mfbdev->mfb == mga_fb) {
718 /* if pushing console in kmap it */
719 ret = ttm_bo_kmap(&bo->bo, 0, bo->bo.num_pages, &bo->kmap);
720 if (ret)
721 DRM_ERROR("failed to kmap fbcon\n");
722
723 }
724 mgag200_bo_unreserve(bo);
725
726 DRM_INFO("mga base %llx\n", gpu_addr);
727
728 mga_set_start_address(crtc, (u32)gpu_addr);
729
730 return 0;
731}
732
733static int mga_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
734 struct drm_framebuffer *old_fb)
735{
736 return mga_crtc_do_set_base(crtc, old_fb, x, y, 0);
737}
738
739static int mga_crtc_mode_set(struct drm_crtc *crtc,
740 struct drm_display_mode *mode,
741 struct drm_display_mode *adjusted_mode,
742 int x, int y, struct drm_framebuffer *old_fb)
743{
744 struct drm_device *dev = crtc->dev;
745 struct mga_device *mdev = dev->dev_private;
746 int hdisplay, hsyncstart, hsyncend, htotal;
747 int vdisplay, vsyncstart, vsyncend, vtotal;
748 int pitch;
749 int option = 0, option2 = 0;
750 int i;
751 unsigned char misc = 0;
752 unsigned char ext_vga[6];
753 unsigned char ext_vga_index24;
754 unsigned char dac_index90 = 0;
755 u8 bppshift;
756
757 static unsigned char dacvalue[] = {
758 /* 0x00: */ 0, 0, 0, 0, 0, 0, 0x00, 0,
759 /* 0x08: */ 0, 0, 0, 0, 0, 0, 0, 0,
760 /* 0x10: */ 0, 0, 0, 0, 0, 0, 0, 0,
761 /* 0x18: */ 0x00, 0, 0xC9, 0xFF, 0xBF, 0x20, 0x1F, 0x20,
762 /* 0x20: */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
763 /* 0x28: */ 0x00, 0x00, 0x00, 0x00, 0, 0, 0, 0x40,
764 /* 0x30: */ 0x00, 0xB0, 0x00, 0xC2, 0x34, 0x14, 0x02, 0x83,
765 /* 0x38: */ 0x00, 0x93, 0x00, 0x77, 0x00, 0x00, 0x00, 0x3A,
766 /* 0x40: */ 0, 0, 0, 0, 0, 0, 0, 0,
767 /* 0x48: */ 0, 0, 0, 0, 0, 0, 0, 0
768 };
769
770 bppshift = mdev->bpp_shifts[(crtc->fb->bits_per_pixel >> 3) - 1];
771
772 switch (mdev->type) {
773 case G200_SE_A:
774 case G200_SE_B:
775 dacvalue[MGA1064_VREF_CTL] = 0x03;
776 dacvalue[MGA1064_PIX_CLK_CTL] = MGA1064_PIX_CLK_CTL_SEL_PLL;
777 dacvalue[MGA1064_MISC_CTL] = MGA1064_MISC_CTL_DAC_EN |
778 MGA1064_MISC_CTL_VGA8 |
779 MGA1064_MISC_CTL_DAC_RAM_CS;
780 if (mdev->has_sdram)
781 option = 0x40049120;
782 else
783 option = 0x4004d120;
784 option2 = 0x00008000;
785 break;
786 case G200_WB:
787 dacvalue[MGA1064_VREF_CTL] = 0x07;
788 option = 0x41049120;
789 option2 = 0x0000b000;
790 break;
791 case G200_EV:
792 dacvalue[MGA1064_PIX_CLK_CTL] = MGA1064_PIX_CLK_CTL_SEL_PLL;
793 dacvalue[MGA1064_MISC_CTL] = MGA1064_MISC_CTL_VGA8 |
794 MGA1064_MISC_CTL_DAC_RAM_CS;
795 option = 0x00000120;
796 option2 = 0x0000b000;
797 break;
798 case G200_EH:
799 dacvalue[MGA1064_MISC_CTL] = MGA1064_MISC_CTL_VGA8 |
800 MGA1064_MISC_CTL_DAC_RAM_CS;
801 option = 0x00000120;
802 option2 = 0x0000b000;
803 break;
804 case G200_ER:
805 dac_index90 = 0;
806 break;
807 }
808
809 switch (crtc->fb->bits_per_pixel) {
810 case 8:
811 dacvalue[MGA1064_MUL_CTL] = MGA1064_MUL_CTL_8bits;
812 break;
813 case 16:
814 if (crtc->fb->depth == 15)
815 dacvalue[MGA1064_MUL_CTL] = MGA1064_MUL_CTL_15bits;
816 else
817 dacvalue[MGA1064_MUL_CTL] = MGA1064_MUL_CTL_16bits;
818 break;
819 case 24:
820 dacvalue[MGA1064_MUL_CTL] = MGA1064_MUL_CTL_24bits;
821 break;
822 case 32:
823 dacvalue[MGA1064_MUL_CTL] = MGA1064_MUL_CTL_32_24bits;
824 break;
825 }
826
827 if (mode->flags & DRM_MODE_FLAG_NHSYNC)
828 misc |= 0x40;
829 if (mode->flags & DRM_MODE_FLAG_NVSYNC)
830 misc |= 0x80;
831
832
833 for (i = 0; i < sizeof(dacvalue); i++) {
834 if ((i <= 0x03) ||
835 (i == 0x07) ||
836 (i == 0x0b) ||
837 (i == 0x0f) ||
838 ((i >= 0x13) && (i <= 0x17)) ||
839 (i == 0x1b) ||
840 (i == 0x1c) ||
841 ((i >= 0x1f) && (i <= 0x29)) ||
842 ((i >= 0x30) && (i <= 0x37)))
843 continue;
844 if (IS_G200_SE(mdev) &&
845 ((i == 0x2c) || (i == 0x2d) || (i == 0x2e)))
846 continue;
847 if ((mdev->type == G200_EV || mdev->type == G200_WB || mdev->type == G200_EH) &&
848 (i >= 0x44) && (i <= 0x4e))
849 continue;
850
851 WREG_DAC(i, dacvalue[i]);
852 }
853
854 if (mdev->type == G200_ER) {
855 WREG_DAC(0x90, dac_index90);
856 }
857
858
859 if (option)
860 pci_write_config_dword(dev->pdev, PCI_MGA_OPTION, option);
861 if (option2)
862 pci_write_config_dword(dev->pdev, PCI_MGA_OPTION2, option2);
863
864 WREG_SEQ(2, 0xf);
865 WREG_SEQ(3, 0);
866 WREG_SEQ(4, 0xe);
867
868 pitch = crtc->fb->pitches[0] / (crtc->fb->bits_per_pixel / 8);
869 if (crtc->fb->bits_per_pixel == 24)
870 pitch = pitch >> (4 - bppshift);
871 else
872 pitch = pitch >> (4 - bppshift);
873
874 hdisplay = mode->hdisplay / 8 - 1;
875 hsyncstart = mode->hsync_start / 8 - 1;
876 hsyncend = mode->hsync_end / 8 - 1;
877 htotal = mode->htotal / 8 - 1;
878
879 /* Work around hardware quirk */
880 if ((htotal & 0x07) == 0x06 || (htotal & 0x07) == 0x04)
881 htotal++;
882
883 vdisplay = mode->vdisplay - 1;
884 vsyncstart = mode->vsync_start - 1;
885 vsyncend = mode->vsync_end - 1;
886 vtotal = mode->vtotal - 2;
887
888 WREG_GFX(0, 0);
889 WREG_GFX(1, 0);
890 WREG_GFX(2, 0);
891 WREG_GFX(3, 0);
892 WREG_GFX(4, 0);
893 WREG_GFX(5, 0x40);
894 WREG_GFX(6, 0x5);
895 WREG_GFX(7, 0xf);
896 WREG_GFX(8, 0xf);
897
898 WREG_CRT(0, htotal - 4);
899 WREG_CRT(1, hdisplay);
900 WREG_CRT(2, hdisplay);
901 WREG_CRT(3, (htotal & 0x1F) | 0x80);
902 WREG_CRT(4, hsyncstart);
903 WREG_CRT(5, ((htotal & 0x20) << 2) | (hsyncend & 0x1F));
904 WREG_CRT(6, vtotal & 0xFF);
905 WREG_CRT(7, ((vtotal & 0x100) >> 8) |
906 ((vdisplay & 0x100) >> 7) |
907 ((vsyncstart & 0x100) >> 6) |
908 ((vdisplay & 0x100) >> 5) |
909 ((vdisplay & 0x100) >> 4) | /* linecomp */
910 ((vtotal & 0x200) >> 4)|
911 ((vdisplay & 0x200) >> 3) |
912 ((vsyncstart & 0x200) >> 2));
913 WREG_CRT(9, ((vdisplay & 0x200) >> 4) |
914 ((vdisplay & 0x200) >> 3));
915 WREG_CRT(10, 0);
916 WREG_CRT(11, 0);
917 WREG_CRT(12, 0);
918 WREG_CRT(13, 0);
919 WREG_CRT(14, 0);
920 WREG_CRT(15, 0);
921 WREG_CRT(16, vsyncstart & 0xFF);
922 WREG_CRT(17, (vsyncend & 0x0F) | 0x20);
923 WREG_CRT(18, vdisplay & 0xFF);
924 WREG_CRT(19, pitch & 0xFF);
925 WREG_CRT(20, 0);
926 WREG_CRT(21, vdisplay & 0xFF);
927 WREG_CRT(22, (vtotal + 1) & 0xFF);
928 WREG_CRT(23, 0xc3);
929 WREG_CRT(24, vdisplay & 0xFF);
930
931 ext_vga[0] = 0;
932 ext_vga[5] = 0;
933
934 /* TODO interlace */
935
936 ext_vga[0] |= (pitch & 0x300) >> 4;
937 ext_vga[1] = (((htotal - 4) & 0x100) >> 8) |
938 ((hdisplay & 0x100) >> 7) |
939 ((hsyncstart & 0x100) >> 6) |
940 (htotal & 0x40);
941 ext_vga[2] = ((vtotal & 0xc00) >> 10) |
942 ((vdisplay & 0x400) >> 8) |
943 ((vdisplay & 0xc00) >> 7) |
944 ((vsyncstart & 0xc00) >> 5) |
945 ((vdisplay & 0x400) >> 3);
946 if (crtc->fb->bits_per_pixel == 24)
947 ext_vga[3] = (((1 << bppshift) * 3) - 1) | 0x80;
948 else
949 ext_vga[3] = ((1 << bppshift) - 1) | 0x80;
950 ext_vga[4] = 0;
951 if (mdev->type == G200_WB)
952 ext_vga[1] |= 0x88;
953
954 ext_vga_index24 = 0x05;
955
956 /* Set pixel clocks */
957 misc = 0x2d;
958 WREG8(MGA_MISC_OUT, misc);
959
960 mga_crtc_set_plls(mdev, mode->clock);
961
962 for (i = 0; i < 6; i++) {
963 WREG_ECRT(i, ext_vga[i]);
964 }
965
966 if (mdev->type == G200_ER)
967 WREG_ECRT(24, ext_vga_index24);
968
969 if (mdev->type == G200_EV) {
970 WREG_ECRT(6, 0);
971 }
972
973 WREG_ECRT(0, ext_vga[0]);
974 /* Enable mga pixel clock */
975 misc = 0x2d;
976
977 WREG8(MGA_MISC_OUT, misc);
978
979 if (adjusted_mode)
980 memcpy(&mdev->mode, mode, sizeof(struct drm_display_mode));
981
982 mga_crtc_do_set_base(crtc, old_fb, x, y, 0);
983
984 /* reset tagfifo */
985 if (mdev->type == G200_ER) {
986 u32 mem_ctl = RREG32(MGAREG_MEMCTL);
987 u8 seq1;
988
989 /* screen off */
990 WREG8(MGAREG_SEQ_INDEX, 0x01);
991 seq1 = RREG8(MGAREG_SEQ_DATA) | 0x20;
992 WREG8(MGAREG_SEQ_DATA, seq1);
993
994 WREG32(MGAREG_MEMCTL, mem_ctl | 0x00200000);
995 udelay(1000);
996 WREG32(MGAREG_MEMCTL, mem_ctl & ~0x00200000);
997
998 WREG8(MGAREG_SEQ_DATA, seq1 & ~0x20);
999 }
1000
1001
1002 if (IS_G200_SE(mdev)) {
1003 if (mdev->reg_1e24 >= 0x02) {
1004 u8 hi_pri_lvl;
1005 u32 bpp;
1006 u32 mb;
1007
1008 if (crtc->fb->bits_per_pixel > 16)
1009 bpp = 32;
1010 else if (crtc->fb->bits_per_pixel > 8)
1011 bpp = 16;
1012 else
1013 bpp = 8;
1014
1015 mb = (mode->clock * bpp) / 1000;
1016 if (mb > 3100)
1017 hi_pri_lvl = 0;
1018 else if (mb > 2600)
1019 hi_pri_lvl = 1;
1020 else if (mb > 1900)
1021 hi_pri_lvl = 2;
1022 else if (mb > 1160)
1023 hi_pri_lvl = 3;
1024 else if (mb > 440)
1025 hi_pri_lvl = 4;
1026 else
1027 hi_pri_lvl = 5;
1028
1029 WREG8(0x1fde, 0x06);
1030 WREG8(0x1fdf, hi_pri_lvl);
1031 } else {
1032 if (mdev->reg_1e24 >= 0x01)
1033 WREG8(0x1fdf, 0x03);
1034 else
1035 WREG8(0x1fdf, 0x04);
1036 }
1037 }
1038 return 0;
1039}
1040
1041#if 0 /* code from mjg to attempt D3 on crtc dpms off - revisit later */
1042static int mga_suspend(struct drm_crtc *crtc)
1043{
1044 struct mga_crtc *mga_crtc = to_mga_crtc(crtc);
1045 struct drm_device *dev = crtc->dev;
1046 struct mga_device *mdev = dev->dev_private;
1047 struct pci_dev *pdev = dev->pdev;
1048 int option;
1049
1050 if (mdev->suspended)
1051 return 0;
1052
1053 WREG_SEQ(1, 0x20);
1054 WREG_ECRT(1, 0x30);
1055 /* Disable the pixel clock */
1056 WREG_DAC(0x1a, 0x05);
1057 /* Power down the DAC */
1058 WREG_DAC(0x1e, 0x18);
1059 /* Power down the pixel PLL */
1060 WREG_DAC(0x1a, 0x0d);
1061
1062 /* Disable PLLs and clocks */
1063 pci_read_config_dword(pdev, PCI_MGA_OPTION, &option);
1064 option &= ~(0x1F8024);
1065 pci_write_config_dword(pdev, PCI_MGA_OPTION, option);
1066 pci_set_power_state(pdev, PCI_D3hot);
1067 pci_disable_device(pdev);
1068
1069 mdev->suspended = true;
1070
1071 return 0;
1072}
1073
1074static int mga_resume(struct drm_crtc *crtc)
1075{
1076 struct mga_crtc *mga_crtc = to_mga_crtc(crtc);
1077 struct drm_device *dev = crtc->dev;
1078 struct mga_device *mdev = dev->dev_private;
1079 struct pci_dev *pdev = dev->pdev;
1080 int option;
1081
1082 if (!mdev->suspended)
1083 return 0;
1084
1085 pci_set_power_state(pdev, PCI_D0);
1086 pci_enable_device(pdev);
1087
1088 /* Disable sysclk */
1089 pci_read_config_dword(pdev, PCI_MGA_OPTION, &option);
1090 option &= ~(0x4);
1091 pci_write_config_dword(pdev, PCI_MGA_OPTION, option);
1092
1093 mdev->suspended = false;
1094
1095 return 0;
1096}
1097
1098#endif
1099
1100static void mga_crtc_dpms(struct drm_crtc *crtc, int mode)
1101{
1102 struct drm_device *dev = crtc->dev;
1103 struct mga_device *mdev = dev->dev_private;
1104 u8 seq1 = 0, crtcext1 = 0;
1105
1106 switch (mode) {
1107 case DRM_MODE_DPMS_ON:
1108 seq1 = 0;
1109 crtcext1 = 0;
1110 mga_crtc_load_lut(crtc);
1111 break;
1112 case DRM_MODE_DPMS_STANDBY:
1113 seq1 = 0x20;
1114 crtcext1 = 0x10;
1115 break;
1116 case DRM_MODE_DPMS_SUSPEND:
1117 seq1 = 0x20;
1118 crtcext1 = 0x20;
1119 break;
1120 case DRM_MODE_DPMS_OFF:
1121 seq1 = 0x20;
1122 crtcext1 = 0x30;
1123 break;
1124 }
1125
1126#if 0
1127 if (mode == DRM_MODE_DPMS_OFF) {
1128 mga_suspend(crtc);
1129 }
1130#endif
1131 WREG8(MGAREG_SEQ_INDEX, 0x01);
1132 seq1 |= RREG8(MGAREG_SEQ_DATA) & ~0x20;
1133 mga_wait_vsync(mdev);
1134 mga_wait_busy(mdev);
1135 WREG8(MGAREG_SEQ_DATA, seq1);
1136 msleep(20);
1137 WREG8(MGAREG_CRTCEXT_INDEX, 0x01);
1138 crtcext1 |= RREG8(MGAREG_CRTCEXT_DATA) & ~0x30;
1139 WREG8(MGAREG_CRTCEXT_DATA, crtcext1);
1140
1141#if 0
1142 if (mode == DRM_MODE_DPMS_ON && mdev->suspended == true) {
1143 mga_resume(crtc);
1144 drm_helper_resume_force_mode(dev);
1145 }
1146#endif
1147}
1148
1149/*
1150 * This is called before a mode is programmed. A typical use might be to
1151 * enable DPMS during the programming to avoid seeing intermediate stages,
1152 * but that's not relevant to us
1153 */
1154static void mga_crtc_prepare(struct drm_crtc *crtc)
1155{
1156 struct drm_device *dev = crtc->dev;
1157 struct mga_device *mdev = dev->dev_private;
1158 u8 tmp;
1159
1160 /* mga_resume(crtc);*/
1161
1162 WREG8(MGAREG_CRTC_INDEX, 0x11);
1163 tmp = RREG8(MGAREG_CRTC_DATA);
1164 WREG_CRT(0x11, tmp | 0x80);
1165
1166 if (mdev->type == G200_SE_A || mdev->type == G200_SE_B) {
1167 WREG_SEQ(0, 1);
1168 msleep(50);
1169 WREG_SEQ(1, 0x20);
1170 msleep(20);
1171 } else {
1172 WREG8(MGAREG_SEQ_INDEX, 0x1);
1173 tmp = RREG8(MGAREG_SEQ_DATA);
1174
1175 /* start sync reset */
1176 WREG_SEQ(0, 1);
1177 WREG_SEQ(1, tmp | 0x20);
1178 }
1179
1180 if (mdev->type == G200_WB)
1181 mga_g200wb_prepare(crtc);
1182
1183 WREG_CRT(17, 0);
1184}
1185
1186/*
1187 * This is called after a mode is programmed. It should reverse anything done
1188 * by the prepare function
1189 */
1190static void mga_crtc_commit(struct drm_crtc *crtc)
1191{
1192 struct drm_device *dev = crtc->dev;
1193 struct mga_device *mdev = dev->dev_private;
1194 struct drm_crtc_helper_funcs *crtc_funcs = crtc->helper_private;
1195 u8 tmp;
1196
1197 if (mdev->type == G200_WB)
1198 mga_g200wb_commit(crtc);
1199
1200 if (mdev->type == G200_SE_A || mdev->type == G200_SE_B) {
1201 msleep(50);
1202 WREG_SEQ(1, 0x0);
1203 msleep(20);
1204 WREG_SEQ(0, 0x3);
1205 } else {
1206 WREG8(MGAREG_SEQ_INDEX, 0x1);
1207 tmp = RREG8(MGAREG_SEQ_DATA);
1208
1209 tmp &= ~0x20;
1210 WREG_SEQ(0x1, tmp);
1211 WREG_SEQ(0, 3);
1212 }
1213 crtc_funcs->dpms(crtc, DRM_MODE_DPMS_ON);
1214}
1215
1216/*
1217 * The core can pass us a set of gamma values to program. We actually only
1218 * use this for 8-bit mode so can't perform smooth fades on deeper modes,
1219 * but it's a requirement that we provide the function
1220 */
1221static void mga_crtc_gamma_set(struct drm_crtc *crtc, u16 *red, u16 *green,
1222 u16 *blue, uint32_t start, uint32_t size)
1223{
1224 struct mga_crtc *mga_crtc = to_mga_crtc(crtc);
1225 int end = (start + size > MGAG200_LUT_SIZE) ? MGAG200_LUT_SIZE : start + size;
1226 int i;
1227
1228 for (i = start; i < end; i++) {
1229 mga_crtc->lut_r[i] = red[i] >> 8;
1230 mga_crtc->lut_g[i] = green[i] >> 8;
1231 mga_crtc->lut_b[i] = blue[i] >> 8;
1232 }
1233 mga_crtc_load_lut(crtc);
1234}
1235
1236/* Simple cleanup function */
1237static void mga_crtc_destroy(struct drm_crtc *crtc)
1238{
1239 struct mga_crtc *mga_crtc = to_mga_crtc(crtc);
1240
1241 drm_crtc_cleanup(crtc);
1242 kfree(mga_crtc);
1243}
1244
1245/* These provide the minimum set of functions required to handle a CRTC */
1246static const struct drm_crtc_funcs mga_crtc_funcs = {
1247 .gamma_set = mga_crtc_gamma_set,
1248 .set_config = drm_crtc_helper_set_config,
1249 .destroy = mga_crtc_destroy,
1250};
1251
1252static const struct drm_crtc_helper_funcs mga_helper_funcs = {
1253 .dpms = mga_crtc_dpms,
1254 .mode_fixup = mga_crtc_mode_fixup,
1255 .mode_set = mga_crtc_mode_set,
1256 .mode_set_base = mga_crtc_mode_set_base,
1257 .prepare = mga_crtc_prepare,
1258 .commit = mga_crtc_commit,
1259 .load_lut = mga_crtc_load_lut,
1260};
1261
1262/* CRTC setup */
1263static void mga_crtc_init(struct drm_device *dev)
1264{
1265 struct mga_device *mdev = dev->dev_private;
1266 struct mga_crtc *mga_crtc;
1267 int i;
1268
1269 mga_crtc = kzalloc(sizeof(struct mga_crtc) +
1270 (MGAG200FB_CONN_LIMIT * sizeof(struct drm_connector *)),
1271 GFP_KERNEL);
1272
1273 if (mga_crtc == NULL)
1274 return;
1275
1276 drm_crtc_init(dev, &mga_crtc->base, &mga_crtc_funcs);
1277
1278 drm_mode_crtc_set_gamma_size(&mga_crtc->base, MGAG200_LUT_SIZE);
1279 mdev->mode_info.crtc = mga_crtc;
1280
1281 for (i = 0; i < MGAG200_LUT_SIZE; i++) {
1282 mga_crtc->lut_r[i] = i;
1283 mga_crtc->lut_g[i] = i;
1284 mga_crtc->lut_b[i] = i;
1285 }
1286
1287 drm_crtc_helper_add(&mga_crtc->base, &mga_helper_funcs);
1288}
1289
1290/** Sets the color ramps on behalf of fbcon */
1291void mga_crtc_fb_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
1292 u16 blue, int regno)
1293{
1294 struct mga_crtc *mga_crtc = to_mga_crtc(crtc);
1295
1296 mga_crtc->lut_r[regno] = red >> 8;
1297 mga_crtc->lut_g[regno] = green >> 8;
1298 mga_crtc->lut_b[regno] = blue >> 8;
1299}
1300
1301/** Gets the color ramps on behalf of fbcon */
1302void mga_crtc_fb_gamma_get(struct drm_crtc *crtc, u16 *red, u16 *green,
1303 u16 *blue, int regno)
1304{
1305 struct mga_crtc *mga_crtc = to_mga_crtc(crtc);
1306
1307 *red = (u16)mga_crtc->lut_r[regno] << 8;
1308 *green = (u16)mga_crtc->lut_g[regno] << 8;
1309 *blue = (u16)mga_crtc->lut_b[regno] << 8;
1310}
1311
1312/*
1313 * The encoder comes after the CRTC in the output pipeline, but before
1314 * the connector. It's responsible for ensuring that the digital
1315 * stream is appropriately converted into the output format. Setup is
1316 * very simple in this case - all we have to do is inform qemu of the
1317 * colour depth in order to ensure that it displays appropriately
1318 */
1319
1320/*
1321 * These functions are analagous to those in the CRTC code, but are intended
1322 * to handle any encoder-specific limitations
1323 */
1324static bool mga_encoder_mode_fixup(struct drm_encoder *encoder,
1325 struct drm_display_mode *mode,
1326 struct drm_display_mode *adjusted_mode)
1327{
1328 return true;
1329}
1330
1331static void mga_encoder_mode_set(struct drm_encoder *encoder,
1332 struct drm_display_mode *mode,
1333 struct drm_display_mode *adjusted_mode)
1334{
1335
1336}
1337
1338static void mga_encoder_dpms(struct drm_encoder *encoder, int state)
1339{
1340 return;
1341}
1342
1343static void mga_encoder_prepare(struct drm_encoder *encoder)
1344{
1345}
1346
1347static void mga_encoder_commit(struct drm_encoder *encoder)
1348{
1349}
1350
1351void mga_encoder_destroy(struct drm_encoder *encoder)
1352{
1353 struct mga_encoder *mga_encoder = to_mga_encoder(encoder);
1354 drm_encoder_cleanup(encoder);
1355 kfree(mga_encoder);
1356}
1357
1358static const struct drm_encoder_helper_funcs mga_encoder_helper_funcs = {
1359 .dpms = mga_encoder_dpms,
1360 .mode_fixup = mga_encoder_mode_fixup,
1361 .mode_set = mga_encoder_mode_set,
1362 .prepare = mga_encoder_prepare,
1363 .commit = mga_encoder_commit,
1364};
1365
1366static const struct drm_encoder_funcs mga_encoder_encoder_funcs = {
1367 .destroy = mga_encoder_destroy,
1368};
1369
1370static struct drm_encoder *mga_encoder_init(struct drm_device *dev)
1371{
1372 struct drm_encoder *encoder;
1373 struct mga_encoder *mga_encoder;
1374
1375 mga_encoder = kzalloc(sizeof(struct mga_encoder), GFP_KERNEL);
1376 if (!mga_encoder)
1377 return NULL;
1378
1379 encoder = &mga_encoder->base;
1380 encoder->possible_crtcs = 0x1;
1381
1382 drm_encoder_init(dev, encoder, &mga_encoder_encoder_funcs,
1383 DRM_MODE_ENCODER_DAC);
1384 drm_encoder_helper_add(encoder, &mga_encoder_helper_funcs);
1385
1386 return encoder;
1387}
1388
1389
1390static int mga_vga_get_modes(struct drm_connector *connector)
1391{
1392 struct mga_connector *mga_connector = to_mga_connector(connector);
1393 struct edid *edid;
1394 int ret = 0;
1395
1396 edid = drm_get_edid(connector, &mga_connector->i2c->adapter);
1397 if (edid) {
1398 drm_mode_connector_update_edid_property(connector, edid);
1399 ret = drm_add_edid_modes(connector, edid);
1400 connector->display_info.raw_edid = NULL;
1401 kfree(edid);
1402 }
1403 return ret;
1404}
1405
1406static int mga_vga_mode_valid(struct drm_connector *connector,
1407 struct drm_display_mode *mode)
1408{
1409 /* FIXME: Add bandwidth and g200se limitations */
1410
1411 if (mode->crtc_hdisplay > 2048 || mode->crtc_hsync_start > 4096 ||
1412 mode->crtc_hsync_end > 4096 || mode->crtc_htotal > 4096 ||
1413 mode->crtc_vdisplay > 2048 || mode->crtc_vsync_start > 4096 ||
1414 mode->crtc_vsync_end > 4096 || mode->crtc_vtotal > 4096) {
1415 return MODE_BAD;
1416 }
1417
1418 return MODE_OK;
1419}
1420
1421struct drm_encoder *mga_connector_best_encoder(struct drm_connector
1422 *connector)
1423{
1424 int enc_id = connector->encoder_ids[0];
1425 struct drm_mode_object *obj;
1426 struct drm_encoder *encoder;
1427
1428 /* pick the encoder ids */
1429 if (enc_id) {
1430 obj =
1431 drm_mode_object_find(connector->dev, enc_id,
1432 DRM_MODE_OBJECT_ENCODER);
1433 if (!obj)
1434 return NULL;
1435 encoder = obj_to_encoder(obj);
1436 return encoder;
1437 }
1438 return NULL;
1439}
1440
1441static enum drm_connector_status mga_vga_detect(struct drm_connector
1442 *connector, bool force)
1443{
1444 return connector_status_connected;
1445}
1446
1447static void mga_connector_destroy(struct drm_connector *connector)
1448{
1449 struct mga_connector *mga_connector = to_mga_connector(connector);
1450 mgag200_i2c_destroy(mga_connector->i2c);
1451 drm_connector_cleanup(connector);
1452 kfree(connector);
1453}
1454
1455struct drm_connector_helper_funcs mga_vga_connector_helper_funcs = {
1456 .get_modes = mga_vga_get_modes,
1457 .mode_valid = mga_vga_mode_valid,
1458 .best_encoder = mga_connector_best_encoder,
1459};
1460
1461struct drm_connector_funcs mga_vga_connector_funcs = {
1462 .dpms = drm_helper_connector_dpms,
1463 .detect = mga_vga_detect,
1464 .fill_modes = drm_helper_probe_single_connector_modes,
1465 .destroy = mga_connector_destroy,
1466};
1467
1468static struct drm_connector *mga_vga_init(struct drm_device *dev)
1469{
1470 struct drm_connector *connector;
1471 struct mga_connector *mga_connector;
1472
1473 mga_connector = kzalloc(sizeof(struct mga_connector), GFP_KERNEL);
1474 if (!mga_connector)
1475 return NULL;
1476
1477 connector = &mga_connector->base;
1478
1479 drm_connector_init(dev, connector,
1480 &mga_vga_connector_funcs, DRM_MODE_CONNECTOR_VGA);
1481
1482 drm_connector_helper_add(connector, &mga_vga_connector_helper_funcs);
1483
1484 mga_connector->i2c = mgag200_i2c_create(dev);
1485 if (!mga_connector->i2c)
1486 DRM_ERROR("failed to add ddc bus\n");
1487
1488 return connector;
1489}
1490
1491
1492int mgag200_modeset_init(struct mga_device *mdev)
1493{
1494 struct drm_encoder *encoder;
1495 struct drm_connector *connector;
1496 int ret;
1497
1498 mdev->mode_info.mode_config_initialized = true;
1499
1500 mdev->dev->mode_config.max_width = MGAG200_MAX_FB_WIDTH;
1501 mdev->dev->mode_config.max_height = MGAG200_MAX_FB_HEIGHT;
1502
1503 mdev->dev->mode_config.fb_base = mdev->mc.vram_base;
1504
1505 mga_crtc_init(mdev->dev);
1506
1507 encoder = mga_encoder_init(mdev->dev);
1508 if (!encoder) {
1509 DRM_ERROR("mga_encoder_init failed\n");
1510 return -1;
1511 }
1512
1513 connector = mga_vga_init(mdev->dev);
1514 if (!connector) {
1515 DRM_ERROR("mga_vga_init failed\n");
1516 return -1;
1517 }
1518
1519 drm_mode_connector_attach_encoder(connector, encoder);
1520
1521 ret = mgag200_fbdev_init(mdev);
1522 if (ret) {
1523 DRM_ERROR("mga_fbdev_init failed\n");
1524 return ret;
1525 }
1526
1527 return 0;
1528}
1529
1530void mgag200_modeset_fini(struct mga_device *mdev)
1531{
1532
1533}
diff --git a/drivers/gpu/drm/mgag200/mgag200_reg.h b/drivers/gpu/drm/mgag200/mgag200_reg.h
new file mode 100644
index 000000000000..fb24d8655feb
--- /dev/null
+++ b/drivers/gpu/drm/mgag200/mgag200_reg.h
@@ -0,0 +1,661 @@
1/*
2 * MGA Millennium (MGA2064W) functions
3 * MGA Mystique (MGA1064SG) functions
4 *
5 * Copyright 1996 The XFree86 Project, Inc.
6 *
7 * Authors
8 * Dirk Hohndel
9 * hohndel@XFree86.Org
10 * David Dawes
11 * dawes@XFree86.Org
12 * Contributors:
13 * Guy DESBIEF, Aix-en-provence, France
14 * g.desbief@aix.pacwan.net
15 * MGA1064SG Mystique register file
16 */
17
18
19#ifndef _MGA_REG_H_
20#define _MGA_REG_H_
21
22#define MGAREG_DWGCTL 0x1c00
23#define MGAREG_MACCESS 0x1c04
24/* the following is a mystique only register */
25#define MGAREG_MCTLWTST 0x1c08
26#define MGAREG_ZORG 0x1c0c
27
28#define MGAREG_PAT0 0x1c10
29#define MGAREG_PAT1 0x1c14
30#define MGAREG_PLNWT 0x1c1c
31
32#define MGAREG_BCOL 0x1c20
33#define MGAREG_FCOL 0x1c24
34
35#define MGAREG_SRC0 0x1c30
36#define MGAREG_SRC1 0x1c34
37#define MGAREG_SRC2 0x1c38
38#define MGAREG_SRC3 0x1c3c
39
40#define MGAREG_XYSTRT 0x1c40
41#define MGAREG_XYEND 0x1c44
42
43#define MGAREG_SHIFT 0x1c50
44/* the following is a mystique only register */
45#define MGAREG_DMAPAD 0x1c54
46#define MGAREG_SGN 0x1c58
47#define MGAREG_LEN 0x1c5c
48
49#define MGAREG_AR0 0x1c60
50#define MGAREG_AR1 0x1c64
51#define MGAREG_AR2 0x1c68
52#define MGAREG_AR3 0x1c6c
53#define MGAREG_AR4 0x1c70
54#define MGAREG_AR5 0x1c74
55#define MGAREG_AR6 0x1c78
56
57#define MGAREG_CXBNDRY 0x1c80
58#define MGAREG_FXBNDRY 0x1c84
59#define MGAREG_YDSTLEN 0x1c88
60#define MGAREG_PITCH 0x1c8c
61
62#define MGAREG_YDST 0x1c90
63#define MGAREG_YDSTORG 0x1c94
64#define MGAREG_YTOP 0x1c98
65#define MGAREG_YBOT 0x1c9c
66
67#define MGAREG_CXLEFT 0x1ca0
68#define MGAREG_CXRIGHT 0x1ca4
69#define MGAREG_FXLEFT 0x1ca8
70#define MGAREG_FXRIGHT 0x1cac
71
72#define MGAREG_XDST 0x1cb0
73
74#define MGAREG_DR0 0x1cc0
75#define MGAREG_DR1 0x1cc4
76#define MGAREG_DR2 0x1cc8
77#define MGAREG_DR3 0x1ccc
78
79#define MGAREG_DR4 0x1cd0
80#define MGAREG_DR5 0x1cd4
81#define MGAREG_DR6 0x1cd8
82#define MGAREG_DR7 0x1cdc
83
84#define MGAREG_DR8 0x1ce0
85#define MGAREG_DR9 0x1ce4
86#define MGAREG_DR10 0x1ce8
87#define MGAREG_DR11 0x1cec
88
89#define MGAREG_DR12 0x1cf0
90#define MGAREG_DR13 0x1cf4
91#define MGAREG_DR14 0x1cf8
92#define MGAREG_DR15 0x1cfc
93
94#define MGAREG_SRCORG 0x2cb4
95#define MGAREG_DSTORG 0x2cb8
96
97/* add or or this to one of the previous "power registers" to start
98 the drawing engine */
99
100#define MGAREG_EXEC 0x0100
101
102#define MGAREG_FIFOSTATUS 0x1e10
103#define MGAREG_Status 0x1e14
104#define MGAREG_CACHEFLUSH 0x1fff
105#define MGAREG_ICLEAR 0x1e18
106#define MGAREG_IEN 0x1e1c
107
108#define MGAREG_VCOUNT 0x1e20
109
110#define MGAREG_Reset 0x1e40
111
112#define MGAREG_OPMODE 0x1e54
113
114/* Warp Registers */
115#define MGAREG_WIADDR 0x1dc0
116#define MGAREG_WIADDR2 0x1dd8
117#define MGAREG_WGETMSB 0x1dc8
118#define MGAREG_WVRTXSZ 0x1dcc
119#define MGAREG_WACCEPTSEQ 0x1dd4
120#define MGAREG_WMISC 0x1e70
121
122#define MGAREG_MEMCTL 0x2e08
123
124/* OPMODE register additives */
125
126#define MGAOPM_DMA_GENERAL (0x00 << 2)
127#define MGAOPM_DMA_BLIT (0x01 << 2)
128#define MGAOPM_DMA_VECTOR (0x10 << 2)
129
130/* MACCESS register additives */
131#define MGAMAC_PW8 0x00
132#define MGAMAC_PW16 0x01
133#define MGAMAC_PW24 0x03 /* not a typo */
134#define MGAMAC_PW32 0x02 /* not a typo */
135#define MGAMAC_BYPASS332 0x10000000
136#define MGAMAC_NODITHER 0x40000000
137#define MGAMAC_DIT555 0x80000000
138
139/* DWGCTL register additives */
140
141/* Lines */
142
143#define MGADWG_LINE_OPEN 0x00
144#define MGADWG_AUTOLINE_OPEN 0x01
145#define MGADWG_LINE_CLOSE 0x02
146#define MGADWG_AUTOLINE_CLOSE 0x03
147
148/* Trapezoids */
149#define MGADWG_TRAP 0x04
150#define MGADWG_TEXTURE_TRAP 0x06
151
152/* BitBlts */
153
154#define MGADWG_BITBLT 0x08
155#define MGADWG_FBITBLT 0x0c
156#define MGADWG_ILOAD 0x09
157#define MGADWG_ILOAD_SCALE 0x0d
158#define MGADWG_ILOAD_FILTER 0x0f
159#define MGADWG_ILOAD_HIQH 0x07
160#define MGADWG_ILOAD_HIQHV 0x0e
161#define MGADWG_IDUMP 0x0a
162
163/* atype access to WRAM */
164
165#define MGADWG_RPL ( 0x00 << 4 )
166#define MGADWG_RSTR ( 0x01 << 4 )
167#define MGADWG_ZI ( 0x03 << 4 )
168#define MGADWG_BLK ( 0x04 << 4 )
169#define MGADWG_I ( 0x07 << 4 )
170
171/* specifies whether bit blits are linear or xy */
172#define MGADWG_LINEAR ( 0x01 << 7 )
173
174/* z drawing mode. use MGADWG_NOZCMP for always */
175
176#define MGADWG_NOZCMP ( 0x00 << 8 )
177#define MGADWG_ZE ( 0x02 << 8 )
178#define MGADWG_ZNE ( 0x03 << 8 )
179#define MGADWG_ZLT ( 0x04 << 8 )
180#define MGADWG_ZLTE ( 0x05 << 8 )
181#define MGADWG_GT ( 0x06 << 8 )
182#define MGADWG_GTE ( 0x07 << 8 )
183
184/* use this to force colour expansion circuitry to do its stuff */
185
186#define MGADWG_SOLID ( 0x01 << 11 )
187
188/* ar register at zero */
189
190#define MGADWG_ARZERO ( 0x01 << 12 )
191
192#define MGADWG_SGNZERO ( 0x01 << 13 )
193
194#define MGADWG_SHIFTZERO ( 0x01 << 14 )
195
196/* See table on 4-43 for bop ALU operations */
197
198/* See table on 4-44 for translucidity masks */
199
200#define MGADWG_BMONOLEF ( 0x00 << 25 )
201#define MGADWG_BMONOWF ( 0x04 << 25 )
202#define MGADWG_BPLAN ( 0x01 << 25 )
203
204/* note that if bfcol is specified and you're doing a bitblt, it causes
205 a fbitblt to be performed, so check that you obey the fbitblt rules */
206
207#define MGADWG_BFCOL ( 0x02 << 25 )
208#define MGADWG_BUYUV ( 0x0e << 25 )
209#define MGADWG_BU32BGR ( 0x03 << 25 )
210#define MGADWG_BU32RGB ( 0x07 << 25 )
211#define MGADWG_BU24BGR ( 0x0b << 25 )
212#define MGADWG_BU24RGB ( 0x0f << 25 )
213
214#define MGADWG_PATTERN ( 0x01 << 29 )
215#define MGADWG_TRANSC ( 0x01 << 30 )
216#define MGAREG_MISC_WRITE 0x3c2
217#define MGAREG_MISC_READ 0x3cc
218#define MGAREG_MEM_MISC_WRITE 0x1fc2
219#define MGAREG_MEM_MISC_READ 0x1fcc
220
221#define MGAREG_MISC_IOADSEL (0x1 << 0)
222#define MGAREG_MISC_RAMMAPEN (0x1 << 1)
223#define MGAREG_MISC_CLK_SEL_VGA25 (0x0 << 2)
224#define MGAREG_MISC_CLK_SEL_VGA28 (0x1 << 2)
225#define MGAREG_MISC_CLK_SEL_MGA_PIX (0x2 << 2)
226#define MGAREG_MISC_CLK_SEL_MGA_MSK (0x3 << 2)
227#define MGAREG_MISC_VIDEO_DIS (0x1 << 4)
228#define MGAREG_MISC_HIGH_PG_SEL (0x1 << 5)
229
230/* MMIO VGA registers */
231#define MGAREG_SEQ_INDEX 0x1fc4
232#define MGAREG_SEQ_DATA 0x1fc5
233#define MGAREG_CRTC_INDEX 0x1fd4
234#define MGAREG_CRTC_DATA 0x1fd5
235#define MGAREG_CRTCEXT_INDEX 0x1fde
236#define MGAREG_CRTCEXT_DATA 0x1fdf
237
238
239
240/* MGA bits for registers PCI_OPTION_REG */
241#define MGA1064_OPT_SYS_CLK_PCI ( 0x00 << 0 )
242#define MGA1064_OPT_SYS_CLK_PLL ( 0x01 << 0 )
243#define MGA1064_OPT_SYS_CLK_EXT ( 0x02 << 0 )
244#define MGA1064_OPT_SYS_CLK_MSK ( 0x03 << 0 )
245
246#define MGA1064_OPT_SYS_CLK_DIS ( 0x01 << 2 )
247#define MGA1064_OPT_G_CLK_DIV_1 ( 0x01 << 3 )
248#define MGA1064_OPT_M_CLK_DIV_1 ( 0x01 << 4 )
249
250#define MGA1064_OPT_SYS_PLL_PDN ( 0x01 << 5 )
251#define MGA1064_OPT_VGA_ION ( 0x01 << 8 )
252
253/* MGA registers in PCI config space */
254#define PCI_MGA_INDEX 0x44
255#define PCI_MGA_DATA 0x48
256#define PCI_MGA_OPTION 0x40
257#define PCI_MGA_OPTION2 0x50
258#define PCI_MGA_OPTION3 0x54
259
260#define RAMDAC_OFFSET 0x3c00
261
262/* TVP3026 direct registers */
263
264#define TVP3026_INDEX 0x00
265#define TVP3026_WADR_PAL 0x00
266#define TVP3026_COL_PAL 0x01
267#define TVP3026_PIX_RD_MSK 0x02
268#define TVP3026_RADR_PAL 0x03
269#define TVP3026_CUR_COL_ADDR 0x04
270#define TVP3026_CUR_COL_DATA 0x05
271#define TVP3026_DATA 0x0a
272#define TVP3026_CUR_RAM 0x0b
273#define TVP3026_CUR_XLOW 0x0c
274#define TVP3026_CUR_XHI 0x0d
275#define TVP3026_CUR_YLOW 0x0e
276#define TVP3026_CUR_YHI 0x0f
277
278/* TVP3026 indirect registers */
279
280#define TVP3026_SILICON_REV 0x01
281#define TVP3026_CURSOR_CTL 0x06
282#define TVP3026_LATCH_CTL 0x0f
283#define TVP3026_TRUE_COLOR_CTL 0x18
284#define TVP3026_MUX_CTL 0x19
285#define TVP3026_CLK_SEL 0x1a
286#define TVP3026_PAL_PAGE 0x1c
287#define TVP3026_GEN_CTL 0x1d
288#define TVP3026_MISC_CTL 0x1e
289#define TVP3026_GEN_IO_CTL 0x2a
290#define TVP3026_GEN_IO_DATA 0x2b
291#define TVP3026_PLL_ADDR 0x2c
292#define TVP3026_PIX_CLK_DATA 0x2d
293#define TVP3026_MEM_CLK_DATA 0x2e
294#define TVP3026_LOAD_CLK_DATA 0x2f
295#define TVP3026_KEY_RED_LOW 0x32
296#define TVP3026_KEY_RED_HI 0x33
297#define TVP3026_KEY_GREEN_LOW 0x34
298#define TVP3026_KEY_GREEN_HI 0x35
299#define TVP3026_KEY_BLUE_LOW 0x36
300#define TVP3026_KEY_BLUE_HI 0x37
301#define TVP3026_KEY_CTL 0x38
302#define TVP3026_MCLK_CTL 0x39
303#define TVP3026_SENSE_TEST 0x3a
304#define TVP3026_TEST_DATA 0x3b
305#define TVP3026_CRC_LSB 0x3c
306#define TVP3026_CRC_MSB 0x3d
307#define TVP3026_CRC_CTL 0x3e
308#define TVP3026_ID 0x3f
309#define TVP3026_RESET 0xff
310
311
312/* MGA1064 DAC Register file */
313/* MGA1064 direct registers */
314
315#define MGA1064_INDEX 0x00
316#define MGA1064_WADR_PAL 0x00
317#define MGA1064_SPAREREG 0x00
318#define MGA1064_COL_PAL 0x01
319#define MGA1064_PIX_RD_MSK 0x02
320#define MGA1064_RADR_PAL 0x03
321#define MGA1064_DATA 0x0a
322
323#define MGA1064_CUR_XLOW 0x0c
324#define MGA1064_CUR_XHI 0x0d
325#define MGA1064_CUR_YLOW 0x0e
326#define MGA1064_CUR_YHI 0x0f
327
328/* MGA1064 indirect registers */
329#define MGA1064_DVI_PIPE_CTL 0x03
330#define MGA1064_CURSOR_BASE_ADR_LOW 0x04
331#define MGA1064_CURSOR_BASE_ADR_HI 0x05
332#define MGA1064_CURSOR_CTL 0x06
333#define MGA1064_CURSOR_COL0_RED 0x08
334#define MGA1064_CURSOR_COL0_GREEN 0x09
335#define MGA1064_CURSOR_COL0_BLUE 0x0a
336
337#define MGA1064_CURSOR_COL1_RED 0x0c
338#define MGA1064_CURSOR_COL1_GREEN 0x0d
339#define MGA1064_CURSOR_COL1_BLUE 0x0e
340
341#define MGA1064_CURSOR_COL2_RED 0x010
342#define MGA1064_CURSOR_COL2_GREEN 0x011
343#define MGA1064_CURSOR_COL2_BLUE 0x012
344
345#define MGA1064_VREF_CTL 0x018
346
347#define MGA1064_MUL_CTL 0x19
348#define MGA1064_MUL_CTL_8bits 0x0
349#define MGA1064_MUL_CTL_15bits 0x01
350#define MGA1064_MUL_CTL_16bits 0x02
351#define MGA1064_MUL_CTL_24bits 0x03
352#define MGA1064_MUL_CTL_32bits 0x04
353#define MGA1064_MUL_CTL_2G8V16bits 0x05
354#define MGA1064_MUL_CTL_G16V16bits 0x06
355#define MGA1064_MUL_CTL_32_24bits 0x07
356
357#define MGA1064_PIX_CLK_CTL 0x1a
358#define MGA1064_PIX_CLK_CTL_CLK_DIS ( 0x01 << 2 )
359#define MGA1064_PIX_CLK_CTL_CLK_POW_DOWN ( 0x01 << 3 )
360#define MGA1064_PIX_CLK_CTL_SEL_PCI ( 0x00 << 0 )
361#define MGA1064_PIX_CLK_CTL_SEL_PLL ( 0x01 << 0 )
362#define MGA1064_PIX_CLK_CTL_SEL_EXT ( 0x02 << 0 )
363#define MGA1064_PIX_CLK_CTL_SEL_MSK ( 0x03 << 0 )
364
365#define MGA1064_GEN_CTL 0x1d
366#define MGA1064_GEN_CTL_SYNC_ON_GREEN_DIS (0x01 << 5)
367#define MGA1064_MISC_CTL 0x1e
368#define MGA1064_MISC_CTL_DAC_EN ( 0x01 << 0 )
369#define MGA1064_MISC_CTL_VGA ( 0x01 << 1 )
370#define MGA1064_MISC_CTL_DIS_CON ( 0x03 << 1 )
371#define MGA1064_MISC_CTL_MAFC ( 0x02 << 1 )
372#define MGA1064_MISC_CTL_VGA8 ( 0x01 << 3 )
373#define MGA1064_MISC_CTL_DAC_RAM_CS ( 0x01 << 4 )
374
375#define MGA1064_GEN_IO_CTL2 0x29
376#define MGA1064_GEN_IO_CTL 0x2a
377#define MGA1064_GEN_IO_DATA 0x2b
378#define MGA1064_SYS_PLL_M 0x2c
379#define MGA1064_SYS_PLL_N 0x2d
380#define MGA1064_SYS_PLL_P 0x2e
381#define MGA1064_SYS_PLL_STAT 0x2f
382
383#define MGA1064_REMHEADCTL 0x30
384#define MGA1064_REMHEADCTL_CLKDIS ( 0x01 << 0 )
385#define MGA1064_REMHEADCTL_CLKSL_OFF ( 0x00 << 1 )
386#define MGA1064_REMHEADCTL_CLKSL_PLL ( 0x01 << 1 )
387#define MGA1064_REMHEADCTL_CLKSL_PCI ( 0x02 << 1 )
388#define MGA1064_REMHEADCTL_CLKSL_MSK ( 0x03 << 1 )
389
390#define MGA1064_REMHEADCTL2 0x31
391
392#define MGA1064_ZOOM_CTL 0x38
393#define MGA1064_SENSE_TST 0x3a
394
395#define MGA1064_CRC_LSB 0x3c
396#define MGA1064_CRC_MSB 0x3d
397#define MGA1064_CRC_CTL 0x3e
398#define MGA1064_COL_KEY_MSK_LSB 0x40
399#define MGA1064_COL_KEY_MSK_MSB 0x41
400#define MGA1064_COL_KEY_LSB 0x42
401#define MGA1064_COL_KEY_MSB 0x43
402#define MGA1064_PIX_PLLA_M 0x44
403#define MGA1064_PIX_PLLA_N 0x45
404#define MGA1064_PIX_PLLA_P 0x46
405#define MGA1064_PIX_PLLB_M 0x48
406#define MGA1064_PIX_PLLB_N 0x49
407#define MGA1064_PIX_PLLB_P 0x4a
408#define MGA1064_PIX_PLLC_M 0x4c
409#define MGA1064_PIX_PLLC_N 0x4d
410#define MGA1064_PIX_PLLC_P 0x4e
411
412#define MGA1064_PIX_PLL_STAT 0x4f
413
414/*Added for G450 dual head*/
415
416#define MGA1064_VID_PLL_STAT 0x8c
417#define MGA1064_VID_PLL_P 0x8D
418#define MGA1064_VID_PLL_M 0x8E
419#define MGA1064_VID_PLL_N 0x8F
420
421/* Modified PLL for G200 Winbond (G200WB) */
422#define MGA1064_WB_PIX_PLLC_M 0xb7
423#define MGA1064_WB_PIX_PLLC_N 0xb6
424#define MGA1064_WB_PIX_PLLC_P 0xb8
425
426/* Modified PLL for G200 Maxim (G200EV) */
427#define MGA1064_EV_PIX_PLLC_M 0xb6
428#define MGA1064_EV_PIX_PLLC_N 0xb7
429#define MGA1064_EV_PIX_PLLC_P 0xb8
430
431/* Modified PLL for G200 EH */
432#define MGA1064_EH_PIX_PLLC_M 0xb6
433#define MGA1064_EH_PIX_PLLC_N 0xb7
434#define MGA1064_EH_PIX_PLLC_P 0xb8
435
436/* Modified PLL for G200 Maxim (G200ER) */
437#define MGA1064_ER_PIX_PLLC_M 0xb7
438#define MGA1064_ER_PIX_PLLC_N 0xb6
439#define MGA1064_ER_PIX_PLLC_P 0xb8
440
441#define MGA1064_DISP_CTL 0x8a
442#define MGA1064_DISP_CTL_DAC1OUTSEL_MASK 0x01
443#define MGA1064_DISP_CTL_DAC1OUTSEL_DIS 0x00
444#define MGA1064_DISP_CTL_DAC1OUTSEL_EN 0x01
445#define MGA1064_DISP_CTL_DAC2OUTSEL_MASK (0x03 << 2)
446#define MGA1064_DISP_CTL_DAC2OUTSEL_DIS 0x00
447#define MGA1064_DISP_CTL_DAC2OUTSEL_CRTC1 (0x01 << 2)
448#define MGA1064_DISP_CTL_DAC2OUTSEL_CRTC2 (0x02 << 2)
449#define MGA1064_DISP_CTL_DAC2OUTSEL_TVE (0x03 << 2)
450#define MGA1064_DISP_CTL_PANOUTSEL_MASK (0x03 << 5)
451#define MGA1064_DISP_CTL_PANOUTSEL_DIS 0x00
452#define MGA1064_DISP_CTL_PANOUTSEL_CRTC1 (0x01 << 5)
453#define MGA1064_DISP_CTL_PANOUTSEL_CRTC2RGB (0x02 << 5)
454#define MGA1064_DISP_CTL_PANOUTSEL_CRTC2656 (0x03 << 5)
455
456#define MGA1064_SYNC_CTL 0x8b
457
458#define MGA1064_PWR_CTL 0xa0
459#define MGA1064_PWR_CTL_DAC2_EN (0x01 << 0)
460#define MGA1064_PWR_CTL_VID_PLL_EN (0x01 << 1)
461#define MGA1064_PWR_CTL_PANEL_EN (0x01 << 2)
462#define MGA1064_PWR_CTL_RFIFO_EN (0x01 << 3)
463#define MGA1064_PWR_CTL_CFIFO_EN (0x01 << 4)
464
465#define MGA1064_PAN_CTL 0xa2
466
467/* Using crtc2 */
468#define MGAREG2_C2CTL 0x10
469#define MGAREG2_C2HPARAM 0x14
470#define MGAREG2_C2HSYNC 0x18
471#define MGAREG2_C2VPARAM 0x1c
472#define MGAREG2_C2VSYNC 0x20
473#define MGAREG2_C2STARTADD0 0x28
474
475#define MGAREG2_C2OFFSET 0x40
476#define MGAREG2_C2DATACTL 0x4c
477
478#define MGAREG_C2CTL 0x3c10
479#define MGAREG_C2CTL_C2_EN 0x01
480
481#define MGAREG_C2_HIPRILVL_M (0x07 << 4)
482#define MGAREG_C2_MAXHIPRI_M (0x07 << 8)
483
484#define MGAREG_C2CTL_PIXCLKSEL_MASK (0x03 << 1)
485#define MGAREG_C2CTL_PIXCLKSELH_MASK (0x01 << 14)
486#define MGAREG_C2CTL_PIXCLKSEL_PCICLK 0x00
487#define MGAREG_C2CTL_PIXCLKSEL_VDOCLK (0x01 << 1)
488#define MGAREG_C2CTL_PIXCLKSEL_PIXELPLL (0x02 << 1)
489#define MGAREG_C2CTL_PIXCLKSEL_VIDEOPLL (0x03 << 1)
490#define MGAREG_C2CTL_PIXCLKSEL_VDCLK (0x01 << 14)
491
492#define MGAREG_C2CTL_PIXCLKSEL_CRISTAL (0x01 << 1) | (0x01 << 14)
493#define MGAREG_C2CTL_PIXCLKSEL_SYSTEMPLL (0x02 << 1) | (0x01 << 14)
494
495#define MGAREG_C2CTL_PIXCLKDIS_MASK (0x01 << 3)
496#define MGAREG_C2CTL_PIXCLKDIS_DISABLE (0x01 << 3)
497
498#define MGAREG_C2CTL_CRTCDACSEL_MASK (0x01 << 20)
499#define MGAREG_C2CTL_CRTCDACSEL_CRTC1 0x00
500#define MGAREG_C2CTL_CRTCDACSEL_CRTC2 (0x01 << 20)
501
502#define MGAREG_C2HPARAM 0x3c14
503#define MGAREG_C2HSYNC 0x3c18
504#define MGAREG_C2VPARAM 0x3c1c
505#define MGAREG_C2VSYNC 0x3c20
506#define MGAREG_C2STARTADD0 0x3c28
507
508#define MGAREG_C2OFFSET 0x3c40
509#define MGAREG_C2DATACTL 0x3c4c
510
511/* video register */
512
513#define MGAREG_BESA1C3ORG 0x3d60
514#define MGAREG_BESA1CORG 0x3d10
515#define MGAREG_BESA1ORG 0x3d00
516#define MGAREG_BESCTL 0x3d20
517#define MGAREG_BESGLOBCTL 0x3dc0
518#define MGAREG_BESHCOORD 0x3d28
519#define MGAREG_BESHISCAL 0x3d30
520#define MGAREG_BESHSRCEND 0x3d3c
521#define MGAREG_BESHSRCLST 0x3d50
522#define MGAREG_BESHSRCST 0x3d38
523#define MGAREG_BESLUMACTL 0x3d40
524#define MGAREG_BESPITCH 0x3d24
525#define MGAREG_BESV1SRCLST 0x3d54
526#define MGAREG_BESV1WGHT 0x3d48
527#define MGAREG_BESVCOORD 0x3d2c
528#define MGAREG_BESVISCAL 0x3d34
529
530/* texture engine registers */
531
532#define MGAREG_TMR0 0x2c00
533#define MGAREG_TMR1 0x2c04
534#define MGAREG_TMR2 0x2c08
535#define MGAREG_TMR3 0x2c0c
536#define MGAREG_TMR4 0x2c10
537#define MGAREG_TMR5 0x2c14
538#define MGAREG_TMR6 0x2c18
539#define MGAREG_TMR7 0x2c1c
540#define MGAREG_TMR8 0x2c20
541#define MGAREG_TEXORG 0x2c24
542#define MGAREG_TEXWIDTH 0x2c28
543#define MGAREG_TEXHEIGHT 0x2c2c
544#define MGAREG_TEXCTL 0x2c30
545# define MGA_TW4 (0x00000000)
546# define MGA_TW8 (0x00000001)
547# define MGA_TW15 (0x00000002)
548# define MGA_TW16 (0x00000003)
549# define MGA_TW12 (0x00000004)
550# define MGA_TW32 (0x00000006)
551# define MGA_TW8A (0x00000007)
552# define MGA_TW8AL (0x00000008)
553# define MGA_TW422 (0x0000000A)
554# define MGA_TW422UYVY (0x0000000B)
555# define MGA_PITCHLIN (0x00000100)
556# define MGA_NOPERSPECTIVE (0x00200000)
557# define MGA_TAKEY (0x02000000)
558# define MGA_TAMASK (0x04000000)
559# define MGA_CLAMPUV (0x18000000)
560# define MGA_TEXMODULATE (0x20000000)
561#define MGAREG_TEXCTL2 0x2c3c
562# define MGA_G400_TC2_MAGIC (0x00008000)
563# define MGA_TC2_DECALBLEND (0x00000001)
564# define MGA_TC2_IDECAL (0x00000002)
565# define MGA_TC2_DECALDIS (0x00000004)
566# define MGA_TC2_CKSTRANSDIS (0x00000010)
567# define MGA_TC2_BORDEREN (0x00000020)
568# define MGA_TC2_SPECEN (0x00000040)
569# define MGA_TC2_DUALTEX (0x00000080)
570# define MGA_TC2_TABLEFOG (0x00000100)
571# define MGA_TC2_BUMPMAP (0x00000200)
572# define MGA_TC2_SELECT_TMU1 (0x80000000)
573#define MGAREG_TEXTRANS 0x2c34
574#define MGAREG_TEXTRANSHIGH 0x2c38
575#define MGAREG_TEXFILTER 0x2c58
576# define MGA_MIN_NRST (0x00000000)
577# define MGA_MIN_BILIN (0x00000002)
578# define MGA_MIN_ANISO (0x0000000D)
579# define MGA_MAG_NRST (0x00000000)
580# define MGA_MAG_BILIN (0x00000020)
581# define MGA_FILTERALPHA (0x00100000)
582#define MGAREG_ALPHASTART 0x2c70
583#define MGAREG_ALPHAXINC 0x2c74
584#define MGAREG_ALPHAYINC 0x2c78
585#define MGAREG_ALPHACTRL 0x2c7c
586# define MGA_SRC_ZERO (0x00000000)
587# define MGA_SRC_ONE (0x00000001)
588# define MGA_SRC_DST_COLOR (0x00000002)
589# define MGA_SRC_ONE_MINUS_DST_COLOR (0x00000003)
590# define MGA_SRC_ALPHA (0x00000004)
591# define MGA_SRC_ONE_MINUS_SRC_ALPHA (0x00000005)
592# define MGA_SRC_DST_ALPHA (0x00000006)
593# define MGA_SRC_ONE_MINUS_DST_ALPHA (0x00000007)
594# define MGA_SRC_SRC_ALPHA_SATURATE (0x00000008)
595# define MGA_SRC_BLEND_MASK (0x0000000f)
596# define MGA_DST_ZERO (0x00000000)
597# define MGA_DST_ONE (0x00000010)
598# define MGA_DST_SRC_COLOR (0x00000020)
599# define MGA_DST_ONE_MINUS_SRC_COLOR (0x00000030)
600# define MGA_DST_SRC_ALPHA (0x00000040)
601# define MGA_DST_ONE_MINUS_SRC_ALPHA (0x00000050)
602# define MGA_DST_DST_ALPHA (0x00000060)
603# define MGA_DST_ONE_MINUS_DST_ALPHA (0x00000070)
604# define MGA_DST_BLEND_MASK (0x00000070)
605# define MGA_ALPHACHANNEL (0x00000100)
606# define MGA_VIDEOALPHA (0x00000200)
607# define MGA_DIFFUSEDALPHA (0x01000000)
608# define MGA_MODULATEDALPHA (0x02000000)
609#define MGAREG_TDUALSTAGE0 (0x2CF8)
610#define MGAREG_TDUALSTAGE1 (0x2CFC)
611# define MGA_TDS_COLOR_ARG2_DIFFUSE (0x00000000)
612# define MGA_TDS_COLOR_ARG2_SPECULAR (0x00000001)
613# define MGA_TDS_COLOR_ARG2_FCOL (0x00000002)
614# define MGA_TDS_COLOR_ARG2_PREVSTAGE (0x00000003)
615# define MGA_TDS_COLOR_ALPHA_DIFFUSE (0x00000000)
616# define MGA_TDS_COLOR_ALPHA_FCOL (0x00000004)
617# define MGA_TDS_COLOR_ALPHA_CURRTEX (0x00000008)
618# define MGA_TDS_COLOR_ALPHA_PREVTEX (0x0000000c)
619# define MGA_TDS_COLOR_ALPHA_PREVSTAGE (0x00000010)
620# define MGA_TDS_COLOR_ARG1_REPLICATEALPHA (0x00000020)
621# define MGA_TDS_COLOR_ARG1_INV (0x00000040)
622# define MGA_TDS_COLOR_ARG2_REPLICATEALPHA (0x00000080)
623# define MGA_TDS_COLOR_ARG2_INV (0x00000100)
624# define MGA_TDS_COLOR_ALPHA1INV (0x00000200)
625# define MGA_TDS_COLOR_ALPHA2INV (0x00000400)
626# define MGA_TDS_COLOR_ARG1MUL_ALPHA1 (0x00000800)
627# define MGA_TDS_COLOR_ARG2MUL_ALPHA2 (0x00001000)
628# define MGA_TDS_COLOR_ARG1ADD_MULOUT (0x00002000)
629# define MGA_TDS_COLOR_ARG2ADD_MULOUT (0x00004000)
630# define MGA_TDS_COLOR_MODBRIGHT_2X (0x00008000)
631# define MGA_TDS_COLOR_MODBRIGHT_4X (0x00010000)
632# define MGA_TDS_COLOR_ADD_SUB (0x00000000)
633# define MGA_TDS_COLOR_ADD_ADD (0x00020000)
634# define MGA_TDS_COLOR_ADD2X (0x00040000)
635# define MGA_TDS_COLOR_ADDBIAS (0x00080000)
636# define MGA_TDS_COLOR_BLEND (0x00100000)
637# define MGA_TDS_COLOR_SEL_ARG1 (0x00000000)
638# define MGA_TDS_COLOR_SEL_ARG2 (0x00200000)
639# define MGA_TDS_COLOR_SEL_ADD (0x00400000)
640# define MGA_TDS_COLOR_SEL_MUL (0x00600000)
641# define MGA_TDS_ALPHA_ARG1_INV (0x00800000)
642# define MGA_TDS_ALPHA_ARG2_DIFFUSE (0x00000000)
643# define MGA_TDS_ALPHA_ARG2_FCOL (0x01000000)
644# define MGA_TDS_ALPHA_ARG2_PREVTEX (0x02000000)
645# define MGA_TDS_ALPHA_ARG2_PREVSTAGE (0x03000000)
646# define MGA_TDS_ALPHA_ARG2_INV (0x04000000)
647# define MGA_TDS_ALPHA_ADD (0x08000000)
648# define MGA_TDS_ALPHA_ADDBIAS (0x10000000)
649# define MGA_TDS_ALPHA_ADD2X (0x20000000)
650# define MGA_TDS_ALPHA_SEL_ARG1 (0x00000000)
651# define MGA_TDS_ALPHA_SEL_ARG2 (0x40000000)
652# define MGA_TDS_ALPHA_SEL_ADD (0x80000000)
653# define MGA_TDS_ALPHA_SEL_MUL (0xc0000000)
654
655#define MGAREG_DWGSYNC 0x2c4c
656
657#define MGAREG_AGP_PLL 0x1e4c
658#define MGA_AGP2XPLL_ENABLE 0x1
659#define MGA_AGP2XPLL_DISABLE 0x0
660
661#endif
diff --git a/drivers/gpu/drm/mgag200/mgag200_ttm.c b/drivers/gpu/drm/mgag200/mgag200_ttm.c
new file mode 100644
index 000000000000..b223dcb7a710
--- /dev/null
+++ b/drivers/gpu/drm/mgag200/mgag200_ttm.c
@@ -0,0 +1,452 @@
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 "mgag200_drv.h"
30#include <ttm/ttm_page_alloc.h>
31
32static inline struct mga_device *
33mgag200_bdev(struct ttm_bo_device *bd)
34{
35 return container_of(bd, struct mga_device, ttm.bdev);
36}
37
38static int
39mgag200_ttm_mem_global_init(struct drm_global_reference *ref)
40{
41 return ttm_mem_global_init(ref->object);
42}
43
44static void
45mgag200_ttm_mem_global_release(struct drm_global_reference *ref)
46{
47 ttm_mem_global_release(ref->object);
48}
49
50static int mgag200_ttm_global_init(struct mga_device *ast)
51{
52 struct drm_global_reference *global_ref;
53 int r;
54
55 global_ref = &ast->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 = &mgag200_ttm_mem_global_init;
59 global_ref->release = &mgag200_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 ast->ttm.bo_global_ref.mem_glob =
68 ast->ttm.mem_global_ref.object;
69 global_ref = &ast->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(&ast->ttm.mem_global_ref);
78 return r;
79 }
80 return 0;
81}
82
83void
84mgag200_ttm_global_release(struct mga_device *ast)
85{
86 if (ast->ttm.mem_global_ref.release == NULL)
87 return;
88
89 drm_global_item_unref(&ast->ttm.bo_global_ref.ref);
90 drm_global_item_unref(&ast->ttm.mem_global_ref);
91 ast->ttm.mem_global_ref.release = NULL;
92}
93
94
95static void mgag200_bo_ttm_destroy(struct ttm_buffer_object *tbo)
96{
97 struct mgag200_bo *bo;
98
99 bo = container_of(tbo, struct mgag200_bo, bo);
100
101 drm_gem_object_release(&bo->gem);
102 kfree(bo);
103}
104
105bool mgag200_ttm_bo_is_mgag200_bo(struct ttm_buffer_object *bo)
106{
107 if (bo->destroy == &mgag200_bo_ttm_destroy)
108 return true;
109 return false;
110}
111
112static int
113mgag200_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
138mgag200_bo_evict_flags(struct ttm_buffer_object *bo, struct ttm_placement *pl)
139{
140 struct mgag200_bo *mgabo = mgag200_bo(bo);
141
142 if (!mgag200_ttm_bo_is_mgag200_bo(bo))
143 return;
144
145 mgag200_ttm_placement(mgabo, TTM_PL_FLAG_SYSTEM);
146 *pl = mgabo->placement;
147}
148
149static int mgag200_bo_verify_access(struct ttm_buffer_object *bo, struct file *filp)
150{
151 return 0;
152}
153
154static int mgag200_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 mga_device *mdev = mgag200_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(mdev->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 mgag200_ttm_io_mem_free(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
184{
185}
186
187static int mgag200_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 mgag200_ttm_backend_destroy(struct ttm_tt *tt)
199{
200 ttm_tt_fini(tt);
201 kfree(tt);
202}
203
204static struct ttm_backend_func mgag200_tt_backend_func = {
205 .destroy = &mgag200_ttm_backend_destroy,
206};
207
208
209struct ttm_tt *mgag200_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 = &mgag200_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 mgag200_ttm_tt_populate(struct ttm_tt *ttm)
227{
228 return ttm_pool_populate(ttm);
229}
230
231static void mgag200_ttm_tt_unpopulate(struct ttm_tt *ttm)
232{
233 ttm_pool_unpopulate(ttm);
234}
235
236struct ttm_bo_driver mgag200_bo_driver = {
237 .ttm_tt_create = mgag200_ttm_tt_create,
238 .ttm_tt_populate = mgag200_ttm_tt_populate,
239 .ttm_tt_unpopulate = mgag200_ttm_tt_unpopulate,
240 .init_mem_type = mgag200_bo_init_mem_type,
241 .evict_flags = mgag200_bo_evict_flags,
242 .move = mgag200_bo_move,
243 .verify_access = mgag200_bo_verify_access,
244 .io_mem_reserve = &mgag200_ttm_io_mem_reserve,
245 .io_mem_free = &mgag200_ttm_io_mem_free,
246};
247
248int mgag200_mm_init(struct mga_device *mdev)
249{
250 int ret;
251 struct drm_device *dev = mdev->dev;
252 struct ttm_bo_device *bdev = &mdev->ttm.bdev;
253
254 ret = mgag200_ttm_global_init(mdev);
255 if (ret)
256 return ret;
257
258 ret = ttm_bo_device_init(&mdev->ttm.bdev,
259 mdev->ttm.bo_global_ref.ref.object,
260 &mgag200_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, mdev->mc.vram_size >> PAGE_SHIFT);
268 if (ret) {
269 DRM_ERROR("Failed ttm VRAM init: %d\n", ret);
270 return ret;
271 }
272
273 mdev->fb_mtrr = drm_mtrr_add(pci_resource_start(dev->pdev, 0),
274 pci_resource_len(dev->pdev, 0),
275 DRM_MTRR_WC);
276
277 return 0;
278}
279
280void mgag200_mm_fini(struct mga_device *mdev)
281{
282 struct drm_device *dev = mdev->dev;
283 ttm_bo_device_release(&mdev->ttm.bdev);
284
285 mgag200_ttm_global_release(mdev);
286
287 if (mdev->fb_mtrr >= 0) {
288 drm_mtrr_del(mdev->fb_mtrr,
289 pci_resource_start(dev->pdev, 0),
290 pci_resource_len(dev->pdev, 0), DRM_MTRR_WC);
291 mdev->fb_mtrr = -1;
292 }
293}
294
295void mgag200_ttm_placement(struct mgag200_bo *bo, int domain)
296{
297 u32 c = 0;
298 bo->placement.fpfn = 0;
299 bo->placement.lpfn = 0;
300 bo->placement.placement = bo->placements;
301 bo->placement.busy_placement = bo->placements;
302 if (domain & TTM_PL_FLAG_VRAM)
303 bo->placements[c++] = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED | TTM_PL_FLAG_VRAM;
304 if (domain & TTM_PL_FLAG_SYSTEM)
305 bo->placements[c++] = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM;
306 if (!c)
307 bo->placements[c++] = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM;
308 bo->placement.num_placement = c;
309 bo->placement.num_busy_placement = c;
310}
311
312int mgag200_bo_reserve(struct mgag200_bo *bo, bool no_wait)
313{
314 int ret;
315
316 ret = ttm_bo_reserve(&bo->bo, true, no_wait, false, 0);
317 if (ret) {
318 if (ret != -ERESTARTSYS)
319 DRM_ERROR("reserve failed %p\n", bo);
320 return ret;
321 }
322 return 0;
323}
324
325void mgag200_bo_unreserve(struct mgag200_bo *bo)
326{
327 ttm_bo_unreserve(&bo->bo);
328}
329
330int mgag200_bo_create(struct drm_device *dev, int size, int align,
331 uint32_t flags, struct mgag200_bo **pmgabo)
332{
333 struct mga_device *mdev = dev->dev_private;
334 struct mgag200_bo *mgabo;
335 size_t acc_size;
336 int ret;
337
338 mgabo = kzalloc(sizeof(struct mgag200_bo), GFP_KERNEL);
339 if (!mgabo)
340 return -ENOMEM;
341
342 ret = drm_gem_object_init(dev, &mgabo->gem, size);
343 if (ret) {
344 kfree(mgabo);
345 return ret;
346 }
347
348 mgabo->gem.driver_private = NULL;
349 mgabo->bo.bdev = &mdev->ttm.bdev;
350
351 mgag200_ttm_placement(mgabo, TTM_PL_FLAG_VRAM | TTM_PL_FLAG_SYSTEM);
352
353 acc_size = ttm_bo_dma_acc_size(&mdev->ttm.bdev, size,
354 sizeof(struct mgag200_bo));
355
356 ret = ttm_bo_init(&mdev->ttm.bdev, &mgabo->bo, size,
357 ttm_bo_type_device, &mgabo->placement,
358 align >> PAGE_SHIFT, 0, false, NULL, acc_size,
359 NULL, mgag200_bo_ttm_destroy);
360 if (ret)
361 return ret;
362
363 *pmgabo = mgabo;
364 return 0;
365}
366
367static inline u64 mgag200_bo_gpu_offset(struct mgag200_bo *bo)
368{
369 return bo->bo.offset;
370}
371
372int mgag200_bo_pin(struct mgag200_bo *bo, u32 pl_flag, u64 *gpu_addr)
373{
374 int i, ret;
375
376 if (bo->pin_count) {
377 bo->pin_count++;
378 if (gpu_addr)
379 *gpu_addr = mgag200_bo_gpu_offset(bo);
380 }
381
382 mgag200_ttm_placement(bo, pl_flag);
383 for (i = 0; i < bo->placement.num_placement; i++)
384 bo->placements[i] |= TTM_PL_FLAG_NO_EVICT;
385 ret = ttm_bo_validate(&bo->bo, &bo->placement, false, false, false);
386 if (ret)
387 return ret;
388
389 bo->pin_count = 1;
390 if (gpu_addr)
391 *gpu_addr = mgag200_bo_gpu_offset(bo);
392 return 0;
393}
394
395int mgag200_bo_unpin(struct mgag200_bo *bo)
396{
397 int i, ret;
398 if (!bo->pin_count) {
399 DRM_ERROR("unpin bad %p\n", bo);
400 return 0;
401 }
402 bo->pin_count--;
403 if (bo->pin_count)
404 return 0;
405
406 for (i = 0; i < bo->placement.num_placement ; i++)
407 bo->placements[i] &= ~TTM_PL_FLAG_NO_EVICT;
408 ret = ttm_bo_validate(&bo->bo, &bo->placement, false, false, false);
409 if (ret)
410 return ret;
411
412 return 0;
413}
414
415int mgag200_bo_push_sysram(struct mgag200_bo *bo)
416{
417 int i, ret;
418 if (!bo->pin_count) {
419 DRM_ERROR("unpin bad %p\n", bo);
420 return 0;
421 }
422 bo->pin_count--;
423 if (bo->pin_count)
424 return 0;
425
426 if (bo->kmap.virtual)
427 ttm_bo_kunmap(&bo->kmap);
428
429 mgag200_ttm_placement(bo, TTM_PL_FLAG_SYSTEM);
430 for (i = 0; i < bo->placement.num_placement ; i++)
431 bo->placements[i] |= TTM_PL_FLAG_NO_EVICT;
432
433 ret = ttm_bo_validate(&bo->bo, &bo->placement, false, false, false);
434 if (ret) {
435 DRM_ERROR("pushing to VRAM failed\n");
436 return ret;
437 }
438 return 0;
439}
440
441int mgag200_mmap(struct file *filp, struct vm_area_struct *vma)
442{
443 struct drm_file *file_priv;
444 struct mga_device *mdev;
445
446 if (unlikely(vma->vm_pgoff < DRM_FILE_PAGE_OFFSET))
447 return drm_mmap(filp, vma);
448
449 file_priv = filp->private_data;
450 mdev = file_priv->minor->dev->dev_private;
451 return ttm_bo_mmap(filp, vma, &mdev->ttm.bdev);
452}