aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/video/intelfb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/video/intelfb')
-rw-r--r--drivers/video/intelfb/Makefile8
-rw-r--r--drivers/video/intelfb/intelfb.h280
-rw-r--r--drivers/video/intelfb/intelfbdrv.c1570
-rw-r--r--drivers/video/intelfb/intelfbdrv.h68
-rw-r--r--drivers/video/intelfb/intelfbhw.c1780
-rw-r--r--drivers/video/intelfb/intelfbhw.h570
6 files changed, 4276 insertions, 0 deletions
diff --git a/drivers/video/intelfb/Makefile b/drivers/video/intelfb/Makefile
new file mode 100644
index 00000000000..722d21d6e5c
--- /dev/null
+++ b/drivers/video/intelfb/Makefile
@@ -0,0 +1,8 @@
1obj-$(CONFIG_FB_INTEL) += intelfb.o
2
3intelfb-objs := intelfbdrv.o intelfbhw.o
4
5ifdef CONFIG_FB_INTEL_DEBUG
6#EXTRA_CFLAGS += -DDEBUG -DVERBOSE -DREGDUMP
7EXTRA_CFLAGS += -DDEBUG -DREGDUMP
8endif
diff --git a/drivers/video/intelfb/intelfb.h b/drivers/video/intelfb/intelfb.h
new file mode 100644
index 00000000000..6680ec9ba69
--- /dev/null
+++ b/drivers/video/intelfb/intelfb.h
@@ -0,0 +1,280 @@
1#ifndef _INTELFB_H
2#define _INTELFB_H
3
4/* $DHD: intelfb/intelfb.h,v 1.40 2003/06/27 15:06:25 dawes Exp $ */
5
6#include <linux/agp_backend.h>
7#include <linux/fb.h>
8
9
10/*** Version/name ***/
11#define INTELFB_VERSION "0.9.2"
12#define INTELFB_MODULE_NAME "intelfb"
13#define SUPPORTED_CHIPSETS "830M/845G/852GM/855GM/865G/915G"
14
15
16/*** Debug/feature defines ***/
17
18#ifndef DEBUG
19#define DEBUG 0
20#endif
21
22#ifndef VERBOSE
23#define VERBOSE 0
24#endif
25
26#ifndef REGDUMP
27#define REGDUMP 0
28#endif
29
30#ifndef DETECT_VGA_CLASS_ONLY
31#define DETECT_VGA_CLASS_ONLY 1
32#endif
33
34#ifndef ALLOCATE_FOR_PANNING
35#define ALLOCATE_FOR_PANNING 1
36#endif
37
38#ifndef PREFERRED_MODE
39#define PREFERRED_MODE "1024x768-32@70"
40#endif
41
42/*** hw-related values ***/
43
44/* PCI ids for supported devices */
45#define PCI_DEVICE_ID_INTEL_830M 0x3577
46#define PCI_DEVICE_ID_INTEL_845G 0x2562
47#define PCI_DEVICE_ID_INTEL_85XGM 0x3582
48#define PCI_DEVICE_ID_INTEL_865G 0x2572
49#define PCI_DEVICE_ID_INTEL_915G 0x2582
50
51/* Size of MMIO region */
52#define INTEL_REG_SIZE 0x80000
53
54#define STRIDE_ALIGNMENT 16
55
56#define PALETTE_8_ENTRIES 256
57
58
59/*** Macros ***/
60
61/* basic arithmetic */
62#define KB(x) ((x) * 1024)
63#define MB(x) ((x) * 1024 * 1024)
64#define BtoKB(x) ((x) / 1024)
65#define BtoMB(x) ((x) / 1024 / 1024)
66
67#define GTT_PAGE_SIZE KB(4)
68
69#define ROUND_UP_TO(x, y) (((x) + (y) - 1) / (y) * (y))
70#define ROUND_DOWN_TO(x, y) ((x) / (y) * (y))
71#define ROUND_UP_TO_PAGE(x) ROUND_UP_TO((x), GTT_PAGE_SIZE)
72#define ROUND_DOWN_TO_PAGE(x) ROUND_DOWN_TO((x), GTT_PAGE_SIZE)
73
74/* messages */
75#define PFX INTELFB_MODULE_NAME ": "
76
77#define ERR_MSG(fmt, args...) printk(KERN_ERR PFX fmt, ## args)
78#define WRN_MSG(fmt, args...) printk(KERN_WARNING PFX fmt, ## args)
79#define NOT_MSG(fmt, args...) printk(KERN_NOTICE PFX fmt, ## args)
80#define INF_MSG(fmt, args...) printk(KERN_INFO PFX fmt, ## args)
81#if DEBUG
82#define DBG_MSG(fmt, args...) printk(KERN_DEBUG PFX fmt, ## args)
83#else
84#define DBG_MSG(fmt, args...) while (0) printk(fmt, ## args)
85#endif
86
87/* get commonly used pointers */
88#define GET_DINFO(info) (info)->par
89
90/* misc macros */
91#define ACCEL(d, i) \
92 ((d)->accel && !(d)->ring_lockup && \
93 ((i)->var.accel_flags & FB_ACCELF_TEXT))
94
95/*#define NOACCEL_CHIPSET(d) \
96 ((d)->chipset != INTEL_865G)*/
97#define NOACCEL_CHIPSET(d) \
98 (0)
99
100#define FIXED_MODE(d) ((d)->fixed_mode)
101
102/*** Driver paramters ***/
103
104#define RINGBUFFER_SIZE KB(64)
105#define HW_CURSOR_SIZE KB(4)
106
107/* Intel agpgart driver */
108#define AGP_PHYSICAL_MEMORY 2
109
110/*** Data Types ***/
111
112/* supported chipsets */
113enum intel_chips {
114 INTEL_830M,
115 INTEL_845G,
116 INTEL_85XGM,
117 INTEL_852GM,
118 INTEL_852GME,
119 INTEL_855GM,
120 INTEL_855GME,
121 INTEL_865G,
122 INTEL_915G
123};
124
125struct intelfb_hwstate {
126 u32 vga0_divisor;
127 u32 vga1_divisor;
128 u32 vga_pd;
129 u32 dpll_a;
130 u32 dpll_b;
131 u32 fpa0;
132 u32 fpa1;
133 u32 fpb0;
134 u32 fpb1;
135 u32 palette_a[PALETTE_8_ENTRIES];
136 u32 palette_b[PALETTE_8_ENTRIES];
137 u32 htotal_a;
138 u32 hblank_a;
139 u32 hsync_a;
140 u32 vtotal_a;
141 u32 vblank_a;
142 u32 vsync_a;
143 u32 src_size_a;
144 u32 bclrpat_a;
145 u32 htotal_b;
146 u32 hblank_b;
147 u32 hsync_b;
148 u32 vtotal_b;
149 u32 vblank_b;
150 u32 vsync_b;
151 u32 src_size_b;
152 u32 bclrpat_b;
153 u32 adpa;
154 u32 dvoa;
155 u32 dvob;
156 u32 dvoc;
157 u32 dvoa_srcdim;
158 u32 dvob_srcdim;
159 u32 dvoc_srcdim;
160 u32 lvds;
161 u32 pipe_a_conf;
162 u32 pipe_b_conf;
163 u32 disp_arb;
164 u32 cursor_a_control;
165 u32 cursor_b_control;
166 u32 cursor_a_base;
167 u32 cursor_b_base;
168 u32 cursor_size;
169 u32 disp_a_ctrl;
170 u32 disp_b_ctrl;
171 u32 disp_a_base;
172 u32 disp_b_base;
173 u32 cursor_a_palette[4];
174 u32 cursor_b_palette[4];
175 u32 disp_a_stride;
176 u32 disp_b_stride;
177 u32 vgacntrl;
178 u32 add_id;
179 u32 swf0x[7];
180 u32 swf1x[7];
181 u32 swf3x[3];
182 u32 fence[8];
183 u32 instpm;
184 u32 mem_mode;
185 u32 fw_blc_0;
186 u32 fw_blc_1;
187};
188
189struct intelfb_heap_data {
190 u32 physical;
191 u8 __iomem *virtual;
192 u32 offset; // in GATT pages
193 u32 size; // in bytes
194};
195
196struct intelfb_info {
197 struct fb_info *info;
198 struct fb_ops *fbops;
199 struct pci_dev *pdev;
200
201 struct intelfb_hwstate save_state;
202
203 /* agpgart structs */
204 struct agp_memory *gtt_fb_mem; // use all stolen memory or vram
205 struct agp_memory *gtt_ring_mem; // ring buffer
206 struct agp_memory *gtt_cursor_mem; // hw cursor
207
208 /* use a gart reserved fb mem */
209 u8 fbmem_gart;
210
211 /* mtrr support */
212 u32 mtrr_reg;
213 u32 has_mtrr;
214
215 /* heap data */
216 struct intelfb_heap_data aperture;
217 struct intelfb_heap_data fb;
218 struct intelfb_heap_data ring;
219 struct intelfb_heap_data cursor;
220
221 /* mmio regs */
222 u32 mmio_base_phys;
223 u8 __iomem *mmio_base;
224
225 /* fb start offset (in bytes) */
226 u32 fb_start;
227
228 /* ring buffer */
229 u8 __iomem *ring_head;
230 u32 ring_tail;
231 u32 ring_tail_mask;
232 u32 ring_space;
233 u32 ring_lockup;
234
235 /* palette */
236 u32 pseudo_palette[17];
237 struct { u8 red, green, blue, pad; } palette[256];
238
239 /* chip info */
240 int pci_chipset;
241 int chipset;
242 const char *name;
243 int mobile;
244
245 /* current mode */
246 int bpp, depth;
247 u32 visual;
248 int xres, yres, pitch;
249 int pixclock;
250
251 /* current pipe */
252 int pipe;
253
254 /* some flags */
255 int accel;
256 int hwcursor;
257 int fixed_mode;
258 int ring_active;
259
260 /* hw cursor */
261 int cursor_on;
262 int cursor_blanked;
263 u8 cursor_src[64];
264
265 /* initial parameters */
266 int initial_vga;
267 struct fb_var_screeninfo initial_var;
268 u32 initial_fb_base;
269 u32 initial_video_ram;
270 u32 initial_pitch;
271
272 /* driver registered */
273 int registered;
274};
275
276/*** function prototypes ***/
277
278extern int intelfb_var_to_depth(const struct fb_var_screeninfo *var);
279
280#endif /* _INTELFB_H */
diff --git a/drivers/video/intelfb/intelfbdrv.c b/drivers/video/intelfb/intelfbdrv.c
new file mode 100644
index 00000000000..6a05b700083
--- /dev/null
+++ b/drivers/video/intelfb/intelfbdrv.c
@@ -0,0 +1,1570 @@
1/*
2 * intelfb
3 *
4 * Linux framebuffer driver for Intel(R) 830M/845G/852GM/855GM/865G/915G
5 * integrated graphics chips.
6 *
7 * Copyright © 2002, 2003 David Dawes <dawes@xfree86.org>
8 * 2004 Sylvain Meyer
9 *
10 * This driver consists of two parts. The first part (intelfbdrv.c) provides
11 * the basic fbdev interfaces, is derived in part from the radeonfb and
12 * vesafb drivers, and is covered by the GPL. The second part (intelfbhw.c)
13 * provides the code to program the hardware. Most of it is derived from
14 * the i810/i830 XFree86 driver. The HW-specific code is covered here
15 * under a dual license (GPL and MIT/XFree86 license).
16 *
17 * Author: David Dawes
18 *
19 */
20
21/* $DHD: intelfb/intelfbdrv.c,v 1.20 2003/06/27 15:17:40 dawes Exp $ */
22
23/*
24 * Changes:
25 * 01/2003 - Initial driver (0.1.0), no mode switching, no acceleration.
26 * This initial version is a basic core that works a lot like
27 * the vesafb driver. It must be built-in to the kernel,
28 * and the initial video mode must be set with vga=XXX at
29 * boot time. (David Dawes)
30 *
31 * 01/2003 - Version 0.2.0: Mode switching added, colormap support
32 * implemented, Y panning, and soft screen blanking implemented.
33 * No acceleration yet. (David Dawes)
34 *
35 * 01/2003 - Version 0.3.0: fbcon acceleration support added. Module
36 * option handling added. (David Dawes)
37 *
38 * 01/2003 - Version 0.4.0: fbcon HW cursor support added. (David Dawes)
39 *
40 * 01/2003 - Version 0.4.1: Add auto-generation of built-in modes.
41 * (David Dawes)
42 *
43 * 02/2003 - Version 0.4.2: Add check for active non-CRT devices, and
44 * mode validation checks. (David Dawes)
45 *
46 * 02/2003 - Version 0.4.3: Check when the VC is in graphics mode so that
47 * acceleration is disabled while an XFree86 server is running.
48 * (David Dawes)
49 *
50 * 02/2003 - Version 0.4.4: Monitor DPMS support. (David Dawes)
51 *
52 * 02/2003 - Version 0.4.5: Basic XFree86 + fbdev working. (David Dawes)
53 *
54 * 02/2003 - Version 0.5.0: Modify to work with the 2.5.32 kernel as well
55 * as 2.4.x kernels. (David Dawes)
56 *
57 * 02/2003 - Version 0.6.0: Split out HW-specifics into a separate file.
58 * (David Dawes)
59 *
60 * 02/2003 - Version 0.7.0: Test on 852GM/855GM. Acceleration and HW
61 * cursor are disabled on this platform. (David Dawes)
62 *
63 * 02/2003 - Version 0.7.1: Test on 845G. Acceleration is disabled
64 * on this platform. (David Dawes)
65 *
66 * 02/2003 - Version 0.7.2: Test on 830M. Acceleration and HW
67 * cursor are disabled on this platform. (David Dawes)
68 *
69 * 02/2003 - Version 0.7.3: Fix 8-bit modes for mobile platforms
70 * (David Dawes)
71 *
72 * 02/2003 - Version 0.7.4: Add checks for FB and FBCON_HAS_CFB* configured
73 * in the kernel, and add mode bpp verification and default
74 * bpp selection based on which FBCON_HAS_CFB* are configured.
75 * (David Dawes)
76 *
77 * 02/2003 - Version 0.7.5: Add basic package/install scripts based on the
78 * DRI packaging scripts. (David Dawes)
79 *
80 * 04/2003 - Version 0.7.6: Fix typo that affects builds with SMP-enabled
81 * kernels. (David Dawes, reported by Anupam).
82 *
83 * 06/2003 - Version 0.7.7:
84 * Fix Makefile.kernel build problem (Tsutomu Yasuda).
85 * Fix mis-placed #endif (2.4.21 kernel).
86 *
87 * 09/2004 - Version 0.9.0 - by Sylvain Meyer
88 * Port to linux 2.6 kernel fbdev
89 * Fix HW accel and HW cursor on i845G
90 * Use of agpgart for fb memory reservation
91 * Add mtrr support
92 *
93 * 10/2004 - Version 0.9.1
94 * Use module_param instead of old MODULE_PARM
95 * Some cleanup
96 *
97 * 11/2004 - Version 0.9.2
98 * Add vram option to reserve more memory than stolen by BIOS
99 * Fix intelfbhw_pan_display typo
100 * Add __initdata annotations
101 *
102 * TODO:
103 *
104 *
105 * Wish List:
106 *
107 *
108 */
109
110#include <linux/config.h>
111#include <linux/module.h>
112#include <linux/kernel.h>
113#include <linux/errno.h>
114#include <linux/string.h>
115#include <linux/mm.h>
116#include <linux/tty.h>
117#include <linux/slab.h>
118#include <linux/delay.h>
119#include <linux/fb.h>
120#include <linux/console.h>
121#include <linux/selection.h>
122#include <linux/ioport.h>
123#include <linux/init.h>
124#include <linux/pci.h>
125#include <linux/vmalloc.h>
126#include <linux/kd.h>
127#include <linux/vt_kern.h>
128#include <linux/pagemap.h>
129#include <linux/version.h>
130
131#include <asm/io.h>
132
133#ifdef CONFIG_MTRR
134#include <asm/mtrr.h>
135#endif
136
137#include "intelfb.h"
138#include "intelfbdrv.h"
139#include "intelfbhw.h"
140
141/*
142 * Limiting the class to PCI_CLASS_DISPLAY_VGA prevents function 1 of the
143 * mobile chipsets from being registered.
144 */
145#if DETECT_VGA_CLASS_ONLY
146#define INTELFB_CLASS_MASK ~0 << 8
147#else
148#define INTELFB_CLASS_MASK 0
149#endif
150
151static struct pci_device_id intelfb_pci_table[] __devinitdata = {
152 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_830M, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_830M },
153 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_845G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_845G },
154 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_85XGM, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_85XGM },
155 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_865G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_865G },
156 { PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_915G, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_DISPLAY_VGA << 8, INTELFB_CLASS_MASK, INTEL_915G },
157 { 0, }
158};
159
160/* Global data */
161static int num_registered = 0;
162
163/* fb ops */
164static struct fb_ops intel_fb_ops = {
165 .owner = THIS_MODULE,
166 .fb_check_var = intelfb_check_var,
167 .fb_set_par = intelfb_set_par,
168 .fb_setcolreg = intelfb_setcolreg,
169 .fb_blank = intelfb_blank,
170 .fb_pan_display = intelfb_pan_display,
171 .fb_fillrect = intelfb_fillrect,
172 .fb_copyarea = intelfb_copyarea,
173 .fb_imageblit = intelfb_imageblit,
174 .fb_cursor = intelfb_cursor,
175 .fb_sync = intelfb_sync,
176 .fb_ioctl = intelfb_ioctl
177};
178
179/* PCI driver module table */
180static struct pci_driver intelfb_driver = {
181 .name = "Intel(R) " SUPPORTED_CHIPSETS " Framebuffer Driver",
182 .id_table = intelfb_pci_table,
183 .probe = intelfb_pci_register,
184 .remove = __devexit_p(intelfb_pci_unregister)
185};
186
187/* Module description/parameters */
188MODULE_AUTHOR("David Dawes <dawes@tungstengraphics.com>, "
189 "Sylvain Meyer <sylvain.meyer@worldonline.fr>");
190MODULE_DESCRIPTION(
191 "Framebuffer driver for Intel(R) " SUPPORTED_CHIPSETS " chipsets");
192MODULE_LICENSE("Dual BSD/GPL");
193MODULE_DEVICE_TABLE(pci, intelfb_pci_table);
194
195static int accel __initdata = 1;
196static int vram __initdata = 4;
197static int hwcursor __initdata = 1;
198static int mtrr __initdata = 1;
199static int fixed __initdata = 0;
200static int noinit __initdata = 0;
201static int noregister __initdata = 0;
202static int probeonly __initdata = 0;
203static int idonly __initdata = 0;
204static int bailearly __initdata = 0;
205static char *mode __initdata = NULL;
206
207module_param(accel, bool, S_IRUGO);
208MODULE_PARM_DESC(accel, "Enable console acceleration");
209module_param(vram, int, S_IRUGO);
210MODULE_PARM_DESC(vram, "System RAM to allocate to framebuffer in MiB");
211module_param(hwcursor, bool, S_IRUGO);
212MODULE_PARM_DESC(hwcursor, "Enable HW cursor");
213module_param(mtrr, bool, S_IRUGO);
214MODULE_PARM_DESC(mtrr, "Enable MTRR support");
215module_param(fixed, bool, S_IRUGO);
216MODULE_PARM_DESC(fixed, "Disable mode switching");
217module_param(noinit, bool, 0);
218MODULE_PARM_DESC(noinit, "Don't initialise graphics mode when loading");
219module_param(noregister, bool, 0);
220MODULE_PARM_DESC(noregister, "Don't register, just probe and exit (debug)");
221module_param(probeonly, bool, 0);
222MODULE_PARM_DESC(probeonly, "Do a minimal probe (debug)");
223module_param(idonly, bool, 0);
224MODULE_PARM_DESC(idonly, "Just identify without doing anything else (debug)");
225module_param(bailearly, bool, 0);
226MODULE_PARM_DESC(bailearly, "Bail out early, depending on value (debug)");
227module_param(mode, charp, S_IRUGO);
228MODULE_PARM_DESC(mode,
229 "Initial video mode \"<xres>x<yres>[-<depth>][@<refresh>]\"");
230
231#ifndef MODULE
232#define OPT_EQUAL(opt, name) (!strncmp(opt, name, strlen(name)))
233#define OPT_INTVAL(opt, name) simple_strtoul(opt + strlen(name), NULL, 0)
234#define OPT_STRVAL(opt, name) (opt + strlen(name))
235
236static __inline__ char *
237get_opt_string(const char *this_opt, const char *name)
238{
239 const char *p;
240 int i;
241 char *ret;
242
243 p = OPT_STRVAL(this_opt, name);
244 i = 0;
245 while (p[i] && p[i] != ' ' && p[i] != ',')
246 i++;
247 ret = kmalloc(i + 1, GFP_KERNEL);
248 if (ret) {
249 strncpy(ret, p, i);
250 ret[i] = '\0';
251 }
252 return ret;
253}
254
255static __inline__ int
256get_opt_int(const char *this_opt, const char *name, int *ret)
257{
258 if (!ret)
259 return 0;
260
261 if (!OPT_EQUAL(this_opt, name))
262 return 0;
263
264 *ret = OPT_INTVAL(this_opt, name);
265 return 1;
266}
267
268static __inline__ int
269get_opt_bool(const char *this_opt, const char *name, int *ret)
270{
271 if (!ret)
272 return 0;
273
274 if (OPT_EQUAL(this_opt, name)) {
275 if (this_opt[strlen(name)] == '=')
276 *ret = simple_strtoul(this_opt + strlen(name) + 1,
277 NULL, 0);
278 else
279 *ret = 1;
280 } else {
281 if (OPT_EQUAL(this_opt, "no") && OPT_EQUAL(this_opt + 2, name))
282 *ret = 0;
283 else
284 return 0;
285 }
286 return 1;
287}
288
289static int __init
290intelfb_setup(char *options)
291{
292 char *this_opt;
293
294 DBG_MSG("intelfb_setup\n");
295
296 if (!options || !*options) {
297 DBG_MSG("no options\n");
298 return 0;
299 } else
300 DBG_MSG("options: %s\n", options);
301
302 /*
303 * These are the built-in options analogous to the module parameters
304 * defined above.
305 *
306 * The syntax is:
307 *
308 * video=intelfb:[mode][,<param>=<val>] ...
309 *
310 * e.g.,
311 *
312 * video=intelfb:1024x768-16@75,accel=0
313 */
314
315 while ((this_opt = strsep(&options, ","))) {
316 if (!*this_opt)
317 continue;
318 if (get_opt_bool(this_opt, "accel", &accel))
319 ;
320 else if (get_opt_int(this_opt, "vram", &vram))
321 ;
322 else if (get_opt_bool(this_opt, "hwcursor", &hwcursor))
323 ;
324 else if (get_opt_bool(this_opt, "mtrr", &mtrr))
325 ;
326 else if (get_opt_bool(this_opt, "fixed", &fixed))
327 ;
328 else if (get_opt_bool(this_opt, "init", &noinit))
329 noinit = !noinit;
330 else if (OPT_EQUAL(this_opt, "mode="))
331 mode = get_opt_string(this_opt, "mode=");
332 else
333 mode = this_opt;
334 }
335
336 return 0;
337}
338
339#endif
340
341static int __init
342intelfb_init(void)
343{
344#ifndef MODULE
345 char *option = NULL;
346#endif
347
348 DBG_MSG("intelfb_init\n");
349
350 INF_MSG("Framebuffer driver for "
351 "Intel(R) " SUPPORTED_CHIPSETS " chipsets\n");
352 INF_MSG("Version " INTELFB_VERSION "\n");
353
354 if (idonly)
355 return -ENODEV;
356
357#ifndef MODULE
358 if (fb_get_options("intelfb", &option))
359 return -ENODEV;
360 intelfb_setup(option);
361#endif
362
363 return pci_register_driver(&intelfb_driver);
364}
365
366static void __exit
367intelfb_exit(void)
368{
369 DBG_MSG("intelfb_exit\n");
370 pci_unregister_driver(&intelfb_driver);
371}
372
373module_init(intelfb_init);
374module_exit(intelfb_exit);
375
376/***************************************************************
377 * mtrr support functions *
378 ***************************************************************/
379
380#ifdef CONFIG_MTRR
381static inline void __devinit set_mtrr(struct intelfb_info *dinfo)
382{
383 dinfo->mtrr_reg = mtrr_add(dinfo->aperture.physical,
384 dinfo->aperture.size, MTRR_TYPE_WRCOMB, 1);
385 if (dinfo->mtrr_reg < 0) {
386 ERR_MSG("unable to set MTRR\n");
387 return;
388 }
389 dinfo->has_mtrr = 1;
390}
391static inline void unset_mtrr(struct intelfb_info *dinfo)
392{
393 if (dinfo->has_mtrr)
394 mtrr_del(dinfo->mtrr_reg, dinfo->aperture.physical,
395 dinfo->aperture.size);
396}
397#else
398#define set_mtrr(x) WRN_MSG("MTRR is disabled in the kernel\n")
399
400#define unset_mtrr(x) do { } while (0)
401#endif /* CONFIG_MTRR */
402
403/***************************************************************
404 * driver init / cleanup *
405 ***************************************************************/
406
407static void
408cleanup(struct intelfb_info *dinfo)
409{
410 DBG_MSG("cleanup\n");
411
412 if (!dinfo)
413 return;
414
415 fb_dealloc_cmap(&dinfo->info->cmap);
416 kfree(dinfo->info->pixmap.addr);
417
418 if (dinfo->registered)
419 unregister_framebuffer(dinfo->info);
420
421 unset_mtrr(dinfo);
422
423 if (dinfo->fbmem_gart && dinfo->gtt_fb_mem) {
424 agp_unbind_memory(dinfo->gtt_fb_mem);
425 agp_free_memory(dinfo->gtt_fb_mem);
426 }
427 if (dinfo->gtt_cursor_mem) {
428 agp_unbind_memory(dinfo->gtt_cursor_mem);
429 agp_free_memory(dinfo->gtt_cursor_mem);
430 }
431 if (dinfo->gtt_ring_mem) {
432 agp_unbind_memory(dinfo->gtt_ring_mem);
433 agp_free_memory(dinfo->gtt_ring_mem);
434 }
435
436 if (dinfo->mmio_base)
437 iounmap((void __iomem *)dinfo->mmio_base);
438 if (dinfo->aperture.virtual)
439 iounmap((void __iomem *)dinfo->aperture.virtual);
440
441 if (dinfo->mmio_base_phys)
442 release_mem_region(dinfo->mmio_base_phys, INTEL_REG_SIZE);
443 if (dinfo->aperture.physical)
444 release_mem_region(dinfo->aperture.physical,
445 dinfo->aperture.size);
446 framebuffer_release(dinfo->info);
447}
448
449#define bailout(dinfo) do { \
450 DBG_MSG("bailout\n"); \
451 cleanup(dinfo); \
452 INF_MSG("Not going to register framebuffer, exiting...\n"); \
453 return -ENODEV; \
454} while (0)
455
456
457static int __devinit
458intelfb_pci_register(struct pci_dev *pdev, const struct pci_device_id *ent)
459{
460 struct fb_info *info;
461 struct intelfb_info *dinfo;
462 int i, j, err, dvo;
463 int aperture_size, stolen_size;
464 struct agp_kern_info gtt_info;
465 int agp_memtype;
466 const char *s;
467 struct agp_bridge_data *bridge;
468 int aperture_bar = 0;
469 int mmio_bar = 1;
470
471 DBG_MSG("intelfb_pci_register\n");
472
473 num_registered++;
474 if (num_registered != 1) {
475 ERR_MSG("Attempted to register %d devices "
476 "(should be only 1).\n", num_registered);
477 return -ENODEV;
478 }
479
480 info = framebuffer_alloc(sizeof(struct intelfb_info), &pdev->dev);
481 if (!info) {
482 ERR_MSG("Could not allocate memory for intelfb_info.\n");
483 return -ENODEV;
484 }
485 if (fb_alloc_cmap(&info->cmap, 256, 1) < 0) {
486 ERR_MSG("Could not allocate cmap for intelfb_info.\n");
487 goto err_out_cmap;
488 return -ENODEV;
489 }
490
491 dinfo = info->par;
492 dinfo->info = info;
493 dinfo->fbops = &intel_fb_ops;
494 dinfo->pdev = pdev;
495
496 /* Reserve pixmap space. */
497 info->pixmap.addr = kmalloc(64 * 1024, GFP_KERNEL);
498 if (info->pixmap.addr == NULL) {
499 ERR_MSG("Cannot reserve pixmap memory.\n");
500 goto err_out_pixmap;
501 }
502 memset(info->pixmap.addr, 0, 64 * 1024);
503
504 /* set early this option because it could be changed by tv encoder
505 driver */
506 dinfo->fixed_mode = fixed;
507
508 /* Enable device. */
509 if ((err = pci_enable_device(pdev))) {
510 ERR_MSG("Cannot enable device.\n");
511 cleanup(dinfo);
512 return -ENODEV;
513 }
514
515 /* Set base addresses. */
516 if (ent->device == PCI_DEVICE_ID_INTEL_915G) {
517 aperture_bar = 2;
518 mmio_bar = 0;
519 /* Disable HW cursor on 915G (not implemented yet) */
520 hwcursor = 0;
521 }
522 dinfo->aperture.physical = pci_resource_start(pdev, aperture_bar);
523 dinfo->aperture.size = pci_resource_len(pdev, aperture_bar);
524 dinfo->mmio_base_phys = pci_resource_start(pdev, mmio_bar);
525 DBG_MSG("fb aperture: 0x%llx/0x%llx, MMIO region: 0x%llx/0x%llx\n",
526 (unsigned long long)pci_resource_start(pdev, aperture_bar),
527 (unsigned long long)pci_resource_len(pdev, aperture_bar),
528 (unsigned long long)pci_resource_start(pdev, mmio_bar),
529 (unsigned long long)pci_resource_len(pdev, mmio_bar));
530
531 /* Reserve the fb and MMIO regions */
532 if (!request_mem_region(dinfo->aperture.physical, dinfo->aperture.size,
533 INTELFB_MODULE_NAME)) {
534 ERR_MSG("Cannot reserve FB region.\n");
535 cleanup(dinfo);
536 return -ENODEV;
537 }
538 if (!request_mem_region(dinfo->mmio_base_phys,
539 INTEL_REG_SIZE,
540 INTELFB_MODULE_NAME)) {
541 ERR_MSG("Cannot reserve MMIO region.\n");
542 cleanup(dinfo);
543 return -ENODEV;
544 }
545
546 /* Map the fb and MMIO regions */
547 dinfo->aperture.virtual = (u8 __iomem *)ioremap_nocache
548 (dinfo->aperture.physical, dinfo->aperture.size);
549 if (!dinfo->aperture.virtual) {
550 ERR_MSG("Cannot remap FB region.\n");
551 cleanup(dinfo);
552 return -ENODEV;
553 }
554 dinfo->mmio_base =
555 (u8 __iomem *)ioremap_nocache(dinfo->mmio_base_phys,
556 INTEL_REG_SIZE);
557 if (!dinfo->mmio_base) {
558 ERR_MSG("Cannot remap MMIO region.\n");
559 cleanup(dinfo);
560 return -ENODEV;
561 }
562
563 /* Get the chipset info. */
564 dinfo->pci_chipset = pdev->device;
565
566 if (intelfbhw_get_chipset(pdev, &dinfo->name, &dinfo->chipset,
567 &dinfo->mobile)) {
568 cleanup(dinfo);
569 return -ENODEV;
570 }
571
572 if (intelfbhw_get_memory(pdev, &aperture_size,&stolen_size)) {
573 cleanup(dinfo);
574 return -ENODEV;
575 }
576
577 INF_MSG("%02x:%02x.%d: %s, aperture size %dMB, "
578 "stolen memory %dkB\n",
579 pdev->bus->number, PCI_SLOT(pdev->devfn),
580 PCI_FUNC(pdev->devfn), dinfo->name,
581 BtoMB(aperture_size), BtoKB(stolen_size));
582
583 /* Set these from the options. */
584 dinfo->accel = accel;
585 dinfo->hwcursor = hwcursor;
586
587 if (NOACCEL_CHIPSET(dinfo) && dinfo->accel == 1) {
588 INF_MSG("Acceleration is not supported for the %s chipset.\n",
589 dinfo->name);
590 dinfo->accel = 0;
591 }
592
593 /* Framebuffer parameters - Use all the stolen memory if >= vram */
594 if (ROUND_UP_TO_PAGE(stolen_size) >= MB(vram)) {
595 dinfo->fb.size = ROUND_UP_TO_PAGE(stolen_size);
596 dinfo->fbmem_gart = 0;
597 } else {
598 dinfo->fb.size = MB(vram);
599 dinfo->fbmem_gart = 1;
600 }
601
602 /* Allocate space for the ring buffer and HW cursor if enabled. */
603 if (dinfo->accel) {
604 dinfo->ring.size = RINGBUFFER_SIZE;
605 dinfo->ring_tail_mask = dinfo->ring.size - 1;
606 }
607 if (dinfo->hwcursor) {
608 dinfo->cursor.size = HW_CURSOR_SIZE;
609 }
610
611 /* Use agpgart to manage the GATT */
612 if (!(bridge = agp_backend_acquire(pdev))) {
613 ERR_MSG("cannot acquire agp\n");
614 cleanup(dinfo);
615 return -ENODEV;
616 }
617
618 /* get the current gatt info */
619 if (agp_copy_info(bridge, &gtt_info)) {
620 ERR_MSG("cannot get agp info\n");
621 agp_backend_release(bridge);
622 cleanup(dinfo);
623 return -ENODEV;
624 }
625
626 /* set the mem offsets - set them after the already used pages */
627 if (dinfo->accel) {
628 dinfo->ring.offset = (stolen_size >> 12)
629 + gtt_info.current_memory;
630 }
631 if (dinfo->hwcursor) {
632 dinfo->cursor.offset = (stolen_size >> 12) +
633 + gtt_info.current_memory + (dinfo->ring.size >> 12);
634 }
635 if (dinfo->fbmem_gart) {
636 dinfo->fb.offset = (stolen_size >> 12) +
637 + gtt_info.current_memory + (dinfo->ring.size >> 12)
638 + (dinfo->cursor.size >> 12);
639 }
640
641 /* Allocate memories (which aren't stolen) */
642 if (dinfo->accel) {
643 if (!(dinfo->gtt_ring_mem =
644 agp_allocate_memory(bridge, dinfo->ring.size >> 12,
645 AGP_NORMAL_MEMORY))) {
646 ERR_MSG("cannot allocate ring buffer memory\n");
647 agp_backend_release(bridge);
648 cleanup(dinfo);
649 return -ENOMEM;
650 }
651 if (agp_bind_memory(dinfo->gtt_ring_mem,
652 dinfo->ring.offset)) {
653 ERR_MSG("cannot bind ring buffer memory\n");
654 agp_backend_release(bridge);
655 cleanup(dinfo);
656 return -EBUSY;
657 }
658 dinfo->ring.physical = dinfo->aperture.physical
659 + (dinfo->ring.offset << 12);
660 dinfo->ring.virtual = dinfo->aperture.virtual
661 + (dinfo->ring.offset << 12);
662 dinfo->ring_head = dinfo->ring.virtual;
663 }
664 if (dinfo->hwcursor) {
665 agp_memtype = dinfo->mobile ? AGP_PHYSICAL_MEMORY
666 : AGP_NORMAL_MEMORY;
667 if (!(dinfo->gtt_cursor_mem =
668 agp_allocate_memory(bridge, dinfo->cursor.size >> 12,
669 agp_memtype))) {
670 ERR_MSG("cannot allocate cursor memory\n");
671 agp_backend_release(bridge);
672 cleanup(dinfo);
673 return -ENOMEM;
674 }
675 if (agp_bind_memory(dinfo->gtt_cursor_mem,
676 dinfo->cursor.offset)) {
677 ERR_MSG("cannot bind cursor memory\n");
678 agp_backend_release(bridge);
679 cleanup(dinfo);
680 return -EBUSY;
681 }
682 if (dinfo->mobile)
683 dinfo->cursor.physical
684 = dinfo->gtt_cursor_mem->physical;
685 else
686 dinfo->cursor.physical = dinfo->aperture.physical
687 + (dinfo->cursor.offset << 12);
688 dinfo->cursor.virtual = dinfo->aperture.virtual
689 + (dinfo->cursor.offset << 12);
690 }
691 if (dinfo->fbmem_gart) {
692 if (!(dinfo->gtt_fb_mem =
693 agp_allocate_memory(bridge, dinfo->fb.size >> 12,
694 AGP_NORMAL_MEMORY))) {
695 WRN_MSG("cannot allocate framebuffer memory - use "
696 "the stolen one\n");
697 dinfo->fbmem_gart = 0;
698 }
699 if (agp_bind_memory(dinfo->gtt_fb_mem,
700 dinfo->fb.offset)) {
701 WRN_MSG("cannot bind framebuffer memory - use "
702 "the stolen one\n");
703 dinfo->fbmem_gart = 0;
704 }
705 }
706
707 /* update framebuffer memory parameters */
708 if (!dinfo->fbmem_gart)
709 dinfo->fb.offset = 0; /* starts at offset 0 */
710 dinfo->fb.physical = dinfo->aperture.physical
711 + (dinfo->fb.offset << 12);
712 dinfo->fb.virtual = dinfo->aperture.virtual + (dinfo->fb.offset << 12);
713 dinfo->fb_start = dinfo->fb.offset << 12;
714
715 /* release agpgart */
716 agp_backend_release(bridge);
717
718 if (mtrr)
719 set_mtrr(dinfo);
720
721 DBG_MSG("fb: 0x%x(+ 0x%x)/0x%x (0x%x)\n",
722 dinfo->fb.physical, dinfo->fb.offset, dinfo->fb.size,
723 (u32 __iomem ) dinfo->fb.virtual);
724 DBG_MSG("MMIO: 0x%x/0x%x (0x%x)\n",
725 dinfo->mmio_base_phys, INTEL_REG_SIZE,
726 (u32 __iomem) dinfo->mmio_base);
727 DBG_MSG("ring buffer: 0x%x/0x%x (0x%x)\n",
728 dinfo->ring.physical, dinfo->ring.size,
729 (u32 __iomem ) dinfo->ring.virtual);
730 DBG_MSG("HW cursor: 0x%x/0x%x (0x%x) (offset 0x%x) (phys 0x%x)\n",
731 dinfo->cursor.physical, dinfo->cursor.size,
732 (u32 __iomem ) dinfo->cursor.virtual, dinfo->cursor.offset,
733 dinfo->cursor.physical);
734
735 DBG_MSG("options: vram = %d, accel = %d, hwcursor = %d, fixed = %d, "
736 "noinit = %d\n", vram, accel, hwcursor, fixed, noinit);
737 DBG_MSG("options: mode = \"%s\"\n", mode ? mode : "");
738
739 if (probeonly)
740 bailout(dinfo);
741
742 /*
743 * Check if the LVDS port or any DVO ports are enabled. If so,
744 * don't allow mode switching
745 */
746 dvo = intelfbhw_check_non_crt(dinfo);
747 if (dvo) {
748 dinfo->fixed_mode = 1;
749 WRN_MSG("Non-CRT device is enabled ( ");
750 i = 0;
751 while (dvo) {
752 if (dvo & 1) {
753 s = intelfbhw_dvo_to_string(1 << i);
754 if (s)
755 printk("%s ", s);
756 }
757 dvo >>= 1;
758 ++i;
759 }
760 printk("). Disabling mode switching.\n");
761 }
762
763 if (bailearly == 1)
764 bailout(dinfo);
765
766 if (FIXED_MODE(dinfo) && ORIG_VIDEO_ISVGA != VIDEO_TYPE_VLFB) {
767 ERR_MSG("Video mode must be programmed at boot time.\n");
768 cleanup(dinfo);
769 return -ENODEV;
770 }
771
772 if (bailearly == 2)
773 bailout(dinfo);
774
775 /* Initialise dinfo and related data. */
776 /* If an initial mode was programmed at boot time, get its details. */
777 if (ORIG_VIDEO_ISVGA == VIDEO_TYPE_VLFB)
778 get_initial_mode(dinfo);
779
780 if (bailearly == 3)
781 bailout(dinfo);
782
783 if (FIXED_MODE(dinfo)) {
784 /* remap fb address */
785 update_dinfo(dinfo, &dinfo->initial_var);
786 }
787
788 if (bailearly == 4)
789 bailout(dinfo);
790
791
792 if (intelfb_set_fbinfo(dinfo)) {
793 cleanup(dinfo);
794 return -ENODEV;
795 }
796
797 if (bailearly == 5)
798 bailout(dinfo);
799
800 for (i = 0; i < 16; i++) {
801 j = color_table[i];
802 dinfo->palette[i].red = default_red[j];
803 dinfo->palette[i].green = default_grn[j];
804 dinfo->palette[i].blue = default_blu[j];
805 }
806
807 if (bailearly == 6)
808 bailout(dinfo);
809
810 pci_set_drvdata(pdev, dinfo);
811
812 /* Save the initial register state. */
813 i = intelfbhw_read_hw_state(dinfo, &dinfo->save_state,
814 bailearly > 6 ? bailearly - 6 : 0);
815 if (i != 0) {
816 DBG_MSG("intelfbhw_read_hw_state returned %d\n", i);
817 bailout(dinfo);
818 }
819
820 intelfbhw_print_hw_state(dinfo, &dinfo->save_state);
821
822 if (bailearly == 18)
823 bailout(dinfo);
824
825 /* Cursor initialisation */
826 if (dinfo->hwcursor) {
827 intelfbhw_cursor_init(dinfo);
828 intelfbhw_cursor_reset(dinfo);
829 }
830
831 if (bailearly == 19)
832 bailout(dinfo);
833
834 /* 2d acceleration init */
835 if (dinfo->accel)
836 intelfbhw_2d_start(dinfo);
837
838 if (bailearly == 20)
839 bailout(dinfo);
840
841 if (noregister)
842 bailout(dinfo);
843
844 if (register_framebuffer(dinfo->info) < 0) {
845 ERR_MSG("Cannot register framebuffer.\n");
846 cleanup(dinfo);
847 return -ENODEV;
848 }
849
850 dinfo->registered = 1;
851
852 return 0;
853
854err_out_pixmap:
855 fb_dealloc_cmap(&info->cmap);
856err_out_cmap:
857 framebuffer_release(info);
858 return -ENODEV;
859}
860
861static void __devexit
862intelfb_pci_unregister(struct pci_dev *pdev)
863{
864 struct intelfb_info *dinfo = pci_get_drvdata(pdev);
865
866 DBG_MSG("intelfb_pci_unregister\n");
867
868 if (!dinfo)
869 return;
870
871 cleanup(dinfo);
872
873 pci_set_drvdata(pdev, NULL);
874}
875
876/***************************************************************
877 * helper functions *
878 ***************************************************************/
879
880int __inline__
881intelfb_var_to_depth(const struct fb_var_screeninfo *var)
882{
883 DBG_MSG("intelfb_var_to_depth: bpp: %d, green.length is %d\n",
884 var->bits_per_pixel, var->green.length);
885
886 switch (var->bits_per_pixel) {
887 case 16:
888 return (var->green.length == 6) ? 16 : 15;
889 case 32:
890 return 24;
891 default:
892 return var->bits_per_pixel;
893 }
894}
895
896
897static __inline__ int
898var_to_refresh(const struct fb_var_screeninfo *var)
899{
900 int xtot = var->xres + var->left_margin + var->right_margin +
901 var->hsync_len;
902 int ytot = var->yres + var->upper_margin + var->lower_margin +
903 var->vsync_len;
904
905 return (1000000000 / var->pixclock * 1000 + 500) / xtot / ytot;
906}
907
908/***************************************************************
909 * Various intialisation functions *
910 ***************************************************************/
911
912static void __devinit
913get_initial_mode(struct intelfb_info *dinfo)
914{
915 struct fb_var_screeninfo *var;
916 int xtot, ytot;
917
918 DBG_MSG("get_initial_mode\n");
919
920 dinfo->initial_vga = 1;
921 dinfo->initial_fb_base = screen_info.lfb_base;
922 dinfo->initial_video_ram = screen_info.lfb_size * KB(64);
923 dinfo->initial_pitch = screen_info.lfb_linelength;
924
925 var = &dinfo->initial_var;
926 memset(var, 0, sizeof(*var));
927 var->xres = screen_info.lfb_width;
928 var->yres = screen_info.lfb_height;
929 var->bits_per_pixel = screen_info.lfb_depth;
930 switch (screen_info.lfb_depth) {
931 case 15:
932 var->bits_per_pixel = 16;
933 break;
934 case 24:
935 var->bits_per_pixel = 32;
936 break;
937 }
938
939 DBG_MSG("Initial info: FB is 0x%x/0x%x (%d kByte)\n",
940 dinfo->initial_fb_base, dinfo->initial_video_ram,
941 BtoKB(dinfo->initial_video_ram));
942
943 DBG_MSG("Initial info: mode is %dx%d-%d (%d)\n",
944 var->xres, var->yres, var->bits_per_pixel,
945 dinfo->initial_pitch);
946
947 /* Dummy timing values (assume 60Hz) */
948 var->left_margin = (var->xres / 8) & 0xf8;
949 var->right_margin = 32;
950 var->upper_margin = 16;
951 var->lower_margin = 4;
952 var->hsync_len = (var->xres / 8) & 0xf8;
953 var->vsync_len = 4;
954
955 xtot = var->xres + var->left_margin +
956 var->right_margin + var->hsync_len;
957 ytot = var->yres + var->upper_margin +
958 var->lower_margin + var->vsync_len;
959 var->pixclock = 10000000 / xtot * 1000 / ytot * 100 / 60;
960
961 var->height = -1;
962 var->width = -1;
963
964 if (var->bits_per_pixel > 8) {
965 var->red.offset = screen_info.red_pos;
966 var->red.length = screen_info.red_size;
967 var->green.offset = screen_info.green_pos;
968 var->green.length = screen_info.green_size;
969 var->blue.offset = screen_info.blue_pos;
970 var->blue.length = screen_info.blue_size;
971 var->transp.offset = screen_info.rsvd_pos;
972 var->transp.length = screen_info.rsvd_size;
973 } else {
974 var->red.length = 8;
975 var->green.length = 8;
976 var->blue.length = 8;
977 }
978}
979
980static int __devinit
981intelfb_init_var(struct intelfb_info *dinfo)
982{
983 struct fb_var_screeninfo *var;
984 int msrc = 0;
985
986 DBG_MSG("intelfb_init_var\n");
987
988 var = &dinfo->info->var;
989 if (FIXED_MODE(dinfo)) {
990 memcpy(var, &dinfo->initial_var,
991 sizeof(struct fb_var_screeninfo));
992 msrc = 5;
993 } else {
994 if (mode) {
995 msrc = fb_find_mode(var, dinfo->info, mode,
996 vesa_modes, VESA_MODEDB_SIZE,
997 NULL, 0);
998 if (msrc)
999 msrc |= 8;
1000 }
1001 if (!msrc) {
1002 msrc = fb_find_mode(var, dinfo->info, PREFERRED_MODE,
1003 vesa_modes, VESA_MODEDB_SIZE,
1004 NULL, 0);
1005 }
1006 }
1007
1008 if (!msrc) {
1009 ERR_MSG("Cannot find a suitable video mode.\n");
1010 return 1;
1011 }
1012
1013 INF_MSG("Initial video mode is %dx%d-%d@%d.\n", var->xres, var->yres,
1014 var->bits_per_pixel, var_to_refresh(var));
1015
1016 DBG_MSG("Initial video mode is from %d.\n", msrc);
1017
1018#if ALLOCATE_FOR_PANNING
1019 /* Allow use of half of the video ram for panning */
1020 var->xres_virtual = var->xres;
1021 var->yres_virtual =
1022 dinfo->fb.size / 2 / (var->bits_per_pixel * var->xres);
1023 if (var->yres_virtual < var->yres)
1024 var->yres_virtual = var->yres;
1025#else
1026 var->yres_virtual = var->yres;
1027#endif
1028
1029 if (dinfo->accel)
1030 var->accel_flags |= FB_ACCELF_TEXT;
1031 else
1032 var->accel_flags &= ~FB_ACCELF_TEXT;
1033
1034 return 0;
1035}
1036
1037static int __devinit
1038intelfb_set_fbinfo(struct intelfb_info *dinfo)
1039{
1040 struct fb_info *info = dinfo->info;
1041
1042 DBG_MSG("intelfb_set_fbinfo\n");
1043
1044 info->flags = FBINFO_FLAG_DEFAULT;
1045 info->fbops = &intel_fb_ops;
1046 info->pseudo_palette = dinfo->pseudo_palette;
1047
1048 info->pixmap.size = 64*1024;
1049 info->pixmap.buf_align = 8;
1050 info->pixmap.flags = FB_PIXMAP_SYSTEM;
1051
1052 if (intelfb_init_var(dinfo))
1053 return 1;
1054
1055 info->pixmap.scan_align = 1;
1056
1057 update_dinfo(dinfo, &info->var);
1058
1059 return 0;
1060}
1061
1062/* Update dinfo to match the active video mode. */
1063static void
1064update_dinfo(struct intelfb_info *dinfo, struct fb_var_screeninfo *var)
1065{
1066 DBG_MSG("update_dinfo\n");
1067
1068 dinfo->bpp = var->bits_per_pixel;
1069 dinfo->depth = intelfb_var_to_depth(var);
1070 dinfo->xres = var->xres;
1071 dinfo->yres = var->xres;
1072 dinfo->pixclock = var->pixclock;
1073
1074 intelfb_get_fix(&dinfo->info->fix, dinfo->info);
1075
1076 switch (dinfo->bpp) {
1077 case 8:
1078 dinfo->visual = FB_VISUAL_PSEUDOCOLOR;
1079 dinfo->pitch = var->xres_virtual;
1080 break;
1081 case 16:
1082 dinfo->visual = FB_VISUAL_TRUECOLOR;
1083 dinfo->pitch = var->xres_virtual * 2;
1084 break;
1085 case 32:
1086 dinfo->visual = FB_VISUAL_TRUECOLOR;
1087 dinfo->pitch = var->xres_virtual * 4;
1088 break;
1089 }
1090
1091 /* Make sure the line length is a aligned correctly. */
1092 dinfo->pitch = ROUND_UP_TO(dinfo->pitch, STRIDE_ALIGNMENT);
1093
1094 if (FIXED_MODE(dinfo))
1095 dinfo->pitch = dinfo->initial_pitch;
1096
1097 dinfo->info->screen_base = (char __iomem *)dinfo->fb.virtual;
1098 dinfo->info->fix.line_length = dinfo->pitch;
1099 dinfo->info->fix.visual = dinfo->visual;
1100}
1101
1102/* fbops functions */
1103
1104static int
1105intelfb_get_fix(struct fb_fix_screeninfo *fix, struct fb_info *info)
1106{
1107 struct intelfb_info *dinfo = GET_DINFO(info);
1108
1109 DBG_MSG("intelfb_get_fix\n");
1110
1111 memset(fix, 0, sizeof(*fix));
1112 strcpy(fix->id, dinfo->name);
1113 fix->smem_start = dinfo->fb.physical;
1114 fix->smem_len = dinfo->fb.size;
1115 fix->type = FB_TYPE_PACKED_PIXELS;
1116 fix->type_aux = 0;
1117 fix->visual = dinfo->visual;
1118 fix->xpanstep = 8;
1119 fix->ypanstep = 1;
1120 fix->ywrapstep = 0;
1121 fix->line_length = dinfo->pitch;
1122 fix->mmio_start = dinfo->mmio_base_phys;
1123 fix->mmio_len = INTEL_REG_SIZE;
1124 fix->accel = FB_ACCEL_I830;
1125 return 0;
1126}
1127
1128/***************************************************************
1129 * fbdev interface *
1130 ***************************************************************/
1131
1132static int
1133intelfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
1134{
1135 int change_var = 0;
1136 struct fb_var_screeninfo v;
1137 struct intelfb_info *dinfo;
1138 static int first = 1;
1139
1140 DBG_MSG("intelfb_check_var: accel_flags is %d\n", var->accel_flags);
1141
1142 dinfo = GET_DINFO(info);
1143
1144 if (intelfbhw_validate_mode(dinfo, var) != 0)
1145 return -EINVAL;
1146
1147 v = *var;
1148
1149 /* Check for a supported bpp. */
1150 if (v.bits_per_pixel <= 8) {
1151 v.bits_per_pixel = 8;
1152 } else if (v.bits_per_pixel <= 16) {
1153 if (v.bits_per_pixel == 16)
1154 v.green.length = 6;
1155 v.bits_per_pixel = 16;
1156 } else if (v.bits_per_pixel <= 32) {
1157 v.bits_per_pixel = 32;
1158 } else
1159 return -EINVAL;
1160
1161 change_var = ((info->var.xres != var->xres) ||
1162 (info->var.yres != var->yres) ||
1163 (info->var.xres_virtual != var->xres_virtual) ||
1164 (info->var.yres_virtual != var->yres_virtual) ||
1165 (info->var.bits_per_pixel != var->bits_per_pixel) ||
1166 memcmp(&info->var.red, &var->red, sizeof(var->red)) ||
1167 memcmp(&info->var.green, &var->green,
1168 sizeof(var->green)) ||
1169 memcmp(&info->var.blue, &var->blue, sizeof(var->blue)));
1170
1171 if (FIXED_MODE(dinfo) &&
1172 (change_var ||
1173 var->yres_virtual > dinfo->initial_var.yres_virtual ||
1174 var->yres_virtual < dinfo->initial_var.yres ||
1175 var->xoffset || var->nonstd)) {
1176 if (first) {
1177 ERR_MSG("Changing the video mode is not supported.\n");
1178 first = 0;
1179 }
1180 return -EINVAL;
1181 }
1182
1183 switch (intelfb_var_to_depth(&v)) {
1184 case 8:
1185 v.red.offset = v.green.offset = v.blue.offset = 0;
1186 v.red.length = v.green.length = v.blue.length = 8;
1187 v.transp.offset = v.transp.length = 0;
1188 break;
1189 case 15:
1190 v.red.offset = 10;
1191 v.green.offset = 5;
1192 v.blue.offset = 0;
1193 v.red.length = v.green.length = v.blue.length = 5;
1194 v.transp.offset = v.transp.length = 0;
1195 break;
1196 case 16:
1197 v.red.offset = 11;
1198 v.green.offset = 5;
1199 v.blue.offset = 0;
1200 v.red.length = 5;
1201 v.green.length = 6;
1202 v.blue.length = 5;
1203 v.transp.offset = v.transp.length = 0;
1204 break;
1205 case 24:
1206 v.red.offset = 16;
1207 v.green.offset = 8;
1208 v.blue.offset = 0;
1209 v.red.length = v.green.length = v.blue.length = 8;
1210 v.transp.offset = v.transp.length = 0;
1211 break;
1212 case 32:
1213 v.red.offset = 16;
1214 v.green.offset = 8;
1215 v.blue.offset = 0;
1216 v.red.length = v.green.length = v.blue.length = 8;
1217 v.transp.offset = 24;
1218 v.transp.length = 8;
1219 break;
1220 }
1221
1222 if (v.xoffset < 0)
1223 v.xoffset = 0;
1224 if (v.yoffset < 0)
1225 v.yoffset = 0;
1226
1227 if (v.xoffset > v.xres_virtual - v.xres)
1228 v.xoffset = v.xres_virtual - v.xres;
1229 if (v.yoffset > v.yres_virtual - v.yres)
1230 v.yoffset = v.yres_virtual - v.yres;
1231
1232 v.red.msb_right = v.green.msb_right = v.blue.msb_right =
1233 v.transp.msb_right = 0;
1234
1235 *var = v;
1236
1237 return 0;
1238}
1239
1240static int
1241intelfb_set_par(struct fb_info *info)
1242{
1243 struct intelfb_hwstate *hw;
1244 struct intelfb_info *dinfo = GET_DINFO(info);
1245
1246 if (FIXED_MODE(dinfo)) {
1247 ERR_MSG("Changing the video mode is not supported.\n");
1248 return -EINVAL;
1249 }
1250
1251 hw = kmalloc(sizeof(*hw), GFP_ATOMIC);
1252 if (!hw)
1253 return -ENOMEM;
1254
1255 DBG_MSG("intelfb_set_par (%dx%d-%d)\n", info->var.xres,
1256 info->var.yres, info->var.bits_per_pixel);
1257
1258 intelfb_blank(FB_BLANK_POWERDOWN, info);
1259
1260 if (dinfo->accel)
1261 intelfbhw_2d_stop(dinfo);
1262
1263 memcpy(hw, &dinfo->save_state, sizeof(*hw));
1264 if (intelfbhw_mode_to_hw(dinfo, hw, &info->var))
1265 goto invalid_mode;
1266 if (intelfbhw_program_mode(dinfo, hw, 0))
1267 goto invalid_mode;
1268
1269#if REGDUMP > 0
1270 intelfbhw_read_hw_state(dinfo, hw, 0);
1271 intelfbhw_print_hw_state(dinfo, hw);
1272#endif
1273
1274 update_dinfo(dinfo, &info->var);
1275
1276 if (dinfo->accel)
1277 intelfbhw_2d_start(dinfo);
1278
1279 intelfb_pan_display(&info->var, info);
1280
1281 intelfb_blank(FB_BLANK_UNBLANK, info);
1282
1283 if (ACCEL(dinfo, info)) {
1284 info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN |
1285 FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT |
1286 FBINFO_HWACCEL_IMAGEBLIT;
1287 } else {
1288 info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN;
1289 }
1290 kfree(hw);
1291 return 0;
1292invalid_mode:
1293 kfree(hw);
1294 return -EINVAL;
1295}
1296
1297static int
1298intelfb_setcolreg(unsigned regno, unsigned red, unsigned green,
1299 unsigned blue, unsigned transp, struct fb_info *info)
1300{
1301 struct intelfb_info *dinfo = GET_DINFO(info);
1302
1303#if VERBOSE > 0
1304 DBG_MSG("intelfb_setcolreg: regno %d, depth %d\n", regno, dinfo->depth);
1305#endif
1306
1307 if (regno > 255)
1308 return 1;
1309
1310 switch (dinfo->depth) {
1311 case 8:
1312 {
1313 red >>= 8;
1314 green >>= 8;
1315 blue >>= 8;
1316
1317 dinfo->palette[regno].red = red;
1318 dinfo->palette[regno].green = green;
1319 dinfo->palette[regno].blue = blue;
1320
1321 intelfbhw_setcolreg(dinfo, regno, red, green, blue,
1322 transp);
1323 }
1324 break;
1325 case 15:
1326 dinfo->pseudo_palette[regno] = ((red & 0xf800) >> 1) |
1327 ((green & 0xf800) >> 6) |
1328 ((blue & 0xf800) >> 11);
1329 break;
1330 case 16:
1331 dinfo->pseudo_palette[regno] = (red & 0xf800) |
1332 ((green & 0xfc00) >> 5) |
1333 ((blue & 0xf800) >> 11);
1334 break;
1335 case 24:
1336 dinfo->pseudo_palette[regno] = ((red & 0xff00) << 8) |
1337 (green & 0xff00) |
1338 ((blue & 0xff00) >> 8);
1339 break;
1340 }
1341 return 0;
1342}
1343
1344static int
1345intelfb_blank(int blank, struct fb_info *info)
1346{
1347 intelfbhw_do_blank(blank, info);
1348 return 0;
1349}
1350
1351static int
1352intelfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
1353{
1354 intelfbhw_pan_display(var, info);
1355 return 0;
1356}
1357
1358/* When/if we have our own ioctls. */
1359static int
1360intelfb_ioctl(struct inode *inode, struct file *file, unsigned int cmd,
1361 unsigned long arg, struct fb_info *info)
1362{
1363 int retval = 0;
1364
1365 return retval;
1366}
1367
1368static void
1369intelfb_fillrect (struct fb_info *info, const struct fb_fillrect *rect)
1370{
1371 struct intelfb_info *dinfo = GET_DINFO(info);
1372 u32 rop, color;
1373
1374#if VERBOSE > 0
1375 DBG_MSG("intelfb_fillrect\n");
1376#endif
1377
1378 if (!ACCEL(dinfo, info) || dinfo->depth == 4)
1379 return cfb_fillrect(info, rect);
1380
1381 if (rect->rop == ROP_COPY)
1382 rop = PAT_ROP_GXCOPY;
1383 else // ROP_XOR
1384 rop = PAT_ROP_GXXOR;
1385
1386 if (dinfo->depth != 8)
1387 color = dinfo->pseudo_palette[rect->color];
1388 else
1389 color = rect->color;
1390
1391 intelfbhw_do_fillrect(dinfo, rect->dx, rect->dy,
1392 rect->width, rect->height, color,
1393 dinfo->pitch, info->var.bits_per_pixel,
1394 rop);
1395}
1396
1397static void
1398intelfb_copyarea(struct fb_info *info, const struct fb_copyarea *region)
1399{
1400 struct intelfb_info *dinfo = GET_DINFO(info);
1401
1402#if VERBOSE > 0
1403 DBG_MSG("intelfb_copyarea\n");
1404#endif
1405
1406 if (!ACCEL(dinfo, info) || dinfo->depth == 4)
1407 return cfb_copyarea(info, region);
1408
1409 intelfbhw_do_bitblt(dinfo, region->sx, region->sy, region->dx,
1410 region->dy, region->width, region->height,
1411 dinfo->pitch, info->var.bits_per_pixel);
1412}
1413
1414static void
1415intelfb_imageblit(struct fb_info *info, const struct fb_image *image)
1416{
1417 struct intelfb_info *dinfo = GET_DINFO(info);
1418 u32 fgcolor, bgcolor;
1419
1420#if VERBOSE > 0
1421 DBG_MSG("intelfb_imageblit\n");
1422#endif
1423
1424 if (!ACCEL(dinfo, info) || dinfo->depth == 4
1425 || image->depth != 1)
1426 return cfb_imageblit(info, image);
1427
1428 if (dinfo->depth != 8) {
1429 fgcolor = dinfo->pseudo_palette[image->fg_color];
1430 bgcolor = dinfo->pseudo_palette[image->bg_color];
1431 } else {
1432 fgcolor = image->fg_color;
1433 bgcolor = image->bg_color;
1434 }
1435
1436 if (!intelfbhw_do_drawglyph(dinfo, fgcolor, bgcolor, image->width,
1437 image->height, image->data,
1438 image->dx, image->dy,
1439 dinfo->pitch, info->var.bits_per_pixel))
1440 return cfb_imageblit(info, image);
1441}
1442
1443static int
1444intelfb_cursor(struct fb_info *info, struct fb_cursor *cursor)
1445{
1446 struct intelfb_info *dinfo = GET_DINFO(info);
1447
1448#if VERBOSE > 0
1449 DBG_MSG("intelfb_cursor\n");
1450#endif
1451
1452 if (!dinfo->hwcursor)
1453 return soft_cursor(info, cursor);
1454
1455 intelfbhw_cursor_hide(dinfo);
1456
1457 /* If XFree killed the cursor - restore it */
1458 if (INREG(CURSOR_A_BASEADDR) != dinfo->cursor.offset << 12) {
1459 u32 fg, bg;
1460
1461 DBG_MSG("the cursor was killed - restore it !!\n");
1462 DBG_MSG("size %d, %d pos %d, %d\n",
1463 cursor->image.width, cursor->image.height,
1464 cursor->image.dx, cursor->image.dy);
1465
1466 intelfbhw_cursor_init(dinfo);
1467 intelfbhw_cursor_reset(dinfo);
1468 intelfbhw_cursor_setpos(dinfo, cursor->image.dx,
1469 cursor->image.dy);
1470
1471 if (dinfo->depth != 8) {
1472 fg =dinfo->pseudo_palette[cursor->image.fg_color];
1473 bg =dinfo->pseudo_palette[cursor->image.bg_color];
1474 } else {
1475 fg = cursor->image.fg_color;
1476 bg = cursor->image.bg_color;
1477 }
1478 intelfbhw_cursor_setcolor(dinfo, bg, fg);
1479 intelfbhw_cursor_load(dinfo, cursor->image.width,
1480 cursor->image.height,
1481 dinfo->cursor_src);
1482
1483 if (cursor->enable)
1484 intelfbhw_cursor_show(dinfo);
1485 return 0;
1486 }
1487
1488 if (cursor->set & FB_CUR_SETPOS) {
1489 u32 dx, dy;
1490
1491 dx = cursor->image.dx - info->var.xoffset;
1492 dy = cursor->image.dy - info->var.yoffset;
1493
1494 intelfbhw_cursor_setpos(dinfo, dx, dy);
1495 }
1496
1497 if (cursor->set & FB_CUR_SETSIZE) {
1498 if (cursor->image.width > 64 || cursor->image.height > 64)
1499 return -ENXIO;
1500
1501 intelfbhw_cursor_reset(dinfo);
1502 }
1503
1504 if (cursor->set & FB_CUR_SETCMAP) {
1505 u32 fg, bg;
1506
1507 if (dinfo->depth != 8) {
1508 fg = dinfo->pseudo_palette[cursor->image.fg_color];
1509 bg = dinfo->pseudo_palette[cursor->image.bg_color];
1510 } else {
1511 fg = cursor->image.fg_color;
1512 bg = cursor->image.bg_color;
1513 }
1514
1515 intelfbhw_cursor_setcolor(dinfo, bg, fg);
1516 }
1517
1518 if (cursor->set & (FB_CUR_SETSHAPE | FB_CUR_SETIMAGE)) {
1519 u32 s_pitch = (ROUND_UP_TO(cursor->image.width, 8) / 8);
1520 u32 size = s_pitch * cursor->image.height;
1521 u8 *dat = (u8 *) cursor->image.data;
1522 u8 *msk = (u8 *) cursor->mask;
1523 u8 src[64];
1524 u32 i;
1525
1526 if (cursor->image.depth != 1)
1527 return -ENXIO;
1528
1529 switch (cursor->rop) {
1530 case ROP_XOR:
1531 for (i = 0; i < size; i++)
1532 src[i] = dat[i] ^ msk[i];
1533 break;
1534 case ROP_COPY:
1535 default:
1536 for (i = 0; i < size; i++)
1537 src[i] = dat[i] & msk[i];
1538 break;
1539 }
1540
1541 /* save the bitmap to restore it when XFree will
1542 make the cursor dirty */
1543 memcpy(dinfo->cursor_src, src, size);
1544
1545 intelfbhw_cursor_load(dinfo, cursor->image.width,
1546 cursor->image.height, src);
1547 }
1548
1549 if (cursor->enable)
1550 intelfbhw_cursor_show(dinfo);
1551
1552 return 0;
1553}
1554
1555static int
1556intelfb_sync(struct fb_info *info)
1557{
1558 struct intelfb_info *dinfo = GET_DINFO(info);
1559
1560#if VERBOSE > 0
1561 DBG_MSG("intelfb_sync\n");
1562#endif
1563
1564 if (dinfo->ring_lockup)
1565 return 0;
1566
1567 intelfbhw_do_sync(dinfo);
1568 return 0;
1569}
1570
diff --git a/drivers/video/intelfb/intelfbdrv.h b/drivers/video/intelfb/intelfbdrv.h
new file mode 100644
index 00000000000..cc305812888
--- /dev/null
+++ b/drivers/video/intelfb/intelfbdrv.h
@@ -0,0 +1,68 @@
1#ifndef _INTELFBDRV_H
2#define _INTELFBDRV_H
3
4/*
5 ******************************************************************************
6 * intelfb
7 *
8 * Linux framebuffer driver for Intel(R) 830M/845G/852GM/855GM/865G/915G
9 * integrated graphics chips.
10 *
11 * Copyright © 2004 Sylvain Meyer
12 *
13 * Author: Sylvain Meyer
14 *
15 ******************************************************************************
16 * This program is free software; you can redistribute it and/or modify
17 * it under the terms of the GNU General Public License as published by
18 * the Free Software Foundation; either version 2 of the License, or
19 * (at your option) any later version.
20 *
21 * This program is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
24 * GNU General Public License for more details.
25 *
26 * You should have received a copy of the GNU General Public License
27 * along with this program; if not, write to the Free Software
28 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29*/
30
31static void __devinit get_initial_mode(struct intelfb_info *dinfo);
32static void update_dinfo(struct intelfb_info *dinfo,
33 struct fb_var_screeninfo *var);
34static int intelfb_get_fix(struct fb_fix_screeninfo *fix,
35 struct fb_info *info);
36
37static int intelfb_check_var(struct fb_var_screeninfo *var,
38 struct fb_info *info);
39static int intelfb_set_par(struct fb_info *info);
40static int intelfb_setcolreg(unsigned regno, unsigned red, unsigned green,
41 unsigned blue, unsigned transp,
42 struct fb_info *info);
43
44static int intelfb_blank(int blank, struct fb_info *info);
45static int intelfb_pan_display(struct fb_var_screeninfo *var,
46 struct fb_info *info);
47
48static void intelfb_fillrect(struct fb_info *info,
49 const struct fb_fillrect *rect);
50static void intelfb_copyarea(struct fb_info *info,
51 const struct fb_copyarea *region);
52static void intelfb_imageblit(struct fb_info *info,
53 const struct fb_image *image);
54static int intelfb_cursor(struct fb_info *info,
55 struct fb_cursor *cursor);
56
57static int intelfb_sync(struct fb_info *info);
58
59static int intelfb_ioctl(struct inode *inode, struct file *file,
60 unsigned int cmd, unsigned long arg,
61 struct fb_info *info);
62
63static int __devinit intelfb_pci_register(struct pci_dev *pdev,
64 const struct pci_device_id *ent);
65static void __devexit intelfb_pci_unregister(struct pci_dev *pdev);
66static int __devinit intelfb_set_fbinfo(struct intelfb_info *dinfo);
67
68#endif
diff --git a/drivers/video/intelfb/intelfbhw.c b/drivers/video/intelfb/intelfbhw.c
new file mode 100644
index 00000000000..f5bed581dc4
--- /dev/null
+++ b/drivers/video/intelfb/intelfbhw.c
@@ -0,0 +1,1780 @@
1/*
2 * intelfb
3 *
4 * Linux framebuffer driver for Intel(R) 865G integrated graphics chips.
5 *
6 * Copyright © 2002, 2003 David Dawes <dawes@xfree86.org>
7 * 2004 Sylvain Meyer
8 *
9 * This driver consists of two parts. The first part (intelfbdrv.c) provides
10 * the basic fbdev interfaces, is derived in part from the radeonfb and
11 * vesafb drivers, and is covered by the GPL. The second part (intelfbhw.c)
12 * provides the code to program the hardware. Most of it is derived from
13 * the i810/i830 XFree86 driver. The HW-specific code is covered here
14 * under a dual license (GPL and MIT/XFree86 license).
15 *
16 * Author: David Dawes
17 *
18 */
19
20/* $DHD: intelfb/intelfbhw.c,v 1.9 2003/06/27 15:06:25 dawes Exp $ */
21
22#include <linux/config.h>
23#include <linux/module.h>
24#include <linux/kernel.h>
25#include <linux/errno.h>
26#include <linux/string.h>
27#include <linux/mm.h>
28#include <linux/tty.h>
29#include <linux/slab.h>
30#include <linux/delay.h>
31#include <linux/fb.h>
32#include <linux/console.h>
33#include <linux/selection.h>
34#include <linux/ioport.h>
35#include <linux/init.h>
36#include <linux/pci.h>
37#include <linux/vmalloc.h>
38#include <linux/kd.h>
39#include <linux/vt_kern.h>
40#include <linux/pagemap.h>
41#include <linux/version.h>
42
43#include <asm/io.h>
44
45#include "intelfb.h"
46#include "intelfbhw.h"
47
48int
49intelfbhw_get_chipset(struct pci_dev *pdev, const char **name, int *chipset,
50 int *mobile)
51{
52 u32 tmp;
53
54 if (!pdev || !name || !chipset || !mobile)
55 return 1;
56
57 switch (pdev->device) {
58 case PCI_DEVICE_ID_INTEL_830M:
59 *name = "Intel(R) 830M";
60 *chipset = INTEL_830M;
61 *mobile = 1;
62 return 0;
63 case PCI_DEVICE_ID_INTEL_845G:
64 *name = "Intel(R) 845G";
65 *chipset = INTEL_845G;
66 *mobile = 0;
67 return 0;
68 case PCI_DEVICE_ID_INTEL_85XGM:
69 tmp = 0;
70 *mobile = 1;
71 pci_read_config_dword(pdev, INTEL_85X_CAPID, &tmp);
72 switch ((tmp >> INTEL_85X_VARIANT_SHIFT) &
73 INTEL_85X_VARIANT_MASK) {
74 case INTEL_VAR_855GME:
75 *name = "Intel(R) 855GME";
76 *chipset = INTEL_855GME;
77 return 0;
78 case INTEL_VAR_855GM:
79 *name = "Intel(R) 855GM";
80 *chipset = INTEL_855GM;
81 return 0;
82 case INTEL_VAR_852GME:
83 *name = "Intel(R) 852GME";
84 *chipset = INTEL_852GME;
85 return 0;
86 case INTEL_VAR_852GM:
87 *name = "Intel(R) 852GM";
88 *chipset = INTEL_852GM;
89 return 0;
90 default:
91 *name = "Intel(R) 852GM/855GM";
92 *chipset = INTEL_85XGM;
93 return 0;
94 }
95 break;
96 case PCI_DEVICE_ID_INTEL_865G:
97 *name = "Intel(R) 865G";
98 *chipset = INTEL_865G;
99 *mobile = 0;
100 return 0;
101 case PCI_DEVICE_ID_INTEL_915G:
102 *name = "Intel(R) 915G";
103 *chipset = INTEL_915G;
104 *mobile = 0;
105 return 0;
106 default:
107 return 1;
108 }
109}
110
111int
112intelfbhw_get_memory(struct pci_dev *pdev, int *aperture_size,
113 int *stolen_size)
114{
115 struct pci_dev *bridge_dev;
116 u16 tmp;
117
118 if (!pdev || !aperture_size || !stolen_size)
119 return 1;
120
121 /* Find the bridge device. It is always 0:0.0 */
122 if (!(bridge_dev = pci_find_slot(0, PCI_DEVFN(0, 0)))) {
123 ERR_MSG("cannot find bridge device\n");
124 return 1;
125 }
126
127 /* Get the fb aperture size and "stolen" memory amount. */
128 tmp = 0;
129 pci_read_config_word(bridge_dev, INTEL_GMCH_CTRL, &tmp);
130 switch (pdev->device) {
131 case PCI_DEVICE_ID_INTEL_830M:
132 case PCI_DEVICE_ID_INTEL_845G:
133 if ((tmp & INTEL_GMCH_MEM_MASK) == INTEL_GMCH_MEM_64M)
134 *aperture_size = MB(64);
135 else
136 *aperture_size = MB(128);
137 switch (tmp & INTEL_830_GMCH_GMS_MASK) {
138 case INTEL_830_GMCH_GMS_STOLEN_512:
139 *stolen_size = KB(512) - KB(132);
140 return 0;
141 case INTEL_830_GMCH_GMS_STOLEN_1024:
142 *stolen_size = MB(1) - KB(132);
143 return 0;
144 case INTEL_830_GMCH_GMS_STOLEN_8192:
145 *stolen_size = MB(8) - KB(132);
146 return 0;
147 case INTEL_830_GMCH_GMS_LOCAL:
148 ERR_MSG("only local memory found\n");
149 return 1;
150 case INTEL_830_GMCH_GMS_DISABLED:
151 ERR_MSG("video memory is disabled\n");
152 return 1;
153 default:
154 ERR_MSG("unexpected GMCH_GMS value: 0x%02x\n",
155 tmp & INTEL_830_GMCH_GMS_MASK);
156 return 1;
157 }
158 break;
159 default:
160 *aperture_size = MB(128);
161 switch (tmp & INTEL_855_GMCH_GMS_MASK) {
162 case INTEL_855_GMCH_GMS_STOLEN_1M:
163 *stolen_size = MB(1) - KB(132);
164 return 0;
165 case INTEL_855_GMCH_GMS_STOLEN_4M:
166 *stolen_size = MB(4) - KB(132);
167 return 0;
168 case INTEL_855_GMCH_GMS_STOLEN_8M:
169 *stolen_size = MB(8) - KB(132);
170 return 0;
171 case INTEL_855_GMCH_GMS_STOLEN_16M:
172 *stolen_size = MB(16) - KB(132);
173 return 0;
174 case INTEL_855_GMCH_GMS_STOLEN_32M:
175 *stolen_size = MB(32) - KB(132);
176 return 0;
177 case INTEL_915G_GMCH_GMS_STOLEN_48M:
178 *stolen_size = MB(48) - KB(132);
179 return 0;
180 case INTEL_915G_GMCH_GMS_STOLEN_64M:
181 *stolen_size = MB(64) - KB(132);
182 return 0;
183 case INTEL_855_GMCH_GMS_DISABLED:
184 ERR_MSG("video memory is disabled\n");
185 return 0;
186 default:
187 ERR_MSG("unexpected GMCH_GMS value: 0x%02x\n",
188 tmp & INTEL_855_GMCH_GMS_MASK);
189 return 1;
190 }
191 }
192}
193
194int
195intelfbhw_check_non_crt(struct intelfb_info *dinfo)
196{
197 int dvo = 0;
198
199 if (INREG(LVDS) & PORT_ENABLE)
200 dvo |= LVDS_PORT;
201 if (INREG(DVOA) & PORT_ENABLE)
202 dvo |= DVOA_PORT;
203 if (INREG(DVOB) & PORT_ENABLE)
204 dvo |= DVOB_PORT;
205 if (INREG(DVOC) & PORT_ENABLE)
206 dvo |= DVOC_PORT;
207
208 return dvo;
209}
210
211const char *
212intelfbhw_dvo_to_string(int dvo)
213{
214 if (dvo & DVOA_PORT)
215 return "DVO port A";
216 else if (dvo & DVOB_PORT)
217 return "DVO port B";
218 else if (dvo & DVOC_PORT)
219 return "DVO port C";
220 else if (dvo & LVDS_PORT)
221 return "LVDS port";
222 else
223 return NULL;
224}
225
226
227int
228intelfbhw_validate_mode(struct intelfb_info *dinfo,
229 struct fb_var_screeninfo *var)
230{
231 int bytes_per_pixel;
232 int tmp;
233
234#if VERBOSE > 0
235 DBG_MSG("intelfbhw_validate_mode\n");
236#endif
237
238 bytes_per_pixel = var->bits_per_pixel / 8;
239 if (bytes_per_pixel == 3)
240 bytes_per_pixel = 4;
241
242 /* Check if enough video memory. */
243 tmp = var->yres_virtual * var->xres_virtual * bytes_per_pixel;
244 if (tmp > dinfo->fb.size) {
245 WRN_MSG("Not enough video ram for mode "
246 "(%d KByte vs %d KByte).\n",
247 BtoKB(tmp), BtoKB(dinfo->fb.size));
248 return 1;
249 }
250
251 /* Check if x/y limits are OK. */
252 if (var->xres - 1 > HACTIVE_MASK) {
253 WRN_MSG("X resolution too large (%d vs %d).\n",
254 var->xres, HACTIVE_MASK + 1);
255 return 1;
256 }
257 if (var->yres - 1 > VACTIVE_MASK) {
258 WRN_MSG("Y resolution too large (%d vs %d).\n",
259 var->yres, VACTIVE_MASK + 1);
260 return 1;
261 }
262
263 /* Check for interlaced/doublescan modes. */
264 if (var->vmode & FB_VMODE_INTERLACED) {
265 WRN_MSG("Mode is interlaced.\n");
266 return 1;
267 }
268 if (var->vmode & FB_VMODE_DOUBLE) {
269 WRN_MSG("Mode is double-scan.\n");
270 return 1;
271 }
272
273 /* Check if clock is OK. */
274 tmp = 1000000000 / var->pixclock;
275 if (tmp < MIN_CLOCK) {
276 WRN_MSG("Pixel clock is too low (%d MHz vs %d MHz).\n",
277 (tmp + 500) / 1000, MIN_CLOCK / 1000);
278 return 1;
279 }
280 if (tmp > MAX_CLOCK) {
281 WRN_MSG("Pixel clock is too high (%d MHz vs %d MHz).\n",
282 (tmp + 500) / 1000, MAX_CLOCK / 1000);
283 return 1;
284 }
285
286 return 0;
287}
288
289int
290intelfbhw_pan_display(struct fb_var_screeninfo *var, struct fb_info *info)
291{
292 struct intelfb_info *dinfo = GET_DINFO(info);
293 u32 offset, xoffset, yoffset;
294
295#if VERBOSE > 0
296 DBG_MSG("intelfbhw_pan_display\n");
297#endif
298
299 xoffset = ROUND_DOWN_TO(var->xoffset, 8);
300 yoffset = var->yoffset;
301
302 if ((xoffset + var->xres > var->xres_virtual) ||
303 (yoffset + var->yres > var->yres_virtual))
304 return -EINVAL;
305
306 offset = (yoffset * dinfo->pitch) +
307 (xoffset * var->bits_per_pixel) / 8;
308
309 offset += dinfo->fb.offset << 12;
310
311 OUTREG(DSPABASE, offset);
312
313 return 0;
314}
315
316/* Blank the screen. */
317void
318intelfbhw_do_blank(int blank, struct fb_info *info)
319{
320 struct intelfb_info *dinfo = GET_DINFO(info);
321 u32 tmp;
322
323#if VERBOSE > 0
324 DBG_MSG("intelfbhw_do_blank: blank is %d\n", blank);
325#endif
326
327 /* Turn plane A on or off */
328 tmp = INREG(DSPACNTR);
329 if (blank)
330 tmp &= ~DISPPLANE_PLANE_ENABLE;
331 else
332 tmp |= DISPPLANE_PLANE_ENABLE;
333 OUTREG(DSPACNTR, tmp);
334 /* Flush */
335 tmp = INREG(DSPABASE);
336 OUTREG(DSPABASE, tmp);
337
338 /* Turn off/on the HW cursor */
339#if VERBOSE > 0
340 DBG_MSG("cursor_on is %d\n", dinfo->cursor_on);
341#endif
342 if (dinfo->cursor_on) {
343 if (blank) {
344 intelfbhw_cursor_hide(dinfo);
345 } else {
346 intelfbhw_cursor_show(dinfo);
347 }
348 dinfo->cursor_on = 1;
349 }
350 dinfo->cursor_blanked = blank;
351
352 /* Set DPMS level */
353 tmp = INREG(ADPA) & ~ADPA_DPMS_CONTROL_MASK;
354 switch (blank) {
355 case FB_BLANK_UNBLANK:
356 case FB_BLANK_NORMAL:
357 tmp |= ADPA_DPMS_D0;
358 break;
359 case FB_BLANK_VSYNC_SUSPEND:
360 tmp |= ADPA_DPMS_D1;
361 break;
362 case FB_BLANK_HSYNC_SUSPEND:
363 tmp |= ADPA_DPMS_D2;
364 break;
365 case FB_BLANK_POWERDOWN:
366 tmp |= ADPA_DPMS_D3;
367 break;
368 }
369 OUTREG(ADPA, tmp);
370
371 return;
372}
373
374
375void
376intelfbhw_setcolreg(struct intelfb_info *dinfo, unsigned regno,
377 unsigned red, unsigned green, unsigned blue,
378 unsigned transp)
379{
380#if VERBOSE > 0
381 DBG_MSG("intelfbhw_setcolreg: %d: (%d, %d, %d)\n",
382 regno, red, green, blue);
383#endif
384
385 u32 palette_reg = (dinfo->pipe == PIPE_A) ?
386 PALETTE_A : PALETTE_B;
387
388 OUTREG(palette_reg + (regno << 2),
389 (red << PALETTE_8_RED_SHIFT) |
390 (green << PALETTE_8_GREEN_SHIFT) |
391 (blue << PALETTE_8_BLUE_SHIFT));
392}
393
394
395int
396intelfbhw_read_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw,
397 int flag)
398{
399 int i;
400
401#if VERBOSE > 0
402 DBG_MSG("intelfbhw_read_hw_state\n");
403#endif
404
405 if (!hw || !dinfo)
406 return -1;
407
408 /* Read in as much of the HW state as possible. */
409 hw->vga0_divisor = INREG(VGA0_DIVISOR);
410 hw->vga1_divisor = INREG(VGA1_DIVISOR);
411 hw->vga_pd = INREG(VGAPD);
412 hw->dpll_a = INREG(DPLL_A);
413 hw->dpll_b = INREG(DPLL_B);
414 hw->fpa0 = INREG(FPA0);
415 hw->fpa1 = INREG(FPA1);
416 hw->fpb0 = INREG(FPB0);
417 hw->fpb1 = INREG(FPB1);
418
419 if (flag == 1)
420 return flag;
421
422#if 0
423 /* This seems to be a problem with the 852GM/855GM */
424 for (i = 0; i < PALETTE_8_ENTRIES; i++) {
425 hw->palette_a[i] = INREG(PALETTE_A + (i << 2));
426 hw->palette_b[i] = INREG(PALETTE_B + (i << 2));
427 }
428#endif
429
430 if (flag == 2)
431 return flag;
432
433 hw->htotal_a = INREG(HTOTAL_A);
434 hw->hblank_a = INREG(HBLANK_A);
435 hw->hsync_a = INREG(HSYNC_A);
436 hw->vtotal_a = INREG(VTOTAL_A);
437 hw->vblank_a = INREG(VBLANK_A);
438 hw->vsync_a = INREG(VSYNC_A);
439 hw->src_size_a = INREG(SRC_SIZE_A);
440 hw->bclrpat_a = INREG(BCLRPAT_A);
441 hw->htotal_b = INREG(HTOTAL_B);
442 hw->hblank_b = INREG(HBLANK_B);
443 hw->hsync_b = INREG(HSYNC_B);
444 hw->vtotal_b = INREG(VTOTAL_B);
445 hw->vblank_b = INREG(VBLANK_B);
446 hw->vsync_b = INREG(VSYNC_B);
447 hw->src_size_b = INREG(SRC_SIZE_B);
448 hw->bclrpat_b = INREG(BCLRPAT_B);
449
450 if (flag == 3)
451 return flag;
452
453 hw->adpa = INREG(ADPA);
454 hw->dvoa = INREG(DVOA);
455 hw->dvob = INREG(DVOB);
456 hw->dvoc = INREG(DVOC);
457 hw->dvoa_srcdim = INREG(DVOA_SRCDIM);
458 hw->dvob_srcdim = INREG(DVOB_SRCDIM);
459 hw->dvoc_srcdim = INREG(DVOC_SRCDIM);
460 hw->lvds = INREG(LVDS);
461
462 if (flag == 4)
463 return flag;
464
465 hw->pipe_a_conf = INREG(PIPEACONF);
466 hw->pipe_b_conf = INREG(PIPEBCONF);
467 hw->disp_arb = INREG(DISPARB);
468
469 if (flag == 5)
470 return flag;
471
472 hw->cursor_a_control = INREG(CURSOR_A_CONTROL);
473 hw->cursor_b_control = INREG(CURSOR_B_CONTROL);
474 hw->cursor_a_base = INREG(CURSOR_A_BASEADDR);
475 hw->cursor_b_base = INREG(CURSOR_B_BASEADDR);
476
477 if (flag == 6)
478 return flag;
479
480 for (i = 0; i < 4; i++) {
481 hw->cursor_a_palette[i] = INREG(CURSOR_A_PALETTE0 + (i << 2));
482 hw->cursor_b_palette[i] = INREG(CURSOR_B_PALETTE0 + (i << 2));
483 }
484
485 if (flag == 7)
486 return flag;
487
488 hw->cursor_size = INREG(CURSOR_SIZE);
489
490 if (flag == 8)
491 return flag;
492
493 hw->disp_a_ctrl = INREG(DSPACNTR);
494 hw->disp_b_ctrl = INREG(DSPBCNTR);
495 hw->disp_a_base = INREG(DSPABASE);
496 hw->disp_b_base = INREG(DSPBBASE);
497 hw->disp_a_stride = INREG(DSPASTRIDE);
498 hw->disp_b_stride = INREG(DSPBSTRIDE);
499
500 if (flag == 9)
501 return flag;
502
503 hw->vgacntrl = INREG(VGACNTRL);
504
505 if (flag == 10)
506 return flag;
507
508 hw->add_id = INREG(ADD_ID);
509
510 if (flag == 11)
511 return flag;
512
513 for (i = 0; i < 7; i++) {
514 hw->swf0x[i] = INREG(SWF00 + (i << 2));
515 hw->swf1x[i] = INREG(SWF10 + (i << 2));
516 if (i < 3)
517 hw->swf3x[i] = INREG(SWF30 + (i << 2));
518 }
519
520 for (i = 0; i < 8; i++)
521 hw->fence[i] = INREG(FENCE + (i << 2));
522
523 hw->instpm = INREG(INSTPM);
524 hw->mem_mode = INREG(MEM_MODE);
525 hw->fw_blc_0 = INREG(FW_BLC_0);
526 hw->fw_blc_1 = INREG(FW_BLC_1);
527
528 return 0;
529}
530
531
532void
533intelfbhw_print_hw_state(struct intelfb_info *dinfo, struct intelfb_hwstate *hw)
534{
535#if REGDUMP
536 int i, m1, m2, n, p1, p2;
537
538 DBG_MSG("intelfbhw_print_hw_state\n");
539
540 if (!hw || !dinfo)
541 return;
542 /* Read in as much of the HW state as possible. */
543 printk("hw state dump start\n");
544 printk(" VGA0_DIVISOR: 0x%08x\n", hw->vga0_divisor);
545 printk(" VGA1_DIVISOR: 0x%08x\n", hw->vga1_divisor);
546 printk(" VGAPD: 0x%08x\n", hw->vga_pd);
547 n = (hw->vga0_divisor >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
548 m1 = (hw->vga0_divisor >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
549 m2 = (hw->vga0_divisor >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
550 if (hw->vga_pd & VGAPD_0_P1_FORCE_DIV2)
551 p1 = 0;
552 else
553 p1 = (hw->vga_pd >> VGAPD_0_P1_SHIFT) & DPLL_P1_MASK;
554 p2 = (hw->vga_pd >> VGAPD_0_P2_SHIFT) & DPLL_P2_MASK;
555 printk(" VGA0: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n",
556 m1, m2, n, p1, p2);
557 printk(" VGA0: clock is %d\n", CALC_VCLOCK(m1, m2, n, p1, p2));
558
559 n = (hw->vga1_divisor >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
560 m1 = (hw->vga1_divisor >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
561 m2 = (hw->vga1_divisor >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
562 if (hw->vga_pd & VGAPD_1_P1_FORCE_DIV2)
563 p1 = 0;
564 else
565 p1 = (hw->vga_pd >> VGAPD_1_P1_SHIFT) & DPLL_P1_MASK;
566 p2 = (hw->vga_pd >> VGAPD_1_P2_SHIFT) & DPLL_P2_MASK;
567 printk(" VGA1: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n",
568 m1, m2, n, p1, p2);
569 printk(" VGA1: clock is %d\n", CALC_VCLOCK(m1, m2, n, p1, p2));
570
571 printk(" DPLL_A: 0x%08x\n", hw->dpll_a);
572 printk(" DPLL_B: 0x%08x\n", hw->dpll_b);
573 printk(" FPA0: 0x%08x\n", hw->fpa0);
574 printk(" FPA1: 0x%08x\n", hw->fpa1);
575 printk(" FPB0: 0x%08x\n", hw->fpb0);
576 printk(" FPB1: 0x%08x\n", hw->fpb1);
577
578 n = (hw->fpa0 >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
579 m1 = (hw->fpa0 >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
580 m2 = (hw->fpa0 >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
581 if (hw->dpll_a & DPLL_P1_FORCE_DIV2)
582 p1 = 0;
583 else
584 p1 = (hw->dpll_a >> DPLL_P1_SHIFT) & DPLL_P1_MASK;
585 p2 = (hw->dpll_a >> DPLL_P2_SHIFT) & DPLL_P2_MASK;
586 printk(" PLLA0: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n",
587 m1, m2, n, p1, p2);
588 printk(" PLLA0: clock is %d\n", CALC_VCLOCK(m1, m2, n, p1, p2));
589
590 n = (hw->fpa1 >> FP_N_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
591 m1 = (hw->fpa1 >> FP_M1_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
592 m2 = (hw->fpa1 >> FP_M2_DIVISOR_SHIFT) & FP_DIVISOR_MASK;
593 if (hw->dpll_a & DPLL_P1_FORCE_DIV2)
594 p1 = 0;
595 else
596 p1 = (hw->dpll_a >> DPLL_P1_SHIFT) & DPLL_P1_MASK;
597 p2 = (hw->dpll_a >> DPLL_P2_SHIFT) & DPLL_P2_MASK;
598 printk(" PLLA1: (m1, m2, n, p1, p2) = (%d, %d, %d, %d, %d)\n",
599 m1, m2, n, p1, p2);
600 printk(" PLLA1: clock is %d\n", CALC_VCLOCK(m1, m2, n, p1, p2));
601
602#if 0
603 printk(" PALETTE_A:\n");
604 for (i = 0; i < PALETTE_8_ENTRIES)
605 printk(" %3d: 0x%08x\n", i, hw->palette_a[i];
606 printk(" PALETTE_B:\n");
607 for (i = 0; i < PALETTE_8_ENTRIES)
608 printk(" %3d: 0x%08x\n", i, hw->palette_b[i];
609#endif
610
611 printk(" HTOTAL_A: 0x%08x\n", hw->htotal_a);
612 printk(" HBLANK_A: 0x%08x\n", hw->hblank_a);
613 printk(" HSYNC_A: 0x%08x\n", hw->hsync_a);
614 printk(" VTOTAL_A: 0x%08x\n", hw->vtotal_a);
615 printk(" VBLANK_A: 0x%08x\n", hw->vblank_a);
616 printk(" VSYNC_A: 0x%08x\n", hw->vsync_a);
617 printk(" SRC_SIZE_A: 0x%08x\n", hw->src_size_a);
618 printk(" BCLRPAT_A: 0x%08x\n", hw->bclrpat_a);
619 printk(" HTOTAL_B: 0x%08x\n", hw->htotal_b);
620 printk(" HBLANK_B: 0x%08x\n", hw->hblank_b);
621 printk(" HSYNC_B: 0x%08x\n", hw->hsync_b);
622 printk(" VTOTAL_B: 0x%08x\n", hw->vtotal_b);
623 printk(" VBLANK_B: 0x%08x\n", hw->vblank_b);
624 printk(" VSYNC_B: 0x%08x\n", hw->vsync_b);
625 printk(" SRC_SIZE_B: 0x%08x\n", hw->src_size_b);
626 printk(" BCLRPAT_B: 0x%08x\n", hw->bclrpat_b);
627
628 printk(" ADPA: 0x%08x\n", hw->adpa);
629 printk(" DVOA: 0x%08x\n", hw->dvoa);
630 printk(" DVOB: 0x%08x\n", hw->dvob);
631 printk(" DVOC: 0x%08x\n", hw->dvoc);
632 printk(" DVOA_SRCDIM: 0x%08x\n", hw->dvoa_srcdim);
633 printk(" DVOB_SRCDIM: 0x%08x\n", hw->dvob_srcdim);
634 printk(" DVOC_SRCDIM: 0x%08x\n", hw->dvoc_srcdim);
635 printk(" LVDS: 0x%08x\n", hw->lvds);
636
637 printk(" PIPEACONF: 0x%08x\n", hw->pipe_a_conf);
638 printk(" PIPEBCONF: 0x%08x\n", hw->pipe_b_conf);
639 printk(" DISPARB: 0x%08x\n", hw->disp_arb);
640
641 printk(" CURSOR_A_CONTROL: 0x%08x\n", hw->cursor_a_control);
642 printk(" CURSOR_B_CONTROL: 0x%08x\n", hw->cursor_b_control);
643 printk(" CURSOR_A_BASEADDR: 0x%08x\n", hw->cursor_a_base);
644 printk(" CURSOR_B_BASEADDR: 0x%08x\n", hw->cursor_b_base);
645
646 printk(" CURSOR_A_PALETTE: ");
647 for (i = 0; i < 4; i++) {
648 printk("0x%08x", hw->cursor_a_palette[i]);
649 if (i < 3)
650 printk(", ");
651 }
652 printk("\n");
653 printk(" CURSOR_B_PALETTE: ");
654 for (i = 0; i < 4; i++) {
655 printk("0x%08x", hw->cursor_b_palette[i]);
656 if (i < 3)
657 printk(", ");
658 }
659 printk("\n");
660
661 printk(" CURSOR_SIZE: 0x%08x\n", hw->cursor_size);
662
663 printk(" DSPACNTR: 0x%08x\n", hw->disp_a_ctrl);
664 printk(" DSPBCNTR: 0x%08x\n", hw->disp_b_ctrl);
665 printk(" DSPABASE: 0x%08x\n", hw->disp_a_base);
666 printk(" DSPBBASE: 0x%08x\n", hw->disp_b_base);
667 printk(" DSPASTRIDE: 0x%08x\n", hw->disp_a_stride);
668 printk(" DSPBSTRIDE: 0x%08x\n", hw->disp_b_stride);
669
670 printk(" VGACNTRL: 0x%08x\n", hw->vgacntrl);
671 printk(" ADD_ID: 0x%08x\n", hw->add_id);
672
673 for (i = 0; i < 7; i++) {
674 printk(" SWF0%d 0x%08x\n", i,
675 hw->swf0x[i]);
676 }
677 for (i = 0; i < 7; i++) {
678 printk(" SWF1%d 0x%08x\n", i,
679 hw->swf1x[i]);
680 }
681 for (i = 0; i < 3; i++) {
682 printk(" SWF3%d 0x%08x\n", i,
683 hw->swf3x[i]);
684 }
685 for (i = 0; i < 8; i++)
686 printk(" FENCE%d 0x%08x\n", i,
687 hw->fence[i]);
688
689 printk(" INSTPM 0x%08x\n", hw->instpm);
690 printk(" MEM_MODE 0x%08x\n", hw->mem_mode);
691 printk(" FW_BLC_0 0x%08x\n", hw->fw_blc_0);
692 printk(" FW_BLC_1 0x%08x\n", hw->fw_blc_1);
693
694 printk("hw state dump end\n");
695#endif
696}
697
698/* Split the M parameter into M1 and M2. */
699static int
700splitm(unsigned int m, unsigned int *retm1, unsigned int *retm2)
701{
702 int m1, m2;
703
704 m1 = (m - 2 - (MIN_M2 + MAX_M2) / 2) / 5 - 2;
705 if (m1 < MIN_M1)
706 m1 = MIN_M1;
707 if (m1 > MAX_M1)
708 m1 = MAX_M1;
709 m2 = m - 5 * (m1 + 2) - 2;
710 if (m2 < MIN_M2 || m2 > MAX_M2 || m2 >= m1) {
711 return 1;
712 } else {
713 *retm1 = (unsigned int)m1;
714 *retm2 = (unsigned int)m2;
715 return 0;
716 }
717}
718
719/* Split the P parameter into P1 and P2. */
720static int
721splitp(unsigned int p, unsigned int *retp1, unsigned int *retp2)
722{
723 int p1, p2;
724
725 if (p % 4 == 0)
726 p2 = 1;
727 else
728 p2 = 0;
729 p1 = (p / (1 << (p2 + 1))) - 2;
730 if (p % 4 == 0 && p1 < MIN_P1) {
731 p2 = 0;
732 p1 = (p / (1 << (p2 + 1))) - 2;
733 }
734 if (p1 < MIN_P1 || p1 > MAX_P1 || (p1 + 2) * (1 << (p2 + 1)) != p) {
735 return 1;
736 } else {
737 *retp1 = (unsigned int)p1;
738 *retp2 = (unsigned int)p2;
739 return 0;
740 }
741}
742
743static int
744calc_pll_params(int clock, u32 *retm1, u32 *retm2, u32 *retn, u32 *retp1,
745 u32 *retp2, u32 *retclock)
746{
747 u32 m1, m2, n, p1, p2, n1;
748 u32 f_vco, p, p_best = 0, m, f_out;
749 u32 err_max, err_target, err_best = 10000000;
750 u32 n_best = 0, m_best = 0, f_best, f_err;
751 u32 p_min, p_max, p_inc, div_min, div_max;
752
753 /* Accept 0.5% difference, but aim for 0.1% */
754 err_max = 5 * clock / 1000;
755 err_target = clock / 1000;
756
757 DBG_MSG("Clock is %d\n", clock);
758
759 div_max = MAX_VCO_FREQ / clock;
760 div_min = ROUND_UP_TO(MIN_VCO_FREQ, clock) / clock;
761
762 if (clock <= P_TRANSITION_CLOCK)
763 p_inc = 4;
764 else
765 p_inc = 2;
766 p_min = ROUND_UP_TO(div_min, p_inc);
767 p_max = ROUND_DOWN_TO(div_max, p_inc);
768 if (p_min < MIN_P)
769 p_min = 4;
770 if (p_max > MAX_P)
771 p_max = 128;
772
773 DBG_MSG("p range is %d-%d (%d)\n", p_min, p_max, p_inc);
774
775 p = p_min;
776 do {
777 if (splitp(p, &p1, &p2)) {
778 WRN_MSG("cannot split p = %d\n", p);
779 p += p_inc;
780 continue;
781 }
782 n = MIN_N;
783 f_vco = clock * p;
784
785 do {
786 m = ROUND_UP_TO(f_vco * n, PLL_REFCLK) / PLL_REFCLK;
787 if (m < MIN_M)
788 m = MIN_M;
789 if (m > MAX_M)
790 m = MAX_M;
791 f_out = CALC_VCLOCK3(m, n, p);
792 if (splitm(m, &m1, &m2)) {
793 WRN_MSG("cannot split m = %d\n", m);
794 n++;
795 continue;
796 }
797 if (clock > f_out)
798 f_err = clock - f_out;
799 else
800 f_err = f_out - clock;
801
802 if (f_err < err_best) {
803 m_best = m;
804 n_best = n;
805 p_best = p;
806 f_best = f_out;
807 err_best = f_err;
808 }
809 n++;
810 } while ((n <= MAX_N) && (f_out >= clock));
811 p += p_inc;
812 } while ((p <= p_max));
813
814 if (!m_best) {
815 WRN_MSG("cannot find parameters for clock %d\n", clock);
816 return 1;
817 }
818 m = m_best;
819 n = n_best;
820 p = p_best;
821 splitm(m, &m1, &m2);
822 splitp(p, &p1, &p2);
823 n1 = n - 2;
824
825 DBG_MSG("m, n, p: %d (%d,%d), %d (%d), %d (%d,%d), "
826 "f: %d (%d), VCO: %d\n",
827 m, m1, m2, n, n1, p, p1, p2,
828 CALC_VCLOCK3(m, n, p), CALC_VCLOCK(m1, m2, n1, p1, p2),
829 CALC_VCLOCK3(m, n, p) * p);
830 *retm1 = m1;
831 *retm2 = m2;
832 *retn = n1;
833 *retp1 = p1;
834 *retp2 = p2;
835 *retclock = CALC_VCLOCK(m1, m2, n1, p1, p2);
836
837 return 0;
838}
839
840static __inline__ int
841check_overflow(u32 value, u32 limit, const char *description)
842{
843 if (value > limit) {
844 WRN_MSG("%s value %d exceeds limit %d\n",
845 description, value, limit);
846 return 1;
847 }
848 return 0;
849}
850
851/* It is assumed that hw is filled in with the initial state information. */
852int
853intelfbhw_mode_to_hw(struct intelfb_info *dinfo, struct intelfb_hwstate *hw,
854 struct fb_var_screeninfo *var)
855{
856 int pipe = PIPE_A;
857 u32 *dpll, *fp0, *fp1;
858 u32 m1, m2, n, p1, p2, clock_target, clock;
859 u32 hsync_start, hsync_end, hblank_start, hblank_end, htotal, hactive;
860 u32 vsync_start, vsync_end, vblank_start, vblank_end, vtotal, vactive;
861 u32 vsync_pol, hsync_pol;
862 u32 *vs, *vb, *vt, *hs, *hb, *ht, *ss, *pipe_conf;
863
864 DBG_MSG("intelfbhw_mode_to_hw\n");
865
866 /* Disable VGA */
867 hw->vgacntrl |= VGA_DISABLE;
868
869 /* Check whether pipe A or pipe B is enabled. */
870 if (hw->pipe_a_conf & PIPECONF_ENABLE)
871 pipe = PIPE_A;
872 else if (hw->pipe_b_conf & PIPECONF_ENABLE)
873 pipe = PIPE_B;
874
875 /* Set which pipe's registers will be set. */
876 if (pipe == PIPE_B) {
877 dpll = &hw->dpll_b;
878 fp0 = &hw->fpb0;
879 fp1 = &hw->fpb1;
880 hs = &hw->hsync_b;
881 hb = &hw->hblank_b;
882 ht = &hw->htotal_b;
883 vs = &hw->vsync_b;
884 vb = &hw->vblank_b;
885 vt = &hw->vtotal_b;
886 ss = &hw->src_size_b;
887 pipe_conf = &hw->pipe_b_conf;
888 } else {
889 dpll = &hw->dpll_a;
890 fp0 = &hw->fpa0;
891 fp1 = &hw->fpa1;
892 hs = &hw->hsync_a;
893 hb = &hw->hblank_a;
894 ht = &hw->htotal_a;
895 vs = &hw->vsync_a;
896 vb = &hw->vblank_a;
897 vt = &hw->vtotal_a;
898 ss = &hw->src_size_a;
899 pipe_conf = &hw->pipe_a_conf;
900 }
901
902 /* Use ADPA register for sync control. */
903 hw->adpa &= ~ADPA_USE_VGA_HVPOLARITY;
904
905 /* sync polarity */
906 hsync_pol = (var->sync & FB_SYNC_HOR_HIGH_ACT) ?
907 ADPA_SYNC_ACTIVE_HIGH : ADPA_SYNC_ACTIVE_LOW;
908 vsync_pol = (var->sync & FB_SYNC_VERT_HIGH_ACT) ?
909 ADPA_SYNC_ACTIVE_HIGH : ADPA_SYNC_ACTIVE_LOW;
910 hw->adpa &= ~((ADPA_SYNC_ACTIVE_MASK << ADPA_VSYNC_ACTIVE_SHIFT) |
911 (ADPA_SYNC_ACTIVE_MASK << ADPA_HSYNC_ACTIVE_SHIFT));
912 hw->adpa |= (hsync_pol << ADPA_HSYNC_ACTIVE_SHIFT) |
913 (vsync_pol << ADPA_VSYNC_ACTIVE_SHIFT);
914
915 /* Connect correct pipe to the analog port DAC */
916 hw->adpa &= ~(PIPE_MASK << ADPA_PIPE_SELECT_SHIFT);
917 hw->adpa |= (pipe << ADPA_PIPE_SELECT_SHIFT);
918
919 /* Set DPMS state to D0 (on) */
920 hw->adpa &= ~ADPA_DPMS_CONTROL_MASK;
921 hw->adpa |= ADPA_DPMS_D0;
922
923 hw->adpa |= ADPA_DAC_ENABLE;
924
925 *dpll |= (DPLL_VCO_ENABLE | DPLL_VGA_MODE_DISABLE);
926 *dpll &= ~(DPLL_RATE_SELECT_MASK | DPLL_REFERENCE_SELECT_MASK);
927 *dpll |= (DPLL_REFERENCE_DEFAULT | DPLL_RATE_SELECT_FP0);
928
929 /* Desired clock in kHz */
930 clock_target = 1000000000 / var->pixclock;
931
932 if (calc_pll_params(clock_target, &m1, &m2, &n, &p1, &p2, &clock)) {
933 WRN_MSG("calc_pll_params failed\n");
934 return 1;
935 }
936
937 /* Check for overflow. */
938 if (check_overflow(p1, DPLL_P1_MASK, "PLL P1 parameter"))
939 return 1;
940 if (check_overflow(p2, DPLL_P2_MASK, "PLL P2 parameter"))
941 return 1;
942 if (check_overflow(m1, FP_DIVISOR_MASK, "PLL M1 parameter"))
943 return 1;
944 if (check_overflow(m2, FP_DIVISOR_MASK, "PLL M2 parameter"))
945 return 1;
946 if (check_overflow(n, FP_DIVISOR_MASK, "PLL N parameter"))
947 return 1;
948
949 *dpll &= ~DPLL_P1_FORCE_DIV2;
950 *dpll &= ~((DPLL_P2_MASK << DPLL_P2_SHIFT) |
951 (DPLL_P1_MASK << DPLL_P1_SHIFT));
952 *dpll |= (p2 << DPLL_P2_SHIFT) | (p1 << DPLL_P1_SHIFT);
953 *fp0 = (n << FP_N_DIVISOR_SHIFT) |
954 (m1 << FP_M1_DIVISOR_SHIFT) |
955 (m2 << FP_M2_DIVISOR_SHIFT);
956 *fp1 = *fp0;
957
958 hw->dvob &= ~PORT_ENABLE;
959 hw->dvoc &= ~PORT_ENABLE;
960
961 /* Use display plane A. */
962 hw->disp_a_ctrl |= DISPPLANE_PLANE_ENABLE;
963 hw->disp_a_ctrl &= ~DISPPLANE_GAMMA_ENABLE;
964 hw->disp_a_ctrl &= ~DISPPLANE_PIXFORMAT_MASK;
965 switch (intelfb_var_to_depth(var)) {
966 case 8:
967 hw->disp_a_ctrl |= DISPPLANE_8BPP | DISPPLANE_GAMMA_ENABLE;
968 break;
969 case 15:
970 hw->disp_a_ctrl |= DISPPLANE_15_16BPP;
971 break;
972 case 16:
973 hw->disp_a_ctrl |= DISPPLANE_16BPP;
974 break;
975 case 24:
976 hw->disp_a_ctrl |= DISPPLANE_32BPP_NO_ALPHA;
977 break;
978 }
979 hw->disp_a_ctrl &= ~(PIPE_MASK << DISPPLANE_SEL_PIPE_SHIFT);
980 hw->disp_a_ctrl |= (pipe << DISPPLANE_SEL_PIPE_SHIFT);
981
982 /* Set CRTC registers. */
983 hactive = var->xres;
984 hsync_start = hactive + var->right_margin;
985 hsync_end = hsync_start + var->hsync_len;
986 htotal = hsync_end + var->left_margin;
987 hblank_start = hactive;
988 hblank_end = htotal;
989
990 DBG_MSG("H: act %d, ss %d, se %d, tot %d bs %d, be %d\n",
991 hactive, hsync_start, hsync_end, htotal, hblank_start,
992 hblank_end);
993
994 vactive = var->yres;
995 vsync_start = vactive + var->lower_margin;
996 vsync_end = vsync_start + var->vsync_len;
997 vtotal = vsync_end + var->upper_margin;
998 vblank_start = vactive;
999 vblank_end = vtotal;
1000 vblank_end = vsync_end + 1;
1001
1002 DBG_MSG("V: act %d, ss %d, se %d, tot %d bs %d, be %d\n",
1003 vactive, vsync_start, vsync_end, vtotal, vblank_start,
1004 vblank_end);
1005
1006 /* Adjust for register values, and check for overflow. */
1007 hactive--;
1008 if (check_overflow(hactive, HACTIVE_MASK, "CRTC hactive"))
1009 return 1;
1010 hsync_start--;
1011 if (check_overflow(hsync_start, HSYNCSTART_MASK, "CRTC hsync_start"))
1012 return 1;
1013 hsync_end--;
1014 if (check_overflow(hsync_end, HSYNCEND_MASK, "CRTC hsync_end"))
1015 return 1;
1016 htotal--;
1017 if (check_overflow(htotal, HTOTAL_MASK, "CRTC htotal"))
1018 return 1;
1019 hblank_start--;
1020 if (check_overflow(hblank_start, HBLANKSTART_MASK, "CRTC hblank_start"))
1021 return 1;
1022 hblank_end--;
1023 if (check_overflow(hblank_end, HBLANKEND_MASK, "CRTC hblank_end"))
1024 return 1;
1025
1026 vactive--;
1027 if (check_overflow(vactive, VACTIVE_MASK, "CRTC vactive"))
1028 return 1;
1029 vsync_start--;
1030 if (check_overflow(vsync_start, VSYNCSTART_MASK, "CRTC vsync_start"))
1031 return 1;
1032 vsync_end--;
1033 if (check_overflow(vsync_end, VSYNCEND_MASK, "CRTC vsync_end"))
1034 return 1;
1035 vtotal--;
1036 if (check_overflow(vtotal, VTOTAL_MASK, "CRTC vtotal"))
1037 return 1;
1038 vblank_start--;
1039 if (check_overflow(vblank_start, VBLANKSTART_MASK, "CRTC vblank_start"))
1040 return 1;
1041 vblank_end--;
1042 if (check_overflow(vblank_end, VBLANKEND_MASK, "CRTC vblank_end"))
1043 return 1;
1044
1045 *ht = (htotal << HTOTAL_SHIFT) | (hactive << HACTIVE_SHIFT);
1046 *hb = (hblank_start << HBLANKSTART_SHIFT) |
1047 (hblank_end << HSYNCEND_SHIFT);
1048 *hs = (hsync_start << HSYNCSTART_SHIFT) | (hsync_end << HSYNCEND_SHIFT);
1049
1050 *vt = (vtotal << VTOTAL_SHIFT) | (vactive << VACTIVE_SHIFT);
1051 *vb = (vblank_start << VBLANKSTART_SHIFT) |
1052 (vblank_end << VSYNCEND_SHIFT);
1053 *vs = (vsync_start << VSYNCSTART_SHIFT) | (vsync_end << VSYNCEND_SHIFT);
1054 *ss = (hactive << SRC_SIZE_HORIZ_SHIFT) |
1055 (vactive << SRC_SIZE_VERT_SHIFT);
1056
1057 hw->disp_a_stride = var->xres_virtual * var->bits_per_pixel / 8;
1058 DBG_MSG("pitch is %d\n", hw->disp_a_stride);
1059
1060 hw->disp_a_base = hw->disp_a_stride * var->yoffset +
1061 var->xoffset * var->bits_per_pixel / 8;
1062
1063 hw->disp_a_base += dinfo->fb.offset << 12;
1064
1065 /* Check stride alignment. */
1066 if (hw->disp_a_stride % STRIDE_ALIGNMENT != 0) {
1067 WRN_MSG("display stride %d has bad alignment %d\n",
1068 hw->disp_a_stride, STRIDE_ALIGNMENT);
1069 return 1;
1070 }
1071
1072 /* Set the palette to 8-bit mode. */
1073 *pipe_conf &= ~PIPECONF_GAMMA;
1074 return 0;
1075}
1076
1077/* Program a (non-VGA) video mode. */
1078int
1079intelfbhw_program_mode(struct intelfb_info *dinfo,
1080 const struct intelfb_hwstate *hw, int blank)
1081{
1082 int pipe = PIPE_A;
1083 u32 tmp;
1084 const u32 *dpll, *fp0, *fp1, *pipe_conf;
1085 const u32 *hs, *ht, *hb, *vs, *vt, *vb, *ss;
1086 u32 dpll_reg, fp0_reg, fp1_reg, pipe_conf_reg;
1087 u32 hsync_reg, htotal_reg, hblank_reg;
1088 u32 vsync_reg, vtotal_reg, vblank_reg;
1089 u32 src_size_reg;
1090
1091 /* Assume single pipe, display plane A, analog CRT. */
1092
1093#if VERBOSE > 0
1094 DBG_MSG("intelfbhw_program_mode\n");
1095#endif
1096
1097 /* Disable VGA */
1098 tmp = INREG(VGACNTRL);
1099 tmp |= VGA_DISABLE;
1100 OUTREG(VGACNTRL, tmp);
1101
1102 /* Check whether pipe A or pipe B is enabled. */
1103 if (hw->pipe_a_conf & PIPECONF_ENABLE)
1104 pipe = PIPE_A;
1105 else if (hw->pipe_b_conf & PIPECONF_ENABLE)
1106 pipe = PIPE_B;
1107
1108 dinfo->pipe = pipe;
1109
1110 if (pipe == PIPE_B) {
1111 dpll = &hw->dpll_b;
1112 fp0 = &hw->fpb0;
1113 fp1 = &hw->fpb1;
1114 pipe_conf = &hw->pipe_b_conf;
1115 hs = &hw->hsync_b;
1116 hb = &hw->hblank_b;
1117 ht = &hw->htotal_b;
1118 vs = &hw->vsync_b;
1119 vb = &hw->vblank_b;
1120 vt = &hw->vtotal_b;
1121 ss = &hw->src_size_b;
1122 dpll_reg = DPLL_B;
1123 fp0_reg = FPB0;
1124 fp1_reg = FPB1;
1125 pipe_conf_reg = PIPEBCONF;
1126 hsync_reg = HSYNC_B;
1127 htotal_reg = HTOTAL_B;
1128 hblank_reg = HBLANK_B;
1129 vsync_reg = VSYNC_B;
1130 vtotal_reg = VTOTAL_B;
1131 vblank_reg = VBLANK_B;
1132 src_size_reg = SRC_SIZE_B;
1133 } else {
1134 dpll = &hw->dpll_a;
1135 fp0 = &hw->fpa0;
1136 fp1 = &hw->fpa1;
1137 pipe_conf = &hw->pipe_a_conf;
1138 hs = &hw->hsync_a;
1139 hb = &hw->hblank_a;
1140 ht = &hw->htotal_a;
1141 vs = &hw->vsync_a;
1142 vb = &hw->vblank_a;
1143 vt = &hw->vtotal_a;
1144 ss = &hw->src_size_a;
1145 dpll_reg = DPLL_A;
1146 fp0_reg = FPA0;
1147 fp1_reg = FPA1;
1148 pipe_conf_reg = PIPEACONF;
1149 hsync_reg = HSYNC_A;
1150 htotal_reg = HTOTAL_A;
1151 hblank_reg = HBLANK_A;
1152 vsync_reg = VSYNC_A;
1153 vtotal_reg = VTOTAL_A;
1154 vblank_reg = VBLANK_A;
1155 src_size_reg = SRC_SIZE_A;
1156 }
1157
1158 /* Disable planes A and B. */
1159 tmp = INREG(DSPACNTR);
1160 tmp &= ~DISPPLANE_PLANE_ENABLE;
1161 OUTREG(DSPACNTR, tmp);
1162 tmp = INREG(DSPBCNTR);
1163 tmp &= ~DISPPLANE_PLANE_ENABLE;
1164 OUTREG(DSPBCNTR, tmp);
1165
1166 /* Wait for vblank. For now, just wait for a 50Hz cycle (20ms)) */
1167 mdelay(20);
1168
1169 /* Disable Sync */
1170 tmp = INREG(ADPA);
1171 tmp &= ~ADPA_DPMS_CONTROL_MASK;
1172 tmp |= ADPA_DPMS_D3;
1173 OUTREG(ADPA, tmp);
1174
1175 /* turn off pipe */
1176 tmp = INREG(pipe_conf_reg);
1177 tmp &= ~PIPECONF_ENABLE;
1178 OUTREG(pipe_conf_reg, tmp);
1179
1180 /* turn off PLL */
1181 tmp = INREG(dpll_reg);
1182 dpll_reg &= ~DPLL_VCO_ENABLE;
1183 OUTREG(dpll_reg, tmp);
1184
1185 /* Set PLL parameters */
1186 OUTREG(dpll_reg, *dpll & ~DPLL_VCO_ENABLE);
1187 OUTREG(fp0_reg, *fp0);
1188 OUTREG(fp1_reg, *fp1);
1189
1190 /* Set pipe parameters */
1191 OUTREG(hsync_reg, *hs);
1192 OUTREG(hblank_reg, *hb);
1193 OUTREG(htotal_reg, *ht);
1194 OUTREG(vsync_reg, *vs);
1195 OUTREG(vblank_reg, *vb);
1196 OUTREG(vtotal_reg, *vt);
1197 OUTREG(src_size_reg, *ss);
1198
1199 /* Set DVOs B/C */
1200 OUTREG(DVOB, hw->dvob);
1201 OUTREG(DVOC, hw->dvoc);
1202
1203 /* Set ADPA */
1204 OUTREG(ADPA, (hw->adpa & ~(ADPA_DPMS_CONTROL_MASK)) | ADPA_DPMS_D3);
1205
1206 /* Enable PLL */
1207 tmp = INREG(dpll_reg);
1208 tmp |= DPLL_VCO_ENABLE;
1209 OUTREG(dpll_reg, tmp);
1210
1211 /* Enable pipe */
1212 OUTREG(pipe_conf_reg, *pipe_conf | PIPECONF_ENABLE);
1213
1214 /* Enable sync */
1215 tmp = INREG(ADPA);
1216 tmp &= ~ADPA_DPMS_CONTROL_MASK;
1217 tmp |= ADPA_DPMS_D0;
1218 OUTREG(ADPA, tmp);
1219
1220 /* setup display plane */
1221 if (dinfo->pdev->device == PCI_DEVICE_ID_INTEL_830M) {
1222 /*
1223 * i830M errata: the display plane must be enabled
1224 * to allow writes to the other bits in the plane
1225 * control register.
1226 */
1227 tmp = INREG(DSPACNTR);
1228 if ((tmp & DISPPLANE_PLANE_ENABLE) != DISPPLANE_PLANE_ENABLE) {
1229 tmp |= DISPPLANE_PLANE_ENABLE;
1230 OUTREG(DSPACNTR, tmp);
1231 OUTREG(DSPACNTR,
1232 hw->disp_a_ctrl|DISPPLANE_PLANE_ENABLE);
1233 mdelay(1);
1234 }
1235 }
1236
1237 OUTREG(DSPACNTR, hw->disp_a_ctrl & ~DISPPLANE_PLANE_ENABLE);
1238 OUTREG(DSPASTRIDE, hw->disp_a_stride);
1239 OUTREG(DSPABASE, hw->disp_a_base);
1240
1241 /* Enable plane */
1242 if (!blank) {
1243 tmp = INREG(DSPACNTR);
1244 tmp |= DISPPLANE_PLANE_ENABLE;
1245 OUTREG(DSPACNTR, tmp);
1246 OUTREG(DSPABASE, hw->disp_a_base);
1247 }
1248
1249 return 0;
1250}
1251
1252/* forward declarations */
1253static void refresh_ring(struct intelfb_info *dinfo);
1254static void reset_state(struct intelfb_info *dinfo);
1255static void do_flush(struct intelfb_info *dinfo);
1256
1257static int
1258wait_ring(struct intelfb_info *dinfo, int n)
1259{
1260 int i = 0;
1261 unsigned long end;
1262 u32 last_head = INREG(PRI_RING_HEAD) & RING_HEAD_MASK;
1263
1264#if VERBOSE > 0
1265 DBG_MSG("wait_ring: %d\n", n);
1266#endif
1267
1268 end = jiffies + (HZ * 3);
1269 while (dinfo->ring_space < n) {
1270 dinfo->ring_head = (u8 __iomem *)(INREG(PRI_RING_HEAD) &
1271 RING_HEAD_MASK);
1272 if (dinfo->ring_tail + RING_MIN_FREE <
1273 (u32 __iomem) dinfo->ring_head)
1274 dinfo->ring_space = (u32 __iomem) dinfo->ring_head
1275 - (dinfo->ring_tail + RING_MIN_FREE);
1276 else
1277 dinfo->ring_space = (dinfo->ring.size +
1278 (u32 __iomem) dinfo->ring_head)
1279 - (dinfo->ring_tail + RING_MIN_FREE);
1280 if ((u32 __iomem) dinfo->ring_head != last_head) {
1281 end = jiffies + (HZ * 3);
1282 last_head = (u32 __iomem) dinfo->ring_head;
1283 }
1284 i++;
1285 if (time_before(end, jiffies)) {
1286 if (!i) {
1287 /* Try again */
1288 reset_state(dinfo);
1289 refresh_ring(dinfo);
1290 do_flush(dinfo);
1291 end = jiffies + (HZ * 3);
1292 i = 1;
1293 } else {
1294 WRN_MSG("ring buffer : space: %d wanted %d\n",
1295 dinfo->ring_space, n);
1296 WRN_MSG("lockup - turning off hardware "
1297 "acceleration\n");
1298 dinfo->ring_lockup = 1;
1299 break;
1300 }
1301 }
1302 udelay(1);
1303 }
1304 return i;
1305}
1306
1307static void
1308do_flush(struct intelfb_info *dinfo) {
1309 START_RING(2);
1310 OUT_RING(MI_FLUSH | MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE);
1311 OUT_RING(MI_NOOP);
1312 ADVANCE_RING();
1313}
1314
1315void
1316intelfbhw_do_sync(struct intelfb_info *dinfo)
1317{
1318#if VERBOSE > 0
1319 DBG_MSG("intelfbhw_do_sync\n");
1320#endif
1321
1322 if (!dinfo->accel)
1323 return;
1324
1325 /*
1326 * Send a flush, then wait until the ring is empty. This is what
1327 * the XFree86 driver does, and actually it doesn't seem a lot worse
1328 * than the recommended method (both have problems).
1329 */
1330 do_flush(dinfo);
1331 wait_ring(dinfo, dinfo->ring.size - RING_MIN_FREE);
1332 dinfo->ring_space = dinfo->ring.size - RING_MIN_FREE;
1333}
1334
1335static void
1336refresh_ring(struct intelfb_info *dinfo)
1337{
1338#if VERBOSE > 0
1339 DBG_MSG("refresh_ring\n");
1340#endif
1341
1342 dinfo->ring_head = (u8 __iomem *) (INREG(PRI_RING_HEAD) &
1343 RING_HEAD_MASK);
1344 dinfo->ring_tail = INREG(PRI_RING_TAIL) & RING_TAIL_MASK;
1345 if (dinfo->ring_tail + RING_MIN_FREE < (u32 __iomem)dinfo->ring_head)
1346 dinfo->ring_space = (u32 __iomem) dinfo->ring_head
1347 - (dinfo->ring_tail + RING_MIN_FREE);
1348 else
1349 dinfo->ring_space = (dinfo->ring.size +
1350 (u32 __iomem) dinfo->ring_head)
1351 - (dinfo->ring_tail + RING_MIN_FREE);
1352}
1353
1354static void
1355reset_state(struct intelfb_info *dinfo)
1356{
1357 int i;
1358 u32 tmp;
1359
1360#if VERBOSE > 0
1361 DBG_MSG("reset_state\n");
1362#endif
1363
1364 for (i = 0; i < FENCE_NUM; i++)
1365 OUTREG(FENCE + (i << 2), 0);
1366
1367 /* Flush the ring buffer if it's enabled. */
1368 tmp = INREG(PRI_RING_LENGTH);
1369 if (tmp & RING_ENABLE) {
1370#if VERBOSE > 0
1371 DBG_MSG("reset_state: ring was enabled\n");
1372#endif
1373 refresh_ring(dinfo);
1374 intelfbhw_do_sync(dinfo);
1375 DO_RING_IDLE();
1376 }
1377
1378 OUTREG(PRI_RING_LENGTH, 0);
1379 OUTREG(PRI_RING_HEAD, 0);
1380 OUTREG(PRI_RING_TAIL, 0);
1381 OUTREG(PRI_RING_START, 0);
1382}
1383
1384/* Stop the 2D engine, and turn off the ring buffer. */
1385void
1386intelfbhw_2d_stop(struct intelfb_info *dinfo)
1387{
1388#if VERBOSE > 0
1389 DBG_MSG("intelfbhw_2d_stop: accel: %d, ring_active: %d\n", dinfo->accel,
1390 dinfo->ring_active);
1391#endif
1392
1393 if (!dinfo->accel)
1394 return;
1395
1396 dinfo->ring_active = 0;
1397 reset_state(dinfo);
1398}
1399
1400/*
1401 * Enable the ring buffer, and initialise the 2D engine.
1402 * It is assumed that the graphics engine has been stopped by previously
1403 * calling intelfb_2d_stop().
1404 */
1405void
1406intelfbhw_2d_start(struct intelfb_info *dinfo)
1407{
1408#if VERBOSE > 0
1409 DBG_MSG("intelfbhw_2d_start: accel: %d, ring_active: %d\n",
1410 dinfo->accel, dinfo->ring_active);
1411#endif
1412
1413 if (!dinfo->accel)
1414 return;
1415
1416 /* Initialise the primary ring buffer. */
1417 OUTREG(PRI_RING_LENGTH, 0);
1418 OUTREG(PRI_RING_TAIL, 0);
1419 OUTREG(PRI_RING_HEAD, 0);
1420
1421 OUTREG(PRI_RING_START, dinfo->ring.physical & RING_START_MASK);
1422 OUTREG(PRI_RING_LENGTH,
1423 ((dinfo->ring.size - GTT_PAGE_SIZE) & RING_LENGTH_MASK) |
1424 RING_NO_REPORT | RING_ENABLE);
1425 refresh_ring(dinfo);
1426 dinfo->ring_active = 1;
1427}
1428
1429/* 2D fillrect (solid fill or invert) */
1430void
1431intelfbhw_do_fillrect(struct intelfb_info *dinfo, u32 x, u32 y, u32 w, u32 h,
1432 u32 color, u32 pitch, u32 bpp, u32 rop)
1433{
1434 u32 br00, br09, br13, br14, br16;
1435
1436#if VERBOSE > 0
1437 DBG_MSG("intelfbhw_do_fillrect: (%d,%d) %dx%d, c 0x%06x, p %d bpp %d, "
1438 "rop 0x%02x\n", x, y, w, h, color, pitch, bpp, rop);
1439#endif
1440
1441 br00 = COLOR_BLT_CMD;
1442 br09 = dinfo->fb_start + (y * pitch + x * (bpp / 8));
1443 br13 = (rop << ROP_SHIFT) | pitch;
1444 br14 = (h << HEIGHT_SHIFT) | ((w * (bpp / 8)) << WIDTH_SHIFT);
1445 br16 = color;
1446
1447 switch (bpp) {
1448 case 8:
1449 br13 |= COLOR_DEPTH_8;
1450 break;
1451 case 16:
1452 br13 |= COLOR_DEPTH_16;
1453 break;
1454 case 32:
1455 br13 |= COLOR_DEPTH_32;
1456 br00 |= WRITE_ALPHA | WRITE_RGB;
1457 break;
1458 }
1459
1460 START_RING(6);
1461 OUT_RING(br00);
1462 OUT_RING(br13);
1463 OUT_RING(br14);
1464 OUT_RING(br09);
1465 OUT_RING(br16);
1466 OUT_RING(MI_NOOP);
1467 ADVANCE_RING();
1468
1469#if VERBOSE > 0
1470 DBG_MSG("ring = 0x%08x, 0x%08x (%d)\n", dinfo->ring_head,
1471 dinfo->ring_tail, dinfo->ring_space);
1472#endif
1473}
1474
1475void
1476intelfbhw_do_bitblt(struct intelfb_info *dinfo, u32 curx, u32 cury,
1477 u32 dstx, u32 dsty, u32 w, u32 h, u32 pitch, u32 bpp)
1478{
1479 u32 br00, br09, br11, br12, br13, br22, br23, br26;
1480
1481#if VERBOSE > 0
1482 DBG_MSG("intelfbhw_do_bitblt: (%d,%d)->(%d,%d) %dx%d, p %d bpp %d\n",
1483 curx, cury, dstx, dsty, w, h, pitch, bpp);
1484#endif
1485
1486 br00 = XY_SRC_COPY_BLT_CMD;
1487 br09 = dinfo->fb_start;
1488 br11 = (pitch << PITCH_SHIFT);
1489 br12 = dinfo->fb_start;
1490 br13 = (SRC_ROP_GXCOPY << ROP_SHIFT) | (pitch << PITCH_SHIFT);
1491 br22 = (dstx << WIDTH_SHIFT) | (dsty << HEIGHT_SHIFT);
1492 br23 = ((dstx + w) << WIDTH_SHIFT) |
1493 ((dsty + h) << HEIGHT_SHIFT);
1494 br26 = (curx << WIDTH_SHIFT) | (cury << HEIGHT_SHIFT);
1495
1496 switch (bpp) {
1497 case 8:
1498 br13 |= COLOR_DEPTH_8;
1499 break;
1500 case 16:
1501 br13 |= COLOR_DEPTH_16;
1502 break;
1503 case 32:
1504 br13 |= COLOR_DEPTH_32;
1505 br00 |= WRITE_ALPHA | WRITE_RGB;
1506 break;
1507 }
1508
1509 START_RING(8);
1510 OUT_RING(br00);
1511 OUT_RING(br13);
1512 OUT_RING(br22);
1513 OUT_RING(br23);
1514 OUT_RING(br09);
1515 OUT_RING(br26);
1516 OUT_RING(br11);
1517 OUT_RING(br12);
1518 ADVANCE_RING();
1519}
1520
1521int
1522intelfbhw_do_drawglyph(struct intelfb_info *dinfo, u32 fg, u32 bg, u32 w,
1523 u32 h, const u8* cdat, u32 x, u32 y, u32 pitch, u32 bpp)
1524{
1525 int nbytes, ndwords, pad, tmp;
1526 u32 br00, br09, br13, br18, br19, br22, br23;
1527 int dat, ix, iy, iw;
1528 int i, j;
1529
1530#if VERBOSE > 0
1531 DBG_MSG("intelfbhw_do_drawglyph: (%d,%d) %dx%d\n", x, y, w, h);
1532#endif
1533
1534 /* size in bytes of a padded scanline */
1535 nbytes = ROUND_UP_TO(w, 16) / 8;
1536
1537 /* Total bytes of padded scanline data to write out. */
1538 nbytes = nbytes * h;
1539
1540 /*
1541 * Check if the glyph data exceeds the immediate mode limit.
1542 * It would take a large font (1K pixels) to hit this limit.
1543 */
1544 if (nbytes > MAX_MONO_IMM_SIZE)
1545 return 0;
1546
1547 /* Src data is packaged a dword (32-bit) at a time. */
1548 ndwords = ROUND_UP_TO(nbytes, 4) / 4;
1549
1550 /*
1551 * Ring has to be padded to a quad word. But because the command starts
1552 with 7 bytes, pad only if there is an even number of ndwords
1553 */
1554 pad = !(ndwords % 2);
1555
1556 tmp = (XY_MONO_SRC_IMM_BLT_CMD & DW_LENGTH_MASK) + ndwords;
1557 br00 = (XY_MONO_SRC_IMM_BLT_CMD & ~DW_LENGTH_MASK) | tmp;
1558 br09 = dinfo->fb_start;
1559 br13 = (SRC_ROP_GXCOPY << ROP_SHIFT) | (pitch << PITCH_SHIFT);
1560 br18 = bg;
1561 br19 = fg;
1562 br22 = (x << WIDTH_SHIFT) | (y << HEIGHT_SHIFT);
1563 br23 = ((x + w) << WIDTH_SHIFT) | ((y + h) << HEIGHT_SHIFT);
1564
1565 switch (bpp) {
1566 case 8:
1567 br13 |= COLOR_DEPTH_8;
1568 break;
1569 case 16:
1570 br13 |= COLOR_DEPTH_16;
1571 break;
1572 case 32:
1573 br13 |= COLOR_DEPTH_32;
1574 br00 |= WRITE_ALPHA | WRITE_RGB;
1575 break;
1576 }
1577
1578 START_RING(8 + ndwords);
1579 OUT_RING(br00);
1580 OUT_RING(br13);
1581 OUT_RING(br22);
1582 OUT_RING(br23);
1583 OUT_RING(br09);
1584 OUT_RING(br18);
1585 OUT_RING(br19);
1586 ix = iy = 0;
1587 iw = ROUND_UP_TO(w, 8) / 8;
1588 while (ndwords--) {
1589 dat = 0;
1590 for (j = 0; j < 2; ++j) {
1591 for (i = 0; i < 2; ++i) {
1592 if (ix != iw || i == 0)
1593 dat |= cdat[iy*iw + ix++] << (i+j*2)*8;
1594 }
1595 if (ix == iw && iy != (h-1)) {
1596 ix = 0;
1597 ++iy;
1598 }
1599 }
1600 OUT_RING(dat);
1601 }
1602 if (pad)
1603 OUT_RING(MI_NOOP);
1604 ADVANCE_RING();
1605
1606 return 1;
1607}
1608
1609/* HW cursor functions. */
1610void
1611intelfbhw_cursor_init(struct intelfb_info *dinfo)
1612{
1613 u32 tmp;
1614
1615#if VERBOSE > 0
1616 DBG_MSG("intelfbhw_cursor_init\n");
1617#endif
1618
1619 if (dinfo->mobile) {
1620 if (!dinfo->cursor.physical)
1621 return;
1622 tmp = INREG(CURSOR_A_CONTROL);
1623 tmp &= ~(CURSOR_MODE_MASK | CURSOR_MOBILE_GAMMA_ENABLE |
1624 CURSOR_MEM_TYPE_LOCAL |
1625 (1 << CURSOR_PIPE_SELECT_SHIFT));
1626 tmp |= CURSOR_MODE_DISABLE;
1627 OUTREG(CURSOR_A_CONTROL, tmp);
1628 OUTREG(CURSOR_A_BASEADDR, dinfo->cursor.physical);
1629 } else {
1630 tmp = INREG(CURSOR_CONTROL);
1631 tmp &= ~(CURSOR_FORMAT_MASK | CURSOR_GAMMA_ENABLE |
1632 CURSOR_ENABLE | CURSOR_STRIDE_MASK);
1633 tmp = CURSOR_FORMAT_3C;
1634 OUTREG(CURSOR_CONTROL, tmp);
1635 OUTREG(CURSOR_A_BASEADDR, dinfo->cursor.offset << 12);
1636 tmp = (64 << CURSOR_SIZE_H_SHIFT) |
1637 (64 << CURSOR_SIZE_V_SHIFT);
1638 OUTREG(CURSOR_SIZE, tmp);
1639 }
1640}
1641
1642void
1643intelfbhw_cursor_hide(struct intelfb_info *dinfo)
1644{
1645 u32 tmp;
1646
1647#if VERBOSE > 0
1648 DBG_MSG("intelfbhw_cursor_hide\n");
1649#endif
1650
1651 dinfo->cursor_on = 0;
1652 if (dinfo->mobile) {
1653 if (!dinfo->cursor.physical)
1654 return;
1655 tmp = INREG(CURSOR_A_CONTROL);
1656 tmp &= ~CURSOR_MODE_MASK;
1657 tmp |= CURSOR_MODE_DISABLE;
1658 OUTREG(CURSOR_A_CONTROL, tmp);
1659 /* Flush changes */
1660 OUTREG(CURSOR_A_BASEADDR, dinfo->cursor.physical);
1661 } else {
1662 tmp = INREG(CURSOR_CONTROL);
1663 tmp &= ~CURSOR_ENABLE;
1664 OUTREG(CURSOR_CONTROL, tmp);
1665 }
1666}
1667
1668void
1669intelfbhw_cursor_show(struct intelfb_info *dinfo)
1670{
1671 u32 tmp;
1672
1673#if VERBOSE > 0
1674 DBG_MSG("intelfbhw_cursor_show\n");
1675#endif
1676
1677 dinfo->cursor_on = 1;
1678
1679 if (dinfo->cursor_blanked)
1680 return;
1681
1682 if (dinfo->mobile) {
1683 if (!dinfo->cursor.physical)
1684 return;
1685 tmp = INREG(CURSOR_A_CONTROL);
1686 tmp &= ~CURSOR_MODE_MASK;
1687 tmp |= CURSOR_MODE_64_4C_AX;
1688 OUTREG(CURSOR_A_CONTROL, tmp);
1689 /* Flush changes */
1690 OUTREG(CURSOR_A_BASEADDR, dinfo->cursor.physical);
1691 } else {
1692 tmp = INREG(CURSOR_CONTROL);
1693 tmp |= CURSOR_ENABLE;
1694 OUTREG(CURSOR_CONTROL, tmp);
1695 }
1696}
1697
1698void
1699intelfbhw_cursor_setpos(struct intelfb_info *dinfo, int x, int y)
1700{
1701 u32 tmp;
1702
1703#if VERBOSE > 0
1704 DBG_MSG("intelfbhw_cursor_setpos: (%d, %d)\n", x, y);
1705#endif
1706
1707 /*
1708 * Sets the position. The coordinates are assumed to already
1709 * have any offset adjusted. Assume that the cursor is never
1710 * completely off-screen, and that x, y are always >= 0.
1711 */
1712
1713 tmp = ((x & CURSOR_POS_MASK) << CURSOR_X_SHIFT) |
1714 ((y & CURSOR_POS_MASK) << CURSOR_Y_SHIFT);
1715 OUTREG(CURSOR_A_POSITION, tmp);
1716}
1717
1718void
1719intelfbhw_cursor_setcolor(struct intelfb_info *dinfo, u32 bg, u32 fg)
1720{
1721#if VERBOSE > 0
1722 DBG_MSG("intelfbhw_cursor_setcolor\n");
1723#endif
1724
1725 OUTREG(CURSOR_A_PALETTE0, bg & CURSOR_PALETTE_MASK);
1726 OUTREG(CURSOR_A_PALETTE1, fg & CURSOR_PALETTE_MASK);
1727 OUTREG(CURSOR_A_PALETTE2, fg & CURSOR_PALETTE_MASK);
1728 OUTREG(CURSOR_A_PALETTE3, bg & CURSOR_PALETTE_MASK);
1729}
1730
1731void
1732intelfbhw_cursor_load(struct intelfb_info *dinfo, int width, int height,
1733 u8 *data)
1734{
1735 u8 __iomem *addr = (u8 __iomem *)dinfo->cursor.virtual;
1736 int i, j, w = width / 8;
1737 int mod = width % 8, t_mask, d_mask;
1738
1739#if VERBOSE > 0
1740 DBG_MSG("intelfbhw_cursor_load\n");
1741#endif
1742
1743 if (!dinfo->cursor.virtual)
1744 return;
1745
1746 t_mask = 0xff >> mod;
1747 d_mask = ~(0xff >> mod);
1748 for (i = height; i--; ) {
1749 for (j = 0; j < w; j++) {
1750 writeb(0x00, addr + j);
1751 writeb(*(data++), addr + j+8);
1752 }
1753 if (mod) {
1754 writeb(t_mask, addr + j);
1755 writeb(*(data++) & d_mask, addr + j+8);
1756 }
1757 addr += 16;
1758 }
1759}
1760
1761void
1762intelfbhw_cursor_reset(struct intelfb_info *dinfo) {
1763 u8 __iomem *addr = (u8 __iomem *)dinfo->cursor.virtual;
1764 int i, j;
1765
1766#if VERBOSE > 0
1767 DBG_MSG("intelfbhw_cursor_reset\n");
1768#endif
1769
1770 if (!dinfo->cursor.virtual)
1771 return;
1772
1773 for (i = 64; i--; ) {
1774 for (j = 0; j < 8; j++) {
1775 writeb(0xff, addr + j+0);
1776 writeb(0x00, addr + j+8);
1777 }
1778 addr += 16;
1779 }
1780}
diff --git a/drivers/video/intelfb/intelfbhw.h b/drivers/video/intelfb/intelfbhw.h
new file mode 100644
index 00000000000..ba1920159f5
--- /dev/null
+++ b/drivers/video/intelfb/intelfbhw.h
@@ -0,0 +1,570 @@
1#ifndef _INTELFBHW_H
2#define _INTELFBHW_H
3
4/* $DHD: intelfb/intelfbhw.h,v 1.5 2003/06/27 15:06:25 dawes Exp $ */
5
6
7/*** HW-specific data ***/
8
9/* Information about the 852GM/855GM variants */
10#define INTEL_85X_CAPID 0x44
11#define INTEL_85X_VARIANT_MASK 0x7
12#define INTEL_85X_VARIANT_SHIFT 5
13#define INTEL_VAR_855GME 0x0
14#define INTEL_VAR_855GM 0x4
15#define INTEL_VAR_852GME 0x2
16#define INTEL_VAR_852GM 0x5
17
18/* Information about DVO/LVDS Ports */
19#define DVOA_PORT 0x1
20#define DVOB_PORT 0x2
21#define DVOC_PORT 0x4
22#define LVDS_PORT 0x8
23
24/*
25 * The Bridge device's PCI config space has information about the
26 * fb aperture size and the amount of pre-reserved memory.
27 */
28#define INTEL_GMCH_CTRL 0x52
29#define INTEL_GMCH_ENABLED 0x4
30#define INTEL_GMCH_MEM_MASK 0x1
31#define INTEL_GMCH_MEM_64M 0x1
32#define INTEL_GMCH_MEM_128M 0
33
34#define INTEL_830_GMCH_GMS_MASK (0x7 << 4)
35#define INTEL_830_GMCH_GMS_DISABLED (0x0 << 4)
36#define INTEL_830_GMCH_GMS_LOCAL (0x1 << 4)
37#define INTEL_830_GMCH_GMS_STOLEN_512 (0x2 << 4)
38#define INTEL_830_GMCH_GMS_STOLEN_1024 (0x3 << 4)
39#define INTEL_830_GMCH_GMS_STOLEN_8192 (0x4 << 4)
40
41#define INTEL_855_GMCH_GMS_MASK (0x7 << 4)
42#define INTEL_855_GMCH_GMS_DISABLED (0x0 << 4)
43#define INTEL_855_GMCH_GMS_STOLEN_1M (0x1 << 4)
44#define INTEL_855_GMCH_GMS_STOLEN_4M (0x2 << 4)
45#define INTEL_855_GMCH_GMS_STOLEN_8M (0x3 << 4)
46#define INTEL_855_GMCH_GMS_STOLEN_16M (0x4 << 4)
47#define INTEL_855_GMCH_GMS_STOLEN_32M (0x5 << 4)
48
49#define INTEL_915G_GMCH_GMS_STOLEN_48M (0x6 << 4)
50#define INTEL_915G_GMCH_GMS_STOLEN_64M (0x7 << 4)
51
52/* HW registers */
53
54/* Fence registers */
55#define FENCE 0x2000
56#define FENCE_NUM 8
57
58/* Primary ring buffer */
59#define PRI_RING_TAIL 0x2030
60#define RING_TAIL_MASK 0x001ffff8
61#define RING_INUSE 0x1
62
63#define PRI_RING_HEAD 0x2034
64#define RING_HEAD_WRAP_MASK 0x7ff
65#define RING_HEAD_WRAP_SHIFT 21
66#define RING_HEAD_MASK 0x001ffffc
67
68#define PRI_RING_START 0x2038
69#define RING_START_MASK 0xfffff000
70
71#define PRI_RING_LENGTH 0x203c
72#define RING_LENGTH_MASK 0x001ff000
73#define RING_REPORT_MASK (0x3 << 1)
74#define RING_NO_REPORT (0x0 << 1)
75#define RING_REPORT_64K (0x1 << 1)
76#define RING_REPORT_4K (0x2 << 1)
77#define RING_REPORT_128K (0x3 << 1)
78#define RING_ENABLE 0x1
79
80/*
81 * Tail can't wrap to any closer than RING_MIN_FREE bytes of the head,
82 * and the last RING_MIN_FREE bytes need to be padded with MI_NOOP
83 */
84#define RING_MIN_FREE 64
85
86#define IPEHR 0x2088
87
88#define INSTDONE 0x2090
89#define PRI_RING_EMPTY 1
90
91#define INSTPM 0x20c0
92#define SYNC_FLUSH_ENABLE (1 << 5)
93
94#define INSTPS 0x20c4
95
96#define MEM_MODE 0x20cc
97
98#define MASK_SHIFT 16
99
100#define FW_BLC_0 0x20d8
101#define FW_DISPA_WM_SHIFT 0
102#define FW_DISPA_WM_MASK 0x3f
103#define FW_DISPA_BL_SHIFT 8
104#define FW_DISPA_BL_MASK 0xf
105#define FW_DISPB_WM_SHIFT 16
106#define FW_DISPB_WM_MASK 0x1f
107#define FW_DISPB_BL_SHIFT 24
108#define FW_DISPB_BL_MASK 0x7
109
110#define FW_BLC_1 0x20dc
111#define FW_DISPC_WM_SHIFT 0
112#define FW_DISPC_WM_MASK 0x1f
113#define FW_DISPC_BL_SHIFT 8
114#define FW_DISPC_BL_MASK 0x7
115
116
117/* PLL registers */
118#define VGA0_DIVISOR 0x06000
119#define VGA1_DIVISOR 0x06004
120#define VGAPD 0x06010
121#define VGAPD_0_P1_SHIFT 0
122#define VGAPD_0_P1_FORCE_DIV2 (1 << 5)
123#define VGAPD_0_P2_SHIFT 7
124#define VGAPD_1_P1_SHIFT 8
125#define VGAPD_1_P1_FORCE_DIV2 (1 << 13)
126#define VGAPD_1_P2_SHIFT 15
127
128#define DPLL_A 0x06014
129#define DPLL_B 0x06018
130#define DPLL_VCO_ENABLE (1 << 31)
131#define DPLL_2X_CLOCK_ENABLE (1 << 30)
132#define DPLL_SYNCLOCK_ENABLE (1 << 29)
133#define DPLL_VGA_MODE_DISABLE (1 << 28)
134#define DPLL_P2_MASK 1
135#define DPLL_P2_SHIFT 23
136#define DPLL_P1_FORCE_DIV2 (1 << 21)
137#define DPLL_P1_MASK 0x1f
138#define DPLL_P1_SHIFT 16
139#define DPLL_REFERENCE_SELECT_MASK (0x3 << 13)
140#define DPLL_REFERENCE_DEFAULT (0x0 << 13)
141#define DPLL_REFERENCE_TVCLK (0x2 << 13)
142#define DPLL_RATE_SELECT_MASK (1 << 8)
143#define DPLL_RATE_SELECT_FP0 (0 << 8)
144#define DPLL_RATE_SELECT_FP1 (1 << 8)
145
146#define FPA0 0x06040
147#define FPA1 0x06044
148#define FPB0 0x06048
149#define FPB1 0x0604c
150#define FP_DIVISOR_MASK 0x3f
151#define FP_N_DIVISOR_SHIFT 16
152#define FP_M1_DIVISOR_SHIFT 8
153#define FP_M2_DIVISOR_SHIFT 0
154
155/* PLL parameters (these are for 852GM/855GM/865G, check earlier chips). */
156/* Clock values are in units of kHz */
157#define PLL_REFCLK 48000
158#define MIN_VCO_FREQ 930000
159#define MAX_VCO_FREQ 1400000
160#define MIN_CLOCK 25000
161#define MAX_CLOCK 350000
162#define P_TRANSITION_CLOCK 165000
163#define MIN_M 108
164#define MAX_M 140
165#define MIN_M1 18
166#define MAX_M1 26
167#define MIN_M2 6
168#define MAX_M2 16
169#define MIN_P 4
170#define MAX_P 128
171#define MIN_P1 0
172#define MAX_P1 31
173#define MIN_N 3
174#define MAX_N 16
175
176#define CALC_VCLOCK(m1, m2, n, p1, p2) \
177 ((PLL_REFCLK * (5 * ((m1) + 2) + ((m2) + 2)) / ((n) + 2)) / \
178 (((p1) + 2) * (1 << (p2 + 1))))
179
180#define CALC_VCLOCK3(m, n, p) ((PLL_REFCLK * (m) / (n)) / (p))
181
182/* Two pipes */
183#define PIPE_A 0
184#define PIPE_B 1
185#define PIPE_MASK 1
186
187/* palette registers */
188#define PALETTE_A 0x0a000
189#define PALETTE_B 0x0a800
190#ifndef PALETTE_8_ENTRIES
191#define PALETTE_8_ENTRIES 256
192#endif
193#define PALETTE_8_SIZE (PALETTE_8_ENTRIES * 4)
194#define PALETTE_10_ENTRIES 128
195#define PALETTE_10_SIZE (PALETTE_10_ENTRIES * 8)
196#define PALETTE_8_MASK 0xff
197#define PALETTE_8_RED_SHIFT 16
198#define PALETTE_8_GREEN_SHIFT 8
199#define PALETTE_8_BLUE_SHIFT 0
200
201/* CRTC registers */
202#define HTOTAL_A 0x60000
203#define HBLANK_A 0x60004
204#define HSYNC_A 0x60008
205#define VTOTAL_A 0x6000c
206#define VBLANK_A 0x60010
207#define VSYNC_A 0x60014
208#define SRC_SIZE_A 0x6001c
209#define BCLRPAT_A 0x60020
210
211#define HTOTAL_B 0x61000
212#define HBLANK_B 0x61004
213#define HSYNC_B 0x61008
214#define VTOTAL_B 0x6100c
215#define VBLANK_B 0x61010
216#define VSYNC_B 0x61014
217#define SRC_SIZE_B 0x6101c
218#define BCLRPAT_B 0x61020
219
220#define HTOTAL_MASK 0xfff
221#define HTOTAL_SHIFT 16
222#define HACTIVE_MASK 0x7ff
223#define HACTIVE_SHIFT 0
224#define HBLANKEND_MASK 0xfff
225#define HBLANKEND_SHIFT 16
226#define HBLANKSTART_MASK 0xfff
227#define HBLANKSTART_SHIFT 0
228#define HSYNCEND_MASK 0xfff
229#define HSYNCEND_SHIFT 16
230#define HSYNCSTART_MASK 0xfff
231#define HSYNCSTART_SHIFT 0
232#define VTOTAL_MASK 0xfff
233#define VTOTAL_SHIFT 16
234#define VACTIVE_MASK 0x7ff
235#define VACTIVE_SHIFT 0
236#define VBLANKEND_MASK 0xfff
237#define VBLANKEND_SHIFT 16
238#define VBLANKSTART_MASK 0xfff
239#define VBLANKSTART_SHIFT 0
240#define VSYNCEND_MASK 0xfff
241#define VSYNCEND_SHIFT 16
242#define VSYNCSTART_MASK 0xfff
243#define VSYNCSTART_SHIFT 0
244#define SRC_SIZE_HORIZ_MASK 0x7ff
245#define SRC_SIZE_HORIZ_SHIFT 16
246#define SRC_SIZE_VERT_MASK 0x7ff
247#define SRC_SIZE_VERT_SHIFT 0
248
249#define ADPA 0x61100
250#define ADPA_DAC_ENABLE (1 << 31)
251#define ADPA_DAC_DISABLE 0
252#define ADPA_PIPE_SELECT_SHIFT 30
253#define ADPA_USE_VGA_HVPOLARITY (1 << 15)
254#define ADPA_SETS_HVPOLARITY 0
255#define ADPA_DPMS_CONTROL_MASK (0x3 << 10)
256#define ADPA_DPMS_D0 (0x0 << 10)
257#define ADPA_DPMS_D2 (0x1 << 10)
258#define ADPA_DPMS_D1 (0x2 << 10)
259#define ADPA_DPMS_D3 (0x3 << 10)
260#define ADPA_VSYNC_ACTIVE_SHIFT 4
261#define ADPA_HSYNC_ACTIVE_SHIFT 3
262#define ADPA_SYNC_ACTIVE_MASK 1
263#define ADPA_SYNC_ACTIVE_HIGH 1
264#define ADPA_SYNC_ACTIVE_LOW 0
265
266#define DVOA 0x61120
267#define DVOB 0x61140
268#define DVOC 0x61160
269#define LVDS 0x61180
270#define PORT_ENABLE (1 << 31)
271#define PORT_PIPE_SELECT_SHIFT 30
272#define PORT_TV_FLAGS_MASK 0xFF
273#define PORT_TV_FLAGS 0xC4 // ripped from my BIOS
274 // to understand and correct
275
276#define DVOA_SRCDIM 0x61124
277#define DVOB_SRCDIM 0x61144
278#define DVOC_SRCDIM 0x61164
279
280#define PIPEACONF 0x70008
281#define PIPEBCONF 0x71008
282#define PIPECONF_ENABLE (1 << 31)
283#define PIPECONF_DISABLE 0
284#define PIPECONF_DOUBLE_WIDE (1 << 30)
285#define PIPECONF_SINGLE_WIDE 0
286#define PIPECONF_LOCKED (1 << 25)
287#define PIPECONF_UNLOCKED 0
288#define PIPECONF_GAMMA (1 << 24)
289#define PIPECONF_PALETTE 0
290
291#define DISPARB 0x70030
292#define DISPARB_AEND_MASK 0x1ff
293#define DISPARB_AEND_SHIFT 0
294#define DISPARB_BEND_MASK 0x3ff
295#define DISPARB_BEND_SHIFT 9
296
297/* Desktop HW cursor */
298#define CURSOR_CONTROL 0x70080
299#define CURSOR_ENABLE (1 << 31)
300#define CURSOR_GAMMA_ENABLE (1 << 30)
301#define CURSOR_STRIDE_MASK (0x3 << 28)
302#define CURSOR_STRIDE_256 (0x0 << 28)
303#define CURSOR_STRIDE_512 (0x1 << 28)
304#define CURSOR_STRIDE_1K (0x2 << 28)
305#define CURSOR_STRIDE_2K (0x3 << 28)
306#define CURSOR_FORMAT_MASK (0x7 << 24)
307#define CURSOR_FORMAT_2C (0x0 << 24)
308#define CURSOR_FORMAT_3C (0x1 << 24)
309#define CURSOR_FORMAT_4C (0x2 << 24)
310#define CURSOR_FORMAT_ARGB (0x4 << 24)
311#define CURSOR_FORMAT_XRGB (0x5 << 24)
312
313/* Mobile HW cursor (and i810) */
314#define CURSOR_A_CONTROL CURSOR_CONTROL
315#define CURSOR_B_CONTROL 0x700c0
316#define CURSOR_MODE_MASK 0x27
317#define CURSOR_MODE_DISABLE 0
318#define CURSOR_MODE_64_3C 0x04
319#define CURSOR_MODE_64_4C_AX 0x05
320#define CURSOR_MODE_64_4C 0x06
321#define CURSOR_MODE_64_32B_AX 0x07
322#define CURSOR_MODE_64_ARGB_AX 0x27
323#define CURSOR_PIPE_SELECT_SHIFT 28
324#define CURSOR_MOBILE_GAMMA_ENABLE (1 << 26)
325#define CURSOR_MEM_TYPE_LOCAL (1 << 25)
326
327/* All platforms (desktop has no pipe B) */
328#define CURSOR_A_BASEADDR 0x70084
329#define CURSOR_B_BASEADDR 0x700c4
330#define CURSOR_BASE_MASK 0xffffff00
331
332#define CURSOR_A_POSITION 0x70088
333#define CURSOR_B_POSITION 0x700c8
334#define CURSOR_POS_SIGN (1 << 15)
335#define CURSOR_POS_MASK 0x7ff
336#define CURSOR_X_SHIFT 0
337#define CURSOR_Y_SHIFT 16
338
339#define CURSOR_A_PALETTE0 0x70090
340#define CURSOR_A_PALETTE1 0x70094
341#define CURSOR_A_PALETTE2 0x70098
342#define CURSOR_A_PALETTE3 0x7009c
343#define CURSOR_B_PALETTE0 0x700d0
344#define CURSOR_B_PALETTE1 0x700d4
345#define CURSOR_B_PALETTE2 0x700d8
346#define CURSOR_B_PALETTE3 0x700dc
347#define CURSOR_COLOR_MASK 0xff
348#define CURSOR_RED_SHIFT 16
349#define CURSOR_GREEN_SHIFT 8
350#define CURSOR_BLUE_SHIFT 0
351#define CURSOR_PALETTE_MASK 0xffffff
352
353/* Desktop only */
354#define CURSOR_SIZE 0x700a0
355#define CURSOR_SIZE_MASK 0x3ff
356#define CURSOR_SIZE_H_SHIFT 0
357#define CURSOR_SIZE_V_SHIFT 12
358
359#define DSPACNTR 0x70180
360#define DSPBCNTR 0x71180
361#define DISPPLANE_PLANE_ENABLE (1 << 31)
362#define DISPPLANE_PLANE_DISABLE 0
363#define DISPPLANE_GAMMA_ENABLE (1<<30)
364#define DISPPLANE_GAMMA_DISABLE 0
365#define DISPPLANE_PIXFORMAT_MASK (0xf<<26)
366#define DISPPLANE_8BPP (0x2<<26)
367#define DISPPLANE_15_16BPP (0x4<<26)
368#define DISPPLANE_16BPP (0x5<<26)
369#define DISPPLANE_32BPP_NO_ALPHA (0x6<<26)
370#define DISPPLANE_32BPP (0x7<<26)
371#define DISPPLANE_STEREO_ENABLE (1<<25)
372#define DISPPLANE_STEREO_DISABLE 0
373#define DISPPLANE_SEL_PIPE_SHIFT 24
374#define DISPPLANE_SRC_KEY_ENABLE (1<<22)
375#define DISPPLANE_SRC_KEY_DISABLE 0
376#define DISPPLANE_LINE_DOUBLE (1<<20)
377#define DISPPLANE_NO_LINE_DOUBLE 0
378#define DISPPLANE_STEREO_POLARITY_FIRST 0
379#define DISPPLANE_STEREO_POLARITY_SECOND (1<<18)
380/* plane B only */
381#define DISPPLANE_ALPHA_TRANS_ENABLE (1<<15)
382#define DISPPLANE_ALPHA_TRANS_DISABLE 0
383#define DISPPLANE_SPRITE_ABOVE_DISPLAYA 0
384#define DISPPLANE_SPRITE_ABOVE_OVERLAY 1
385
386#define DSPABASE 0x70184
387#define DSPASTRIDE 0x70188
388
389#define DSPBBASE 0x71184
390#define DSPBSTRIDE 0x71188
391
392#define VGACNTRL 0x71400
393#define VGA_DISABLE (1 << 31)
394#define VGA_ENABLE 0
395#define VGA_PIPE_SELECT_SHIFT 29
396#define VGA_PALETTE_READ_SELECT 23
397#define VGA_PALETTE_A_WRITE_DISABLE (1 << 22)
398#define VGA_PALETTE_B_WRITE_DISABLE (1 << 21)
399#define VGA_LEGACY_PALETTE (1 << 20)
400#define VGA_6BIT_DAC 0
401#define VGA_8BIT_DAC (1 << 20)
402
403#define ADD_ID 0x71408
404#define ADD_ID_MASK 0xff
405
406/* BIOS scratch area registers (830M and 845G). */
407#define SWF0 0x71410
408#define SWF1 0x71414
409#define SWF2 0x71418
410#define SWF3 0x7141c
411#define SWF4 0x71420
412#define SWF5 0x71424
413#define SWF6 0x71428
414
415/* BIOS scratch area registers (852GM, 855GM, 865G). */
416#define SWF00 0x70410
417#define SWF01 0x70414
418#define SWF02 0x70418
419#define SWF03 0x7041c
420#define SWF04 0x70420
421#define SWF05 0x70424
422#define SWF06 0x70428
423
424#define SWF10 SWF0
425#define SWF11 SWF1
426#define SWF12 SWF2
427#define SWF13 SWF3
428#define SWF14 SWF4
429#define SWF15 SWF5
430#define SWF16 SWF6
431
432#define SWF30 0x72414
433#define SWF31 0x72418
434#define SWF32 0x7241c
435
436/* Memory Commands */
437#define MI_NOOP (0x00 << 23)
438#define MI_NOOP_WRITE_ID (1 << 22)
439#define MI_NOOP_ID_MASK ((1 << 22) - 1)
440
441#define MI_FLUSH (0x04 << 23)
442#define MI_WRITE_DIRTY_STATE (1 << 4)
443#define MI_END_SCENE (1 << 3)
444#define MI_INHIBIT_RENDER_CACHE_FLUSH (1 << 2)
445#define MI_INVALIDATE_MAP_CACHE (1 << 0)
446
447#define MI_STORE_DWORD_IMM ((0x20 << 23) | 1)
448
449/* 2D Commands */
450#define COLOR_BLT_CMD ((2 << 29) | (0x40 << 22) | 3)
451#define XY_COLOR_BLT_CMD ((2 << 29) | (0x50 << 22) | 4)
452#define XY_SETUP_CLIP_BLT_CMD ((2 << 29) | (0x03 << 22) | 1)
453#define XY_SRC_COPY_BLT_CMD ((2 << 29) | (0x53 << 22) | 6)
454#define SRC_COPY_BLT_CMD ((2 << 29) | (0x43 << 22) | 4)
455#define XY_MONO_PAT_BLT_CMD ((2 << 29) | (0x52 << 22) | 7)
456#define XY_MONO_SRC_BLT_CMD ((2 << 29) | (0x54 << 22) | 6)
457#define XY_MONO_SRC_IMM_BLT_CMD ((2 << 29) | (0x71 << 22) | 5)
458#define TXT_IMM_BLT_CMD ((2 << 29) | (0x30 << 22) | 2)
459#define SETUP_BLT_CMD ((2 << 29) | (0x00 << 22) | 6)
460
461#define DW_LENGTH_MASK 0xff
462
463#define WRITE_ALPHA (1 << 21)
464#define WRITE_RGB (1 << 20)
465#define VERT_SEED (3 << 8)
466#define HORIZ_SEED (3 << 12)
467
468#define COLOR_DEPTH_8 (0 << 24)
469#define COLOR_DEPTH_16 (1 << 24)
470#define COLOR_DEPTH_32 (3 << 24)
471
472#define SRC_ROP_GXCOPY 0xcc
473#define SRC_ROP_GXXOR 0x66
474
475#define PAT_ROP_GXCOPY 0xf0
476#define PAT_ROP_GXXOR 0x5a
477
478#define PITCH_SHIFT 0
479#define ROP_SHIFT 16
480#define WIDTH_SHIFT 0
481#define HEIGHT_SHIFT 16
482
483/* in bytes */
484#define MAX_MONO_IMM_SIZE 128
485
486
487/*** Macros ***/
488
489/* I/O macros */
490#define INREG8(addr) readb((u8 __iomem *)(dinfo->mmio_base + (addr)))
491#define INREG(addr) readl((u32 __iomem *)(dinfo->mmio_base + (addr)))
492#define OUTREG8(addr, val) writeb((val),(u8 __iomem *)(dinfo->mmio_base + \
493 (addr)))
494#define OUTREG(addr, val) writel((val),(u32 __iomem *)(dinfo->mmio_base + \
495 (addr)))
496
497/* Ring buffer macros */
498#define OUT_RING(n) do { \
499 writel((n), (u32 __iomem *)(dinfo->ring.virtual + dinfo->ring_tail));\
500 dinfo->ring_tail += 4; \
501 dinfo->ring_tail &= dinfo->ring_tail_mask; \
502} while (0)
503
504#define START_RING(n) do { \
505 if (dinfo->ring_space < (n) * 4) \
506 wait_ring(dinfo,(n) * 4); \
507 dinfo->ring_space -= (n) * 4; \
508} while (0)
509
510#define ADVANCE_RING() do { \
511 OUTREG(PRI_RING_TAIL, dinfo->ring_tail); \
512} while (0)
513
514#define DO_RING_IDLE() do { \
515 u32 head, tail; \
516 do { \
517 head = INREG(PRI_RING_HEAD) & RING_HEAD_MASK; \
518 tail = INREG(PRI_RING_TAIL) & RING_TAIL_MASK; \
519 udelay(10); \
520 } while (head != tail); \
521} while (0)
522
523
524/* function protoypes */
525extern int intelfbhw_get_chipset(struct pci_dev *pdev, const char **name,
526 int *chipset, int *mobile);
527extern int intelfbhw_get_memory(struct pci_dev *pdev, int *aperture_size,
528 int *stolen_size);
529extern int intelfbhw_check_non_crt(struct intelfb_info *dinfo);
530extern const char *intelfbhw_dvo_to_string(int dvo);
531extern int intelfbhw_validate_mode(struct intelfb_info *dinfo,
532 struct fb_var_screeninfo *var);
533extern int intelfbhw_pan_display(struct fb_var_screeninfo *var,
534 struct fb_info *info);
535extern void intelfbhw_do_blank(int blank, struct fb_info *info);
536extern void intelfbhw_setcolreg(struct intelfb_info *dinfo, unsigned regno,
537 unsigned red, unsigned green, unsigned blue,
538 unsigned transp);
539extern int intelfbhw_read_hw_state(struct intelfb_info *dinfo,
540 struct intelfb_hwstate *hw, int flag);
541extern void intelfbhw_print_hw_state(struct intelfb_info *dinfo,
542 struct intelfb_hwstate *hw);
543extern int intelfbhw_mode_to_hw(struct intelfb_info *dinfo,
544 struct intelfb_hwstate *hw,
545 struct fb_var_screeninfo *var);
546extern int intelfbhw_program_mode(struct intelfb_info *dinfo,
547 const struct intelfb_hwstate *hw, int blank);
548extern void intelfbhw_do_sync(struct intelfb_info *dinfo);
549extern void intelfbhw_2d_stop(struct intelfb_info *dinfo);
550extern void intelfbhw_2d_start(struct intelfb_info *dinfo);
551extern void intelfbhw_do_fillrect(struct intelfb_info *dinfo, u32 x, u32 y,
552 u32 w, u32 h, u32 color, u32 pitch, u32 bpp,
553 u32 rop);
554extern void intelfbhw_do_bitblt(struct intelfb_info *dinfo, u32 curx, u32 cury,
555 u32 dstx, u32 dsty, u32 w, u32 h, u32 pitch,
556 u32 bpp);
557extern int intelfbhw_do_drawglyph(struct intelfb_info *dinfo, u32 fg, u32 bg,
558 u32 w, u32 h, const u8* cdat, u32 x, u32 y,
559 u32 pitch, u32 bpp);
560extern void intelfbhw_cursor_init(struct intelfb_info *dinfo);
561extern void intelfbhw_cursor_hide(struct intelfb_info *dinfo);
562extern void intelfbhw_cursor_show(struct intelfb_info *dinfo);
563extern void intelfbhw_cursor_setpos(struct intelfb_info *dinfo, int x, int y);
564extern void intelfbhw_cursor_setcolor(struct intelfb_info *dinfo, u32 bg,
565 u32 fg);
566extern void intelfbhw_cursor_load(struct intelfb_info *dinfo, int width,
567 int height, u8 *data);
568extern void intelfbhw_cursor_reset(struct intelfb_info *dinfo);
569
570#endif /* _INTELFBHW_H */